Android6.0至9.0版本适配总结
简要列举下Android6到Android9在开发中需要适配的问题,做到心中有数,用到时再去查开发文档,文章非原创,后面已黏贴引用链接。
Android6.0
- 对危险权限申请适配(推荐AndPermission)
Android7.xx
-
目录被限制访问
- 私有文件的文件权限不在放权给所有的应用,使用MODE_WORLD_READABLE或MODE_WORLD_WRITEABLE进行操作将触发SercurityException,场景有SharePreference的模式
- 传递file://URI类型的Uri,导致无法访问该路径,会触发FileUriException,可使用FileProvider解决这问题,应用场景:apk安装,拍照
- DownloadManager不再按文件名分享私人存储的文件。COLUMN_LOCAL_FILENAME在Android7.0中被标记为depreciated,尝试在AndroidN以上版本访问该字段将触发SecurityException,可以使用ContentProvider.openFileDescriptor()来访问DownloadManager公开文件
APK sinature schme v2
-
隐式广播的限制
-
ACTION_NEW_PICTURE
和ACTION_NEW_VIDEO
隐式广播无法接受和发出 -
CONNECTIVITY_ACTION
静态注册广播无法收到,动态广播可以收到 - 对于
CONNECTIVITY_CHANGE
广播,ConnectvityManager
提供其他更健壮的API,如NetworkRequest
.
-
-
增加的Dozen模式
AndroidN 对AndroidM的Dozen模式进一步增强,降低进入Dozen模式的条件,AndroidM中的条件是不插电屏幕熄灭静置一段时间,AndroidN中去掉静置的条件。另一方面Dozen模式分为两个阶段,当设备切断电源,屏幕熄灭一段时间就会进入第一阶段,切断网络连接,推迟任务和同步;如果再静置一段时间进入第二阶段,增加对维持唤醒(PowerManagerc.WakeLock)定时任务(AlarmMager)Gps和WiFi扫描的限制。- 在Android6.0中AlarmManager中增加两个方法setAllowWhiledle()和setExactAndAllowWhiledle()通过这两个方法可使得Alarm在Dozen模式下运行,另外使用这方法时,应用每9分钟只能唤醒一次alarm。
- 给应用添加权限
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
,并使用ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
,系统会弹出设置窗口,用户可以直接将该应用添加到白名单中.
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); intent.setData(Uri.parse("package:com.showdy.dozen")); startActivity(intent);
Android8.xx
在Android 8.0之前,如果应用在运行时请求某个权限并且被授予,系统会错误地将属于同一权限组并且在清单中注册的其他权限也一并授予该应用。对于Android8.0的应用,此行为已被纠正。系统只会授予应用明确请求的权限。然而,一旦用户为应用授予某个权限,则所有后续对该权限组中权限的请求都将被自动批准,而不会提示用户
-
PHONE权限组新增两个权限
-
ANSWER_PHONE_CALLS
:权限运行应用处理呼入电话 -
READ_PHONE_NUMBERS
:权限允许应用读取设备中存储电话号码
-
Notifications
适配
方便管理通知行为和设置推出了一个新的概念:渠道和组,它允许你为要显示的每种通知类型创建自定义的类别。安装APK
Android 8.0去除“允许未知来源”选项,需手动确认。如果我们的App具备安装App的功能,那么AndroidManifest文件需要包含REQUEST_INSTALL_PACKAGES权限,未声明此权限的应用将无法安装其他应用。我们可以选择使用。Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES这个action将用户引导至安装未知应用权限界面,同时也可以使用 packageManager.canRequestPackageInstalls()查询此权限的状态。提醒窗口
WindowManager.LayoutParams
的type设置为TYPE_SYSTEM_OVERLAY
在4.4到6.0之前,google没有提供方法让我们用于判断悬浮窗权限,同时也没有跳转到设置界面进行开启的方法,因为此权限是默认开启的,但是有一些产商会修改它,所以在使用之前最好进行判断,以免使用时出现崩溃,判断方法是用反射的方式获取出是否开启了悬浮窗权限。在6.0以及以后的版本中,google为我们提供了判断方法和跳转界面的方法,直接使用Settings.canDrawOverlays(context)
就可以判断是否开启了悬浮窗权限,没有开启可以跳转到设置界面让用户开启。
需要配置的权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
Android9.xx
-
Android9通过下列变更简化通知渠道设置
屏蔽渠道组:现在,用户可以针对某个应用在通知设置中屏蔽整个渠道组。您可以使用 isBlocked()函数确定何时屏蔽一个渠道组,从而不会向该组中的渠道发送任何通知。此外,您的应用可以使用全新的 getNotificationChannelGroup()函数查询当前渠道组设置。
全新的广播 Intent类型:现在,当通知渠道和渠道组的屏蔽状态发生变更时,Android 系统将发送广播 Intent。 拥有已屏蔽的渠道或渠道组的应用可以侦听这些 Intent 并做出相应的回应。 有关这些 Intent 操作和 extra 的更多信息,请参阅 NotificationManager 参考中更新的常量列表。 有关响应广播 Intent 的信息,请参阅广播。
NotificationManager.Policy有3种新的“请勿打扰”优先级类别:
PRIORITY_CATEGORY_ALARMS优先处理警报。
PRIORITY_CATEGORY_MEDIA优先处理媒体源的声音,如媒体和语音导航。
PRIORITY_CATEGORY_SYSTEM优先处理系统声音。NotificationManager.Policy还有7种新的“请勿打扰”常量,可以用来抑制视觉中断:
SUPPRESSED_EFFECT_FULL_SCREEN_INTENT防止通知启动全屏 Activity。
SUPPRESSED_EFFECT_LIGHTS屏蔽通知灯。
SUPPRESSED_EFFECT_PEEK防止通知短暂进入视图(“滑出”)。
SUPPRESSED_EFFECT_STATUS_BAR防止通知显示在支持状态栏的设备的状态栏中。
SUPPRESSED_EFFECT_BADGE在支持标志的设备上屏蔽标志。
SUPPRESSED_EFFECT_AMBIENT在支持微光显示的设备上屏蔽通知。
SUPPRESSED_EFFECT_NOTIFICATION_LIST防止通知显示在支持列表视图(如通知栏或锁屏)的设备的列表视图中。
限制访问通话记录
Android 9 引入CALL_LOG
权限组并将READ_CALL_LOG
、WRITE_CALL_LOG
和PROCESS_OUTGOING_CALLS
权限移入该组。 在之前的 Android 版本中,这些权限位于 PHONE 权限组。
如果应用需要访问通话记录或者需要处理去电,则您必须向 CALL_LOG权限组明确请求这些权限。 否则会发生SecurityException
-
限制访问电话号码
- 在未首先获得
READ_CALL_LOG
权限的情况下,除了应用的用例需要的其他权限之外,运行于 Android 9 上的应用无法读取电话号码或手机状态。与来电和去电关联的电话号码可在手机状态广播(比如来电和去电的手机状态广播)中看到,并可通过PhoneStateListener
类访问。 但是,如果没有READ_CALL_LOG
权限,则PHONE_STATE_CHANGED
广播和PhoneStateListener
提供的电话号码字段为空。 - 要从手机状态中读取电话号码,请根据您的用例更新应用以请求必要的权限:
要通过PHONE_STATE
Intent操作读取电话号码,同时需要READ_CALL_LOG
权限和READ_PHONE_STATE
权限。
要从onCallStateChanged()
中读取电话号码,只需要READ_CALL_LOG
权限。 不需要READ_PHONE_STATE
权限。
- 在未首先获得
刘海屏适配
对使用非SDK接口的限制和适配策略
Build.SERIAL 始终设置为 "UNKNOWN" 以保护用户的隐私。
如果您的应用需要访问设备的硬件序列号,您应改为请求 READ_PHONE_STATE权限,然后调用 getSerial()。-
电话信息现在依赖设备位置设置
如果用户在运行 Android 9的设备上停用设备定位,则以下函数不提供结果:- TelephonyManager.getAllCellInfo()
- TelephonyManager.listen()
- TelephonyManager.getCellLocation()
- TelephonyManager.getNeighboringCellInfo()