Android 10, 30, Q
Android 10 适配攻略
1.Scoped Storage(分区存储)
外部存储空间分为了三部分:
- 特定目录(App-specific),使用getExternalFilesDir()或 getExternalCacheDir()方法访问。无需权限,且卸载应用时会自动删除。
- 照片、视频、音频这类媒体文件。使用MediaStore 访问,访问其他应用的媒体文件时需要READ_EXTERNAL_STORAGE权限。
- 其他目录,使用存储访问框架SAF(Storage Access Framwork)
*:最简单粗暴的方法是请求使用旧的存储模式,在AndroidManifest.xml中添加 android:requestLegacyExternalStorage="true"。
但不推荐此方法。因为在下一个版本的Android中,此条配置将会失效,将强制采用外部储存限制
2.权限变化
1.在后台运行时访问设备位置信息需要权限
Android 10 引入了 ACCESS_BACKGROUND_LOCATION 权限(危险权限)。
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
该权限允许应用程序在后台访问位置。如果请求此权限,则还必须请求ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION权限。只请求此权限无效果。
官方推荐使用前台服务来实现,在前台服务中获取位置信息。
- 在清单中对应的service中添加 android:foregroundServiceType="location"
- 启动前台服务前检查是否具有前台的访问权限
2.一些电话、蓝牙和WLAN的API需要精确位置权限
Android 10中必须具有 ACCESS_FINE_LOCATION 权限才能使用类和方法,电话:TelephonyManager、WLAN:WifiManager、蓝牙:BluetoothAdapter
3.后台启动 Activity 的限制
- 应用在前台任务的返回栈中已有的 Activity
- 应用收到系统的 PendingIntent 通知。
- 用户已向应用授予 SYSTEM_ALERT_WINDOW 权限,或是在应用权限页开启后台弹出页面的开关。
对于全屏 intent,注意设置最高优先级和添加USE_FULL_SCREEN_INTENT权限
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>
4.深色主题
适配方法有两种:
- 手动适配(资源替换)
- 自动适配(Force Dark)
判断深色主题是否开启
其实和上面onConfigurationChanged方法同理:
public static boolean isNightMode(Context context) {
int currentNightMode = context.getResources().getConfiguration().uiMode &
Configuration.UI_MODE_NIGHT_MASK;
return currentNightMode == Configuration.UI_MODE_NIGHT_YES;
}
5.标识符和数据
- 对不可重置的设备标识符实施了限制,受影响的方法包括:Build、TelephonyManager 从 Android 10 开始,应用必须具有 READ_PRIVILEGED_PHONE_STATE 特许权限才能正常使用以上这些方法。
- 限制了对剪贴板数据的访问权限
- 对启用和停用 WLAN 实施了限制
Android 11, 30, R
Android 11 变更及适配攻略
1.存储机制更新
Scoped Storage(分区存储)
android:requestLegacyExternalStorage="true"的适配方式已不起作用
Android 11上直接使用File API访问媒体文件
官方强烈建议直接使用 MediaStore API
存储访问框架 (SAF)变更
Android 11对SAF添加以下限制:
使用 ACTION_OPEN_DOCUMENT_TREE 或 ACTION_OPEN_DOCUMENT,无法浏览到Android/data/ 和 Android/obb/目录及其所有子目录。
使用 ACTION_OPEN_DOCUMENT_TREE无法授权访问存储根目录、Download文件夹。
2.权限变化
单次权限授权
请求位置权限
Android 11中请求弹框取消“始终允许”,也就是说默认不会授予你后台访问设备位置信息的权限
软件包可见性
前台服务类型
Android 10中,在前台服务访问位置信息,需要在对应的service中添加 location 服务类型。
同样的,Android 11中,在前台服务访问摄像头或麦克风,需要在对应的service中添加camera或microphone 服务类型。
<manifest>
...
<service
android:name="MyService"
android:foregroundServiceType="microphone|camera" />
</manifest>
这一限制的变更,使得程序无法在后台启动服务访问摄像头和麦克风。如需使用,只能是前台开启前台服务。除非有如下情况:
- 服务由系统组件启动。
- 服务是通过应用小部件启动。
- 服务是通过与通知交互启动的。
- 服务是PendingIntent启动的,它是从另一个可见的应用程序发送过来的。
- 服务由一个应用程序启动,该应用是一个DPC,且在设备所有者模式下运行。
- 服务由一个提供VoiceInteractionService的应用启动。
- 服务由一个具有START_ACTIVITIES_FROM_BACKGROUND权限的应用启动。
权限自动重置
读取手机号
3.其他行为变更
自定义view的Toast
从后台发送自定义view的Toast消息系统会进行屏蔽。前台使用不受影响。
APK签名
v1 签名的应用无法在Android 11的设备上安装或更新。必须使用v2或更高版本进行签名,
同时Android 11 添加了对 APK 签名方案 v4 的支持
AsyncTask
AsyncTask在Android 11已经不建议使用,建议迁移至kotlin的协程。
此外Handler未指定Looper的构造方法也已不建议使用。
建议明确指定Looper:
private Handler handler = new Handler(Looper.myLooper());
// 或
private Handler handler = new Handler(Looper.getMainLooper());
状态栏高度
targetSdkVersion 30,获取状态栏高度为0,低于30获取值正常。。。需要使用WindowMetrics适配
4.新增工具
兼容性调试工具
无线调试