🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
官网 [Android Pie预览](https://developer.android.com/about/versions/pie) 项目中的 `targetSdkVersion` 改为 `28(9.0)` 。 ## Http请求失败 在`9.0`中默认情况下启用网络传输层安全协议 (`TLS)`,默认情况下已停用明文支持。也就是不允许使用`http`请求,要求使用`https`。 比如我使用的是`okhttp`,会报错: `java.net.UnknownServiceException: CLEARTEXT communication to xxxx not permitted by network security policy` 解决方法是需要我们添加网络安全配置。首先在`res`目录下新建`xml`文件夹,添加`network_security_config.xml`文件: ```xml <?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true" /> </network-security-config> ``` `AndroidManifest.xml`中的`application`添加: ```xml <manifest ... > <application android:networkSecurityConfig="@xml/network_security_config"> ... </application> </manifest> ``` 为了安全灵活,我们可以指定支持的`http`域名: ```xml <?xml version="1.0" encoding="utf-8"?> <network-security-config> <!-- Android 9.0 上部分域名时使用 http --> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">secure.example.com</domain> <domain includeSubdomains="true">cdn.example1.com</domain> </domain-config> </network-security-config> ``` 当然不止这些配置,还有抓包配置、设置自定义CA以及各种场景下灵活的配置,详细的方法可以查看[官方文档](https://developer.android.google.cn/training/articles/security-config.html)。 ## Apache HTTP 客户端弃用 在 `Android 6.0` 时,就已经取消了对 `Apache HTTP` 客户端的支持。 从 `Android 9.0` 开始,默认情况下该库已从 `bootclasspath` 中移除。但是耐不住有些SDK中还在使用,比如我见到的友盟QQ分享报错问题。 所以要想继续使用`Apache HTTP`,需要在应用的 `AndroidManifest.xml` 文件中添加: ```xml <manifest ... > <application> <uses-library android:name="org.apache.http.legacy" android:required="false"/> ... </application> </manifest> ``` ## 前台服务 可以试着搜索一下你的代码,看是否有调用`startForegroundService`或`startForeground`方法来启动一个前台服务。 `startForegroundService`主要来源估计都是**8.0适配**时候加上的: ```java Intent intentService = new Intent(this, MyService.class); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { startForegroundService(intentService); } else { startService(intentService); } ``` `9.0` 要求创建一个前台服务需要请求`FOREGROUND_SERVICE`权限,否则系统会引发`SecurityException`。 ```java java.lang.RuntimeException: Unable to start service com.weilu.test.MyService@81795be with Intent { cmp=com.weilu.test/.MyService }: java.lang.SecurityException: Permission Denial: startForeground from pid=28631, uid=10626 requires android.permission.FOREGROUND_SERVICE at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3723) at android.app.ActivityThread.access$1700(ActivityThread.java:201) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1705) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:207) at android.app.ActivityThread.main(ActivityThread.java:6820) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876) ``` 解决方法就是`AndroidManifest.xml`中添加`FOREGROUND_SERVICE`权限: `<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> ` ## 启动Activity 在 `9.0` 中,不能直接非`Activity`环境中(比如`Service`,`Application`)启动`Activity`,否则会崩溃报错: ```java java.lang.RuntimeException: Unable to create service com.weilu.test.MyService: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want? at android.app.ActivityThread.handleCreateService(ActivityThread.java:3578) at android.app.ActivityThread.access$1400(ActivityThread.java:201) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1690) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:207) at android.app.ActivityThread.main(ActivityThread.java:6820) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876) ``` 这类问题一般会在点击推送消息跳转页面这类场景,解决方法就是 Intent 中添加标志`FLAG_ACTIVITY_NEW_TASK` ```java Intent intent = new Intent(this, TestActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); ``` ## 权限 Android 9 引入[`CALL_LOG`](https://developer.android.com/reference/android/Manifest.permission_group#CALL_LOG)[权限组](https://developer.android.com/guide/topics/permissions/overview#perm-groups)并将[`READ_CALL_LOG`](https://developer.android.com/reference/android/Manifest.permission#READ_CALL_LOG)、[`WRITE_CALL_LOG`](https://developer.android.com/reference/android/Manifest.permission#WRITE_CALL_LOG)和[`PROCESS_OUTGOING_CALLS`](https://developer.android.com/reference/android/Manifest.permission#PROCESS_OUTGOING_CALLS)权限移入该组。 在之前的 Android 版本中,这些权限位于`PHONE`权限组。 > 限制访问通话记录 如果应用需要访问通话记录或者需要处理去电,则您必须向 `CALL_LOG` 权限组明确请求这些权限。 否则会发生 `SecurityException`。 > 限制访问电话号码 要通过 `PHONE_STATE` **Intent** 操作读取电话号码,同时需要 `READ_CALL_LOG` 权限和 `READ_PHONE_STATE` 权限。 要从 `PhoneStateListener` 的 `onCallStateChanged()` 中读取电话号码,只需要 `READ_CALL_LOG` 权限。 不需要 `READ_PHONE_STATE` 权限。 ## 其他 在 `Android 9` 中,调用 `Build.SERIAL` 会始终返回 `UNKNOWN` 以保护用户的隐私。如果你的应用需要访问设备的硬件序列号,那么需要先请求 `READ_PHONE_STATE` 权限,然后调用 `Build.getSerial()`。 注意非 SDK 接口的限制。主要是一些热修复、插件化框架涉及比较多,注意及时升级新版本。 多进程使用 `WebView` 注意无法共用同一数据目录。 [详细点击查看 ](https://developer.android.google.cn/about/versions/pie/android-9.0-changes-28#web-data-dirs) ***** 文章到这里就全部讲述完啦,若有其他需要交流的可以留言哦~!~! 想阅读作者的更多文章,可以查看我 [个人博客](http://dandanlove.com/) 和公共号:![振兴书城](https://imgconvert.csdnimg.cn/aHR0cDovL3VwbG9hZC1pbWFnZXMuamlhbnNodS5pby91cGxvYWRfaW1hZ2VzLzEzMTk4NzktNjEyYzRjNjZkNDBjZTg1NS5qcGc?x-oss-process=image/format,png)