精华内容
下载资源
问答
  • 年初的时候就已经适配安卓9.0,但由于业务需求一直没有使用上,前段时间发布了,结果有用户反馈在安卓9.0的手机上更新下载App发生了闪退。这个时候发现9.0对权限、加密和Apache HTTP client发生了相关变化。 一、...

    年初的时候就已经适配了安卓9.0,但由于业务需求一直没有使用上,前段时间发布了,结果有用户反馈在安卓9.0的手机上更新下载App发生了闪退。这个时候发现9.0对权限、加密和Apache HTTP client发生了相关变化。

    一、首先我遇到的第一个错误是:

    Caused by: java.lang.ClassNotFoundException: Didn't find class "org.apache.http.protocol.BasicHttpContext" on path: DexPathList”,查找了一下原因:

    非Activity-Context启动Activity,现在强制执行 FLAG_ACTIVITY_NEW_TASK 要求,Apache HTTP 客户端弃用,影响采用非标准 ClassLoader 的应用。

    在项目中用到了 Apache HTTP client 的相关类,就会抛出找不到这些类的错误。这是因为官方已经在 Android P 的启动类加载器中将其移除,如果仍然需要使用 Apache HTTP client.

    这种问题的解决方法有两种:

    1. 在 Manifest 文件中加入:

    <uses-library

    android:name="org.apache.http.legacy"

    android:required="false"/>

    1. 可以直接将 Apache HTTP client 的相关类打包进 APK 中。

    二、第二个错误是:

    CLEARTEXT communication to life.115.com not permitted by network security policy:

    原因是:Android P 限制了明文流量的网络请求,非加密的流量请求都会被系统禁止掉;

    解决方案:

    第一步,在资源文件新建xml目录,新建文件 network_security_config,名字可以自己命名。

    <?xml version="1.0" encoding="utf-8"?>

    <network-security-config>

    <base-configcleartextTrafficPermitted="true"/>

    </network-security-config>

    第二步,在AndroidManifest中引用

    <application

    android:name=".app.SophixStubApplication"

    android:allowBackup="true"

    android:icon="@mipmap/jycicon"

    android:label="@string/app_name"

    android:networkSecurityConfig="@xml/network_security_config"

    android:supportsRtl="true"

    android:theme="@style/AppTheme">

    <uses-library

    android:name="org.apache.http.legacy"

    android:required="false"/>

    </application>三、第三个问题就是:

    android.util.AndroidRuntimeException: Calling startActivity from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

    问题的原因是:Context中有一个startActivity方法,Activity继承自Context,重载了startActivity方法。如果使用 Activity的startActivity方法,不会有任何限制,而如果使用Context的startActivity方法的话,就需要开启一个新 的task,遇到上面那个异常的,都是因为使用了Context的startActivity方法。

    解决办法就是:

    加一个flag,intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    其中这个地方我是用于下载apk的,具体的代码如下:

    Intent intent2 = newIntent(Intent.ACTION_VIEW);

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

    intent2.setAction( "android.intent.action.VIEW");

    intent2.addCategory( "android.intent.category.DEFAULT");

    intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_GRANT_READ_URI_PERMISSION);

    Uri contentUri = FileProvider.getUriForFile(getApplicationContext, "com.jyc99.jyc.fileprovider", responseInfo.result);

    intent2.setDataAndType(contentUri, "application/vnd.android.package-archive");

    } else{

    intent2.setAction( "android.intent.action.VIEW");

    intent2.addCategory( "android.intent.category.DEFAULT");

    intent2.setDataAndType(Uri.fromFile(responseInfo.result), "application/vnd.android.package-archive");

    intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    }

    其中特别注意是:intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_GRANT_READ_URI_PERMISSION);

    四、Android 9.0 加密报错

    问题原因:The Crypto provider has been deleted in Android P (and was deprecated in Android N), so the code will crash.

    报错代码:SecureRandom.getInstance(SHA1PRNG, "Crypto"),这个是因为Crypto provider 在Android9.0中已经被Google删除了,调用的话就会发生crash。

    使用如下方法生成SecretKeySpec 对象:

    privatestaticSecretKeySpec deriveKeyInsecurely(String password){

    byte[] passwordBytes = password.getBytes(StandardCharsets.US_ASCII);

    returnnewSecretKeySpec(InsecureSHA1PRNGKeyDerivator.deriveInsecureKey(passwordBytes, AESUtils.KEY_SIZE), "AES");

    } 五、其他Api的修改

    其中错误信息是:

    java.lang.IllegalArgumentException: Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed

    解决方案是:

    if(Build.VERSION.SDK_INT >= 26) {

    canvas.clipPath(mPath);

    } else{

    canvas.clipPath(mPath, Region.Op.REPLACE);

    }

    以上就是我在适配安卓9.0系统中所遇到的坑,每次安卓新版本发布都需要充分了解其中更新的新特新,这样可以避免少踩坑,少改bug。这些适配肯定还不够完善,有补充的大神可以留言评论告知,谢谢了!

    展开全文
  • 安卓9.0适配方案和踩坑

    千次阅读 2019-06-27 17:28:22
    年初的时候就已经适配安卓9.0,但由于业务需求一直没有使用上,前段时间发布了,结果有用户反馈在安卓9.0的手机上更新下载App发生了闪退。这个时候发现9.0对权限、加密和Apache HTTP client发生了相关变化。 一. ...

    年初的时候就已经适配了安卓9.0,但由于业务需求一直没有使用上,前段时间发布了,结果有用户反馈在安卓9.0的手机上更新下载App发生了闪退。这个时候发现9.0对权限、加密和Apache HTTP client发生了相关变化。

    一. 首先我遇到的第一个错误是:Caused by: java.lang.ClassNotFoundException: Didn't find class "org.apache.http.protocol.BasicHttpContext" on path: DexPathList”,查找了一下原因:

    非Activity-Context启动Activity,现在强制执行 FLAG_ACTIVITY_NEW_TASK 要求,Apache HTTP 客户端弃用,影响采用非标准 ClassLoader 的应用

    在项目中用到了 Apache HTTP client 的相关类,<mark>就会抛出找不到这些类的错误</mark>。这是因为官方已经<mark>在 Android P 的启动类加载器中将其移除</mark>,如果仍然需要使用 Apache HTTP client.

    这种问题的解决方法有两种:

    1. 在 Manifest 文件中加入:

    <uses-library
          android:name="org.apache.http.legacy"
          android:required="false" />

    2. 可以直接将 Apache HTTP client 的相关类打包进 APK 中。

    二. 第二个错误是:CLEARTEXT communication to life.115.com not permitted by network security policy:

    原因是:Android P 限制了明文流量的网络请求,非加密的流量请求都会被系统禁止掉;

    解决方案:

    第一步,在资源文件新建xml目录,新建文件 network_security_config,名字可以自己命名。

    <?xml version="1.0" encoding="utf-8"?> 
    <network-security-config> 
       <base-config cleartextTrafficPermitted="true" /> 
    </network-security-config>
    

    第二步,在AndroidManifest中引用

    <application
        android:name=".app.SophixStubApplication"
        android:allowBackup="true"
        android:icon="@mipmap/jycicon"
        android:label="@string/app_name"
        android:networkSecurityConfig="@xml/network_security_config"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
    
        <uses-library
          android:name="org.apache.http.legacy"
          android:required="false" />
    </application>

    三. 第三个问题就是:android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

    问题的原因是Context中有一个startActivity方法,Activity继承自Context,重载了startActivity方法。如果使用 Activity的startActivity方法,不会有任何限制,而如果使用Context的startActivity方法的话,就需要开启一个新 的task,遇到上面那个异常的,都是因为使用了Context的startActivity方法。

    解决办法就是:

    加一个flag,intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    其中这个地方我是用于下载apk的,具体的代码如下:

    Intent intent2 = new Intent(Intent.ACTION_VIEW);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                  intent2.setAction("android.intent.action.VIEW");
                  intent2.addCategory("android.intent.category.DEFAULT");
                  intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_GRANT_READ_URI_PERMISSION);
                  Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.jyc99.jyc.fileprovider", responseInfo.result);
                  intent2.setDataAndType(contentUri, "application/vnd.android.package-archive");
                } else {
                  intent2.setAction("android.intent.action.VIEW");
                  intent2.addCategory("android.intent.category.DEFAULT");
                  intent2.setDataAndType(Uri.fromFile(responseInfo.result), "application/vnd.android.package-archive");
                  intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                }

    其中特别注意是:intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_GRANT_READ_URI_PERMISSION);

    四. Android 9.0 加密报错

    问题原因:The Crypto provider has been deleted in Android P (and was deprecated in Android N), so the code will crash.
    报错代码:SecureRandom.getInstance(SHA1PRNG, "Crypto"),这个是因为Crypto provider 在Android9.0中已经被Google删除了,调用的话就会发生crash。

    使用如下方法生成SecretKeySpec 对象:

    private static SecretKeySpec deriveKeyInsecurely(String password) { 
      byte[] passwordBytes = password.getBytes(StandardCharsets.US_ASCII);
      return new SecretKeySpec(InsecureSHA1PRNGKeyDerivator.deriveInsecureKey(passwordBytes, AESUtils.KEY_SIZE), "AES"); 
    }
    

    五.前台服务需要添加权限

    在安卓9.0版本之后,必须要授予FOREGROUND_SERVICE权限,才能够使用前台服务,否则会抛出异常。如果我们没有在AndroidManifest中注册FOREGROUND_SERVICE权限,在Service启动的时候会抛出SecurityException异常。

    对此只需要在AndroidManifest添加对应的权限即可,这个权限是普通权限,不需要动态申请。

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

    六. 其他Api的修改

    其中错误信息是:

    java.lang.IllegalArgumentException: Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed

    解决方案是:

    if (Build.VERSION.SDK_INT >= 26) {
                        canvas.clipPath(mPath);
                    } else {
                        canvas.clipPath(mPath, Region.Op.REPLACE);
                    }

    以上就是我在适配安卓9.0系统中所遇到的坑,每次安卓新版本发布都需要充分了解其中更新的新特新,这样可以避免少踩坑,少改bug。这些适配肯定还不够完善,有补充的大神可以留言评论告知,谢谢了!

    展开全文
  • 适配安卓9.0

    2020-11-23 02:25:44
    <div><p>现在xposed能通过magisk模块运行在安卓9.0了,可惜微x模块以前在安卓8.1时候激活,微信还只是有些闪退,到了安卓9.0就直接没法用了</p><p>该提问来源于开源项目:fkzhang/...
  • 安卓9.0网络权限适配

    2020-12-22 10:44:56
    安卓9.0网络权限的新要求 如果你的sdkversion是27以上且是http开头的网络协议是要加这个xml配置的 网络权限需要多加一个xml文件,在res中新建一个xml的包,然后在里面新建一个xml resources file 然后文件名写上...

    如果你的sdkversion是27以上且是http开头的网络协议是要加这个xml配置的

    网络权限需要多加一个xml文件,在res中新建一个xml的包,然后在里面新建一个xml resources file 然后文件名写上network_security_config,内容为下:

    
    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
    	<--禁用掉明文流量请求的检查-->
    	<base-config cleartextTrafficPermitted="true" />
    </network-security-config>
    
    

    然后在manifests中application属性添加

    android:networkSecurityConfig="@xml/network_security_config"
    就OK了

    展开全文
  • 安卓6.0~9.0适配

    2018-12-04 09:47:18
    安卓6.0~9.0适配  雾里看花六月天 关注   转自: https://www.jianshu.com/p/23b8ae9d5a95   1.前言 大家还记得Android 6.0权限适配的泪水吗?而现在谷歌已经出了Android P的稳定版,而且谷歌粑粑,为了...

    安卓6.0~9.0适配

    96 雾里看花六月天 关注

     

    转自:  https://www.jianshu.com/p/23b8ae9d5a95

     

    1.前言

    大家还记得Android 6.0权限适配的泪水吗?而现在谷歌已经出了Android P的稳定版,而且谷歌粑粑,为了大家能给辛苦熬夜加班,特地的和个大市场合作,要强制推出9.0的适配,而近期在下不才,为了报着多踩坑的心态,做了一下7.0~9.0的适配,脸颊也是老泪两行

    2.安卓6.0的适配

    2.1 怎么适配

    ● 在6.0所有权限都需要申请?

    曰:当然不是。只有属于危险权限的才需要申请。危险权限看下表1-2

    ● 那危险权限也很多啊,也要一个个申请?

    曰:当然不是。你看看下面的表,都分好组了(9组),对于同一组内的权限,只要有一个被同意,其他的都会被同意。

    ● 谁最帅

    曰:当然是子信。

    2.2 列举权限的分组

    表1-2危险权限分组

    分组 名字 分割线
    PHONE android.permission.READ_PHONE_STATE  
      android.permission.CALL_PHONE  
      android.permission.READ_CALL_LOG  
      android.permission.ADD_VOICEMAIL  
      android.permission.WRITE_CALL_LOG  
      android.permission.USE_SIP  
      android.permission.PROCESS_OUTGOING_CALLS  
    CALENDAR android.permission.READ_CALENDAR  
      android.permission.WRITE_CALENDAR  
    CAMERA android.permission.CAMERA  
    CONTACTS android.permission.READ_CONTACTS  
      android.permission.WRITE_CONTACTS  
      android.permission.GET_ACCOUNTS  
    LOCATION android.permission.ACCESS_FINE_LOCATION  
      android.permission.ACCESS_COARSE_LOCATION  
    MICROPHONE android.permission.RECORD_AUDIO  
    SENSORS android.permission.BODY_SENSORS  
    SMS android.permission.SEND_SMS  
      android.permission.RECEIVE_SMS  
      android.permission.READ_SMS  
      android.permission.RECEIVE_WAP_PUSH  
      android.permission.RECEIVE_MMS  
    STORAGE android.permission.READ_EXTERNAL_STORAGE  
      android.permission.WRITE_EXTERNAL_STORAGE  
    <!-- 危险权限 start -->
    <!--PHONE-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.CALL_PHONE"/>
    <uses-permission android:name="android.permission.READ_CALL_LOG"/>
    <uses-permission android:name="android.permission.ADD_VOICEMAIL"/>
    <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
    <uses-permission android:name="android.permission.USE_SIP"/>
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
    <!--CALENDAR-->
    <uses-permission android:name="android.permission.READ_CALENDAR"/>
    <uses-permission android:name="android.permission.WRITE_CALENDAR"/>
    <!--CAMERA-->
    <uses-permission android:name="android.permission.CAMERA"/>
    <!--CONTACTS-->
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
    <!--LOCATION-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <!--MICROPHONE-->
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <!--SENSORS-->
    <uses-permission android:name="android.permission.BODY_SENSORS"/>
    <!--SMS-->
    <uses-permission android:name="android.permission.SEND_SMS"/>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH"/>
    <uses-permission android:name="android.permission.RECEIVE_MMS"/>
    <!--STORAGE-->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!-- 危险权限 Permissions end -->
    

    以上是列出9组需要动态申请的权限,建议自己统一封装成一个工具类,这里就不细说了

    3.Android 7.0的适配

    3.1 应用间共享文件

    在targetSdkVersion大于等于的24的App中,但是我们没有去适配7.0。那么在调用安装页面,或修改用户头像操作时,就会失败。那么就需要你去适配7.0或是将targetSdkVersion改为24以下(不推荐)。适配的方法这里就不细讲,大家可以看鸿洋大神的
    Android 7.0 行为变更 通过FileProvider在应用间共享文件这篇文章

    3.2 APK signature scheme v2

    Android 7.0 引入一项新的应用签名方案 APK Signature Scheme v2,它能提供更快的应用安装时间和更多针对未授权 APK 文件更改的保护。在默认情况下,Android Studio 2.2 和 Android Plugin for Gradle 2.2 会使用 APK Signature Scheme v2 和传统签名方案来签署您的应用。

    签名版.png

    1)只勾选v1签名就是传统方案签署,但是在7.0上不会使用V2安全的验证方式。

    2)只勾选V2签名7.0以下会显示未安装,7.0上则会使用了V2安全的验证方式。

    3)同时勾选V1和V2则所有版本都没问题。

    3.3 org.apache不支持问题

    // build.gradle里面加上这句话
    defaultConfig {
            useLibrary 'org.apache.http.legacy'
        }
    

    4.Android 8.0的适配

    4.1 安卓8.0中PHONE权限组新增两个权限

    ANSWER_PHONE_CALLS:允许您的应用通过编程方式接听呼入电话。要在您的应用中处理呼入电话,您可以使用 acceptRingingCall() 函数。
    READ_PHONE_NUMBERS :权限允许您的应用读取设备中存储的电话号码。
    

    4.2 通知适配

    安卓8.0中,为了更好的管制通知的提醒,不想一些不重要的通知打扰用户,新增了通知渠道,用户可以根据渠道来屏蔽一些不想要的通知

    兼容的代码

    /**
     * 安卓8。0通知的兼容类哦,
     * NotifyCompatYc   yc : 是雨辰的简写,谢谢哦,嘿嘿 ----高贵的子信
     */
    public class NotifyCompatYc {
    
        public static final String QFMD_CHANNEL_ID = "com.oms.mingdeng";
        public static final String QFMD_CHANNEL_NAME = "祈福明燈";
        public static final String LJMS_DEFAULT_CHANNEL_NAME = "靈機妙算";
        public static final String LJMS_CHANNEL_ID = "com.oms.mmcnotity";
        public static final String XYS_CHANNEL_ID = "com.oms.xuyuanshu";
        public static final String XYS_CHANNEL_NAME = "許願樹";
    
        public static void setONotifyChannel(NotificationManager manager, NotificationCompat.Builder builder, String channeId, String channelName) {
            if (TextUtils.isEmpty(channeId)||TextUtils.isEmpty(channelName)){
                L.e("NotifyCompatYc:  ".concat("安卓8.0的通知兼容库中 channeId 与 channelName 不能为empty"));
            }
            if (Build.VERSION.SDK_INT >= 26) {
                //第三个参数设置通知的优先级别
                NotificationChannel channel =
                        new NotificationChannel(channeId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
                channel.canBypassDnd();//是否可以绕过请勿打扰模式
                channel.canShowBadge();//是否可以显示icon角标
                channel.enableLights(true);//是否显示通知闪灯
                channel.enableVibration(true);//收到小时时震动提示
                channel.setBypassDnd(true);//设置绕过免打扰
                channel.setLockscreenVisibility(NotificationCompat.VISIBILITY_SECRET);
                channel.setLightColor(Color.RED);//设置闪光灯颜色
                channel.getAudioAttributes();//获取设置铃声设置
                channel.setVibrationPattern(new long[]{100, 200, 100});//设置震动模式
                channel.shouldShowLights();//是否会闪光
                if (manager != null) {
                    manager.createNotificationChannel(channel);
                }
                if (builder != null) {
                    builder.setChannelId(channeId);//这个id参数要与上面channel构建的第一个参数对应
                }
            }
        }
    
        public static void setONotifyChannel(NotificationManager manager,  String channeId, String channelName) {
            setONotifyChannel(manager,null,channeId,channelName);
        }
    
        public static Notification getNotification(Context context, String channelId) {
            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, channelId);
            Notification notification = notificationBuilder.setOngoing(true)
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setPriority(NotificationManager.IMPORTANCE_MIN)
                    .setCategory(Notification.CATEGORY_SERVICE)
                    .build();
            return notification;
        }
    }
    
    /**
     * 作者:子川
     * 时间:2017/2/9:18:03
     * 邮箱:lantianhua@linghit.com
     * 说明:TODO
     */
    public class NotifyManager {
    
        // 单例开始
        private volatile static NotifyManager INSTANCE;
    
        private NotifyManager(Context context) {
            initNotifyManager(context);
        }
    
        public static NotifyManager getInstance(Context context) {
            if (INSTANCE == null) {
                synchronized (NotifyManager.class) {
                    if (INSTANCE == null) {
                        INSTANCE = new NotifyManager(context);
                    }
                }
            }
            return INSTANCE;
        }
        // 单例结束
    
        private NotificationManager manager;
       // NotificationManagerCompat
        private NotificationCompat.Builder builder;
    
        //初始化通知栏配置
        private void initNotifyManager(Context context) {
            context = context.getApplicationContext();
            manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            // 如果存在则清除上一个消息
    //        manager.cancel(news_flag);
            builder = new NotificationCompat.Builder(context,NotifyCompatYc.QFMD_CHANNEL_ID);
    
            NotifyCompatYc.setONotifyChannel(manager,builder,NotifyCompatYc.QFMD_CHANNEL_ID,NotifyCompatYc.QFMD_CHANNEL_NAME);
    
            // 设置标题
            builder.setContentTitle(context.getResources().getString(R.string.qfmd_notify_title1));
            // 状态栏的动画提醒语句
            builder.setTicker(context.getResources().getString(R.string.qfmd_notify_ticker));
            // 什么时候提醒的
            builder.setWhen(System.currentTimeMillis());
            // 设置通知栏的优先级
            builder.setPriority(Notification.PRIORITY_DEFAULT);
            // 设置点击可消失
            builder.setAutoCancel(true);
            // 设置是否震动等
            builder.setDefaults(Notification.DEFAULT_VIBRATE);
            // 设置icon
            builder.setSmallIcon(R.drawable.lingji_icon);
            // 设置点击意图
            Intent intent = new Intent(context, GongdenggeActivity.class);
            Bundle bundle = new Bundle();
            bundle.putBoolean(Contants.INTENT_GOTO_MYLMAP, true);
            intent.putExtras(bundle);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 230, intent, PendingIntent.FLAG_UPDATE_CURRENT);
            builder.setContentIntent(pendingIntent);
        }
    
        /**
         * 显示祈福明灯过期通知
         */
        public void showQiFuLampOutOfDateNotify(Context context) {
            // 设置内容
            builder.setContentText(context.getResources().getString(R.string.qfmd_notify_content1));
            manager.notify(13251, builder.build());
        }
    
        public void showQiFuLampBlessNotify(Context context) {
            builder.setContentText(context.getResources().getString(R.string.qfmd_notify_content2));
            manager.notify(13255, builder.build());
        }
    }
    

    4.3 安装APK

    首先在AndroidManifest文件中添加安装未知来源应用的权限:

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
    

    这样系统会自动询问用户完成授权。当然你也可以先使用 canRequestPackageInstalls()查询是否有此权限,如果没有的话使用Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES这个action将用户引导至安装未知应用权限界面去授权。

    private static final int REQUEST_CODE_UNKNOWN_APP = 100;
    
        private void installAPK(){
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                boolean hasInstallPermission = getPackageManager().canRequestPackageInstalls();
                if (hasInstallPermission) {
                    //安装应用
                } else {
                    //跳转至“安装未知应用”权限界面,引导用户开启权限
                    Uri selfPackageUri = Uri.parse("package:" + this.getPackageName());
                    Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, selfPackageUri);
                    startActivityForResult(intent, REQUEST_CODE_UNKNOWN_APP);
                }
            }else {
                //安装应用
            }
    
        }
    
        //接收“安装未知应用”权限的开启结果
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == REQUEST_CODE_UNKNOWN_APP) {
                installAPK();
            }
        }
    
    
    

    4.4 SharedPreferences闪退

    SharedPreferences read = getSharedPreferences(RELEASE_POOL_DATA, MODE_WORLD_READABLE);
    //MODE_WORLD_READABLE :8.0以后不能使用这个获取,会闪退,修改成MODE_PRIVATE
    

    4.5 SecurityException的闪退

    问题原因:项目使用了ActiveAndroid,在 8.0 或 8.1 系统上使用 26 或以上的版本的 SDK 时,调用 ContentResolver 的 notifyChange 方法通知数据更新,或者调用 ContentResolver 的 registerContentObserver 方法监听数据变化时,会出现上述异常。

    解决方案:

    (1)在清单文件配置

    <provider
            android:name="com.activeandroid.content.ContentProvider"
            android:authorities="com.ylmf.androidclient"
            android:enabled="true"
            android:exported="false">
    </provider>
    

    (2)去掉这个监听刷新的方法,改为广播刷新

    4.6 静态广播无法正常接收

    问题原因: Android 8.0 引入了新的广播接收器限制,因此您应该移除所有为隐式广播 Intent 注册的广播接收器

     //setNotificationUri(cursor);
    //给注销掉
    /** 通知数据库发生变化*/
        private void notifyChange () {
            //mContext.getContentResolver().notifyChange(ORDER_URI, null, false);
            BroadcastController.sendChangeDataBroadCast(mContext);
        }
    

    解决方案:
    使用动态广播代替静态广播

    4.7 Caused by: java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation

    解决方案(1):

    问题原因: Android 8.0 非全屏透明页面不允许设置方向(8.1以上谷歌就修复去掉了这个限制)
    
    解决方案:android:windowIsTranslucent设置为false
    

    解决方案(2):<去掉方向的设置>

     

    20171225124419576.png

     

    解决方案(3):
    使用对话框、fragmentDialog、Popwindow的代替透明的Activity

    Android 9.0的适配

    9.1 CLEARTEXT communication to life.115.com not permitted by network security policy

    问题原因: Android P 限制了明文流量的网络请求,非加密的流量请求都会被系统禁止掉

    解决方案:

    在资源文件新建xml目录,新建文件

    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
        <base-config cleartextTrafficPermitted="true" />
    </network-security-config>
    

    清单文件配置:

    <application
            android:networkSecurityConfig="@xml/network_security_config">
            <!--9.0加的,哦哦-->
            <uses-library
                android:name="org.apache.http.legacy"
                android:required="false" />
        </application>
    

    但还是建议都使用https进行传输

    9.2 其他Api的修改

    java.lang.IllegalArgumentException: Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed

    if (Build.VERSION.SDK_INT >= 26) {
                        canvas.clipPath(mPath);
                    } else {
                        canvas.clipPath(mPath, Region.Op.REPLACE);
                    }
    

    总结:经过几天的踩坑,终于把targetSdkVersion升级到28,对于以上的经验,也许还存在某些疏漏的,也希望大家可以指正,补充,告诉,希望对你有一定的帮助,鄙人也很开心

    展开全文
  • 安卓6.0到9.0适配

    2018-12-17 16:36:41
    而现在谷歌已经出了Android P的稳定版,而且谷歌粑粑,为了大家能给辛苦熬夜加班,特地的和个大市场合作,要强制推出9.0适配,而近期在下不才,为了报着多踩坑的心态,做了一下7.0~9.0适配,脸颊也是老泪两行。...
  • 最近遇到一个手机适配问题,就是同样的一个app运行在安卓9.0手机上的显示和安卓其他设备上的颜色比较浅。 因为项目是通过TextureView来绘制界面图像的,所以我只能先去了解这个类相关的Api,试图通过更改Windows的...
  • 安卓9.0即Android 9.0已经面向全球发布,它的代号是Pie,仍然基于Linux内核构建。为了避免Android 9.0 Pie新特性更新引发的适配问题,本文将介绍Android 9.0将带来哪些和开发者息息相关的影响,对Android 9.0新特性...
  • 本文将重点介绍该版本特性中部分需要开发适配的部分。 背景:谷歌在GoogleI / O 2018 上终于发布了Android 9.0。 权限相关 1、后台对传感器的访问受限 Android 9 限制后台应用访问用户输入和传感器数据的能力。...
  • 安卓9.0马达框架分析

    2020-05-23 13:04:27
    安卓9.0马达框架分析 mt8167s;Android 9.0 前言 ​ 最近需要将之前的一些驱动接口转为安卓标准接口,方便上层应用或者第三方应用去适配。这篇文章先从简单的马达框架入手进行讲解。 正文 ​ 整个马达框架比较...
  • Android 4.0~9.0适配

    2019-04-19 17:22:20
    安卓6.0~9.0适配 1.常用适配 大概列举 1、Android 5.0对应的 通知小图标的适配 2、Android 6.0权限的适配 3、Android 7.0的文件共享的适配 此处经常用在读取本地下载好的文件 如apk升级文件等 适配方法如下:...
  • 8月7日,Android P即Android 9.0正式版终于和大家见面了,历经了近半年的改进和优化,Google正式发布安卓9.0。Android 9.0利用人工智能技术,让用户的手机更加智能、简洁与人性化。按照谷歌对Android系统独特的命名...
  • Android 6.0-9.0适配

    2019-11-21 20:49:09
    而现在谷歌已经出了Android P的稳定版,而且谷歌粑粑,为了大家能给辛苦熬夜加班,特地的和个大市场合作,要强制推出9.0适配,而近期在下不才,为了报着多踩坑的心态,做了一下7.0~9.0适配,脸颊也是老泪两行 ...
  • Android6.0~9.0适配

    2018-11-24 08:41:15
    而现在谷歌已经出了Android P的稳定版,而且谷歌粑粑,为了大家能给辛苦熬夜加班,特地的和个大市场合作,要强制推出9.0适配,而近期在下不才,为了报着多踩坑的心态,做了一下7.0~9.0适配,脸颊也是老泪两行 ...
  • 目前,美国Google公司的AndroidP(安卓9.0),已经正式全面推出有几个多月了。众多手机品牌厂商也都在积极的进行更新适配Android 9.0系统(修改UI界面也算是二次开发,嗯)。不知道各位Android用户是否体验到了这一...
  • 安卓App适配9.0系统

    千次阅读 2018-12-28 09:45:19
    9.0系统接口访问网络需要https     在values下新建xml文件:network_security_config.xml  &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;network-security-config&...
  • 2019-07-22 在高德开放平台提交工单咨询,得知9.0无需特殊适配,GPS定位有信号就能取到卫星数,但是我们APP在室外测试,始终无法取得。通过多天对比、修改高德定位demo,发现只要修改applicationId成我们APP的id,在...
  • Android 6.0到9.0适配总结

    千次阅读 2019-01-14 11:29:29
    而现在谷歌已经出了Android P的稳定版,而且谷歌粑粑,为了大家能给辛苦熬夜加班,特地的和个大市场合作,要强制推出9.0适配,而近期在下不才,为了报着多踩坑的心态,做了一下7.0~9.0适配,脸颊也是老泪两行 ...
  • 而现在谷歌已经出了Android P的稳定版,而且谷歌粑粑,为了大家能给辛苦熬夜加班,特地的和个大市场合作,要强制推出9.0适配,而近期在下不才,为了报着多踩坑的心态,做了一下7.0~9.0适配,脸颊也是老泪两行 ...

空空如也

空空如也

1 2 3 4 5
收藏数 88
精华内容 35
关键字:

安卓9.0适配