target Version28的行为变更
隐私权限变更
如果你的应用以 Android 9 为目标平台,应牢记以下行为变更。 对设备序列信息和 DNS 信息进行的这些更新可增强用户隐私保护。
- 构建序列化弃用
1、在 Android 9 中,Build.SERIAL 始终设置为 "UNKNOWN" 以保护用户的隐私。
2、如果你的应用需要访问设备的硬件序列号,应改为请求 READ_PHONE_STATE 权限,然后调用 getSerial()。 - DNS隐私
以 Android 9 为目标平台的应用应采用私有 DNS API。 具体而言,当系统解析程序正在执行 DNS-over-TLS 时,应用应确保任何内置 DNS 客户端均使用加密的 DNS 查找与系统相同的主机名,或停用它而改用系统解析程序。
框架安全性变更
Android 9 包含可提升应用安全性的多个行为变更,但这些变更仅在你的应用以 API 级别 28 或更高级别为目标平台时才会生效:
-
默认情况下启用网络传输层安全协议 (TLS)
如果你的应用以 Android 9 或更高版本为目标平台,则默认情况下 isCleartextTrafficPermitted() 函数返回 false。 如果你的应用需要为特定域名启用明文,你必须在应用的网络安全性配置中针对这些域名将 cleartextTrafficPermitted 显式设置为 true。 -
按进程分设基于网络的数据目录:
1、为改善 Android 9 中的应用稳定性和数据完整性,应用无法再让多个进程共用同一 WebView 数据目录。 此类数据目录一般存储 Cookie、HTTP 缓存以及其他与网络浏览有关的持久性和临时性存储。2、在大多数情况下,你的应用只应在一个进程中使用 android.webkit 软件包中的类,例如 WebView 和 CookieManager。 例如,你应该将所有使用 WebView 的 Activity 对象移入同一进程。 你可以通过在应用的其他进程中调用 disableWebView(),更严格地执行“仅限一个进程”规则。 该调用可防止 WebView 在这些其他进程中被错误地初始化,即使是从依赖内容库进行的调用也能防止。
3、如果你的应用必须在多个进程中使用 WebView 的实例,则必须先利用 WebView.setDataDirectorySuffix() 函数为每个进程指定唯一的数据目录后缀,然后再在该进程中使用 WebView 的给定实例。 该函数会将每个进程的网络数据放入其在应用数据目录内自己的目录中。
注:即使使用 setDataDirectorySuffix(),系统也不会跨应用的进程界限共享 Cookie 以及其他网络数据。 如果应用中的多个进程需要访问同一网络数据,需要自行在这些进程之间复制数据。 例如,可以调用 getCookie() 和 setCookie(),在不同进程之间手动传输 Cookie 数据。
-
以应用为单位的 SELinux 域名
以 Android 9 或更高版本为目标平台的应用无法利用可全局访问的 Unix 权限与其他应用共享数据。 此变更可改善 Android 应用沙盒的完整性, 具体地讲,就是要求应用的私有数据只能由该应用访问。要与其他应用共享文件,请使用 content provider。
链接变更
-
连接数据计数和多路径
- 在以 Android 9 或更高版本为目标平台的应用中,系统计算并非当前默认网络的网络流量,例如,当设备连接 WLAN 时的蜂窝流量,并在 NetworkStatsManager 类中提供函数以查询该流量。
- 具体而言,getMultipathPreference() 现在将返回一个基于上述网络流量的值。 从 Android 9 开始,此函数针对蜂窝数据返回 true,但当超过一天内累积的特定流量时,它将开始返回 false。 在 Android 9 上运行的应用必须调用此函数并采用此提示。
- ConnectivityManager.NetworkCallback 类现在将有关 VPN 的信息发送到应用。 此变更让应用侦听连接事件变得更容易,而无需混用同步和异步调用,也无需使用有限的 API。 此外,它还意味着将设备同时连接至多个 WLAN 网络或多个蜂窝网络时,信息传输可按预期工作。
-
Apache HTTP 客户端弃用
- 在 Android 6.0 中,取消了对 Apache HTTP 客户端的支持。 从 Android 9 开始,默认情况下该内容库已从 bootclasspath 中移除且不可用于应用。要继续使用 Apache HTTP 客户端,以 Android 9 及更高版本为目标的应用可以向其 AndroidManifest.xml 添加以下内容:
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
注:拥有最低 SDK 版本 23 或更低版本的应用需要 android:required="false" 属性,因为在 API 级别低于 24 的设备上,org.apache.http.legacy 库不可用。 (在这些设备上,Apache HTTP 类在 bootclasspath 中提供。)
作为使用运行时 Apache 库的替代,应用可以在其 APK 中绑定自己的 org.apache.http 库版本。 如果进行此操作,必须将该库重新打包(使用一个类似 Jar Jar 的实用程序)以避免运行时中提供的类存在类兼容性问题。
界面变更
-
文档滚动标签
Android 9 可正确处理文档的根标签是滚动标签的案例。 在之前的版本中,滚动位置在 body 标签上设置,根标签的滚动值为零。 Android 9 支持符合标准的行为,在这种行为中,滚动标签是根标签。此外,直接访问 document.body.scrollTop、document.body.scrollLeft、document.documentElement.scrollTop 或 document.documentElement.scrollLeft 会因目标 SDK 的不同而具有不同的行为。 要访问视口滚动值,请使用 document.scrollingElement(若有)。
-
来自已暂停应用的通知
在 Android 9 之前,暂停的应用发出的通知会被取消。 从 Android 9 开始,暂停的应用发出的通知将被隐藏,直至应用继续运行。 -
CSS RGBA 十六进制值处理
以 Android 9 或更高版本为目标的应用必须支持草案版 CSS 颜色模块级别 4 的行为,用于处理 4 和 8 个十六进制数字 CSS 颜色。Chrome 自版本 52 以来便一直支持 CSS 颜色模块级别 4,但 WebView 目前停用此功能,因为现有 Android 应用被发现包含 Android ordering (ARGB) 中的 32 位十六进制颜色,这会导致渲染错误。
例如,对于以 API 级别 27 或更低版本为目标平台的应用,颜色 #80ff8080 目前在 WebView 中被渲染为不透明浅红色 (#ff8080)。 先导部分(Android 会将其解读为 Alpha 部分)目前被忽略。 如果某个应用以 API 级别 28 或更高版本为目标,则 #80ff8080 将被解读为 50% 透明浅绿 (#80ff80)。
-
视图焦点
0 面积的视图(即宽度或高度为 0)再也不能被聚焦。此外,Activity 不再隐式分配触摸模式下的初始焦点。 而是显式请求初始焦点(如若需要的话)。
前台服务
-
针对 Android 9 或更高版本并使用前台服务的应用必须请求 FOREGROUND_SERVICE 权限。 这是普通权限,因此,系统会自动为请求权限的应用授予此权限。
-
如果针对 Android 9 或更高版本的应用尝试创建一个前台服务且未请求 FOREGROUND_SERVICE,则系统会引发 SecurityException。
NotificationManager
- 需要添加NotificationManager.createNotificationChannel(notificationChannel);
趟过的坑
1、在Android 8.0(API level 26)上,Activity出现了一个莫名其妙的crash,异常信息如下:
java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
问题原因
这个问题只出现在api26
//Need to pay attention mActivityInfo.isFixedOrientation() and ActivityInfo.isTranslucentOrFloating(ta)
if (getApplicationInfo().targetSdkVersion >= O_MR1 && mActivityInfo.isFixedOrientation()) {
final TypedArray ta = obtainStyledAttributes(com.android.internal.R.styleable.Window);
final boolean isTranslucentOrFloating = ActivityInfo.isTranslucentOrFloating(ta);
ta.recycle();
//Exception occurred
if (isTranslucentOrFloating) {
throw new IllegalStateException(
"Only fullscreen opaque activities can request orientation");
}
}
解决方案
- 在AndroidManifest.xml中队Activity移除android:screenOrientation="portrait"或者设置为android:screenOrientation="unspecified"
- 或者在Activity的onCreate中设置
if (Build.VERSION.SDK_INT == 26) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
- 设置<item name="android:windowIsTranslucent">false</item>
2、使用appche网络库崩溃
- 异常信息
Caused by: java.lang.ClassNotFoundException: Didn't find class "org.apache.http.util.EncodingUtils" on path: DexPathLis。。。。
- 解决方案
- AndroidManifest.xml 添加以下内容:
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
- 修改应用程序中Http的请求为Https
- AndroidManifest.xml 添加以下内容:
3、通知栏收到消息后无法正常显示
- 解决方法(NotificationManager需要添加chanel):
NotificationManager.createNotificationChannel(notificationChannel);
4、通知栏展示mini播放器后,调用notify时有媒体声音提醒
- 表现形式,有事件触发并调用notify时会发出媒体声音提醒
- 解决办法:
- 更新channelId,设置为一个新的值,跟以往任何一个都不重复,然后再设置channel.setSound(null, null)。
- 手动调用清空channelId的方法
- 卸载app后把importance参数设置为NotificationManager.IMPORTANCE_LOW或者更低。再安装运行。
- mBuilder.setOnlyAlertOnce(true)设置为true,这样的话,每次只会提醒一次声音,不会重复提醒。
- 如果你不想卸载app的话,有个最好的办法就是同时更换channelId和NotificationManager.IMPORTANCE_LOW就可以了。
网友评论