一、隐私权:
1、分区存储
过滤视图
为了让用户更好地控制自己的文件,减少文件混乱情况,Android Q 更改了应用对设备外部存储设备中的文件(例如存储在路径 /sdcard 下的文件)的访问方式。
如果应用以 Android Q 为目标平台,则在访问外部存储设备中的文件时会进入过滤视图,此时只能查看特定目录(Context.getExternalFilesDir())和特定类型的文件
1、 访问自己创建的文件:始终拥有读/写权限,无论文件位于特定目录以内还是以外
2、 访问其他应用创建的文件,需满足:
a)已获得 READ_EXTERNAL_STORAGE 权限
b)文件位于一个明确定义的媒体集合(MediaStore)中:照片 (Images )、视频(Video)、音乐文件(Audio)
3、 访问另一应用创建的任何其他文件(包括“downloads”目录下的文件),必须使用存储访问框架(SAF),用户可以通过该框架选择特定文件
SAF文档:使用“存储访问框架”打开文件 | Android 开发者 | Android Developers
4、 过滤视图对媒体数据的限制:如未获取新的ACCESS_MEDIA_LOCATION权限,则无法查看照片的位置信息等元数据
-
情形1:卸载后保留应用的文件
如果应用在访问外部存储设备中的文件时是过滤视图,那么卸载该应用时,系统会清除特定于该应用的目录中的所有文件。
a) 如果需要卸载后保留文件,需要保存到媒体集合( MediaStore )中
b) 需要在应用的AndroidManifest.xml文件增加:<application android:hasFragileUserData="true"/>,否则应用数据会被直接删除,设置后会提示是否删除
-
情形2:分享媒体文件
某些应用允许用户彼此分享媒体文件。例如,用户可以通过社交媒体应用与朋友分享照片和视频。而分享后可能提示文件不存在。
应用使用路径方式(file:// URI)分享文件,其他应用访问时可能提示文件不存在
建议使用FileProvider适配(content://URI)
2、设备位置
1. Q之前只有ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION;
2. Q新增加了后台定位权限:ACCESS_BACKGROUND_LOCATION,该权限对应始终允许;老的权限:ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION代表仅前台使用允许;
3. 应用的targetSdkVersion<Q,谷歌提供了兼容性方案,只要应用申请了老的位置权限ACCESS_FINE_LOCATION或者ACCESS_COARSE_LOCATION,会默认请求ACCESS_BACKGROUND_LOCATION权限,动态授权弹框参考:
4. 应用的TargetSdkVersion>=Q,如果应用必须要始终定位,可以只申请ACCESS_BACKGROUND_LOCATION即可;s
如果应用只需要申请前台定位,则只需要申请老的定位权限即可;如果都申请则出现三态权限弹框
5. 如果用户选择仅前台使用允许,应用的页面退后台,通过启动前台服务让应用处于前台状态,必须把前台服务标为:foregroundServiceType=“location”,才能获取位置信息。
3、后台应用启动
针对在没有用户互动的情况下从后台启动活动的新限制。
特性说明:
Android Q 对应用可启动 Activity 的时间施加了限制。此项行为变更有助于最大限度地减少对用户造成的中断,并且可以让用户更好地控制其屏幕上显示的内容。
只要应用启动 Activity 是因用户互动直接引发的,该应用就极有可能不会受到此项变更的影响。
允许 Activity 启动的条件
在 Android Q 上运行的应用只有在满足以下一个或多个条件时才能启动 Activity:
- 该应用具有可见窗口,例如在前台运行的 Activity。
注意:为了启动 Activity,前台服务不会将应用限定为在前台运行。 - 该应用在前台任务的返回栈中具有一项 Activity。
- 该应用具有最近启动的 Activity。
- 该应用对最近的一项 Activity 调用了 finish()。这仅适用于在调用 finish() 时,应用在前台中具有一项 Activity,或在前台任务的返回栈中具有一项 Activity 的情况。
- 该应用的一项服务被系统绑定。该条件仅适用于以下服务(可能需要启动界面):AccessibilityService、AutofillService、CallRedirectionService、HostApduService、InCallService、TileService、VoiceInteractionService 以及 VrListenerService。
- 该应用的某一项服务被其他可见应用绑定。请注意,绑定到该服务的应用必须在后台对该应用保持可见,才能成功启动 Activity。
- 该应用会从系统收到通知 PendingIntent。如果存在针对服务和广播接收器的待定 intent,则该应用可以在待定 intent 发送后启动 Activity 几秒钟时间。
- 该应用会收到从其他可见应用发送的 PendingIntent。
- 该应用会收到系统广播,其中要求应用启动界面。示例包括 ACTION_NEW_OUTGOING_CALL 和 SECRET_CODE_ACTION。该应用可以在广播发送后启动 Activity 并持续几秒钟时间。
- 该应用已通过 CompanionDeviceManager API 与配套硬件设备相关联。借助此 API,该应用可以启动 Activity 以响应用户在配对设备上执行的操作。
- 该应用是在设备所有者模式下运行的设备政策控制器。示例用例包括完全托管的企业设备,以及数字标识牌和自助服务终端等专属设备。
- 该应用已获得用户授予的 SYSTEM_ALERT_WINDOW 权限。
4、禁止应用读取Device ID
Q版本将限制应用访问不可重设的设备识别码,如 IMEI、序列号等,所有获取设备识别码的接口都增加了新的权限:READ_PRIVILEGED_PHONE_STATE,该权限需要系统签名的应用才能申请,意味着三方应用无法获取设备识别码
(1)TargetSdkVersion<Q并且没有申请READ_PHONE_STATE权限,或者TargetSdkVersion>=Q,获取device id会抛异常SecurityException;
(2)TargetSdkVersion<Q并且申请了READ_PHONE_STATE,通过getDeviceId接口读取的值为Null;
(3)无法获取到device id,会对应用依赖device id的功能产生影响。
解决方案:
1. 谷歌提供的适配指导文档。
唯一标识符最佳做法:唯一标识符最佳做法 | Android 开发者 | Android Developers
官方文档:Android 10 中的隐私权变更 | Android 开发者 | Android Developers
2. 开发者可以尝试使用Android ID替换Device ID。
(1)获取代码:Settings.System.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
(2)Android ID和Device ID的区别:
(a)手机恢复出厂设置,Android ID可以重置,但是Device ID无法重置;
(b)对于安装在运行 Android 8.0 的设备上的应用,ANDROID_ID 的值现在将根据应用签署密钥和用户确定作用域。应用签署密钥、用户和设备的每个组合都具有唯一的 ANDROID_ID 值。因此,在相同设备上运行但具有不同签署密钥的应用将不会再看到相同的 Android ID(即使对于同一用户来说,也是如此),具体可参考O版本的变更:https://developer.android.com/about/versions/oreo/android-8.0-changes#privacy-all。
老的READ_PHONE_STATE权限整改
由于获取device id权限的变更,通过申请老的READ_PHONE_STATE已经无法获取device id信息,所以如果应用申请敏感权限READ_PHONE_STATE的目的仅仅是为了获取device id,建议代码中增加版本判断,判断如果仅当运行的手机版本是Q以前的版本,才申请用户动态授权,否则申请的权限没有用
5、MAC 地址
为了进一步保护用户的隐私,Android Q在连接Wi-Fi时,默认启用了Mac地址随机化的特性,如果APP不进行适配,使用原来方式获取到的Mac地址可能是随机生成的,并不是真实的Mac地址。
如果APP需要使用Mac地址作为设备的标识,无论您的Target SDK是否设置为Q,只要运行在Android Q上,您就需要进行适配。
6、访问剪贴板数据
除非应用是默认输入法 (IME) 或是目前处于焦点的应用,否则无法访问剪贴板数据
7、访问 /proc/net 文件系统
Android Q 撤消了 /proc/net 访问权限,其中包含有关设备网络状态的信息。需要访问此信息的应用(如 VPN)应引用 NetworkStatsManager 和 ConnectivityManager 类。
8、摄像头和连接性
针对完整摄像头元数据的访问权限实施了新限制,并且现在许多连接工作流都需要精确位置权限。
9、访问相机信息需要获得权限
Android Q 更改了 getCameraCharacteristics() 方法默认返回的信息的广度。具体而言,您的应用必须具有 CAMERA 权限才能访问此方法的返回值中可能包含的设备特定元数据。
10、对启用和停用 WLAN 的限制
以 Android Q 为目标平台的应用无法启用或停用 WLAN。WifiManager.setWifiEnabled()
方法始终返回 false
。
11、电话,Wi-Fi,蓝牙API所需的精确位置权限
1. 应用的targetSdkVersion>=Q:除非应用具有ACCESS_FINE_LOCATION权限,否则在Android Q上运行时,应用无法在Wi-Fi,Wi-Fi Aware或蓝牙API中使用多种方法。
2. 应用的targetSdkVersion<Q:不受影响,只需要申请ACCESS_COARSE_LOCATION或者ACCESS_FINE_LOCATION即可
3. 具体影响的接口有:
Telephony
-
-
- TelephonyManager
getCellLocation()
getAllCellInfo()
requestNetworkScan()
requestCellInfoUpdate()
getAvailableNetworks()
getServiceStateForSubscriber
getServiceState()
- TelephonyScanManager
- TelephonyScanManager.NetworkScanCallback
- PhoneStateListener
- TelephonyManager
-
-
-
requestNetworkScan()
-
-
-
onResults()
-
-
-
onCellLocationChanged()
onCellInfoChanged()
onServiceStateChanged()
-
WLAN
-
-
-
startScan()
getScanResults()
getConnectionInfo()
getConfiguredNetworks()
-
-
Bluetooth
-
-
-
startDiscovery()
startLeScan()
LeScanCallback()
-
-
二、权限变更
1、限制对屏幕内容的访问
为了保护用户的屏幕内容,Android Q 更改了 READ_FRAME_BUFFER
、CAPTURE_VIDEO_OUTPUT
和 CAPTURE_SECURE_VIDEO_OUTPUT
权限的作用域,使其只能通过签名访问,从而禁止以静默方式访问设备的屏幕内容。
需要访问设备屏幕内容的应用应使用 MediaProjection API,此 API 会显示提示,要求用户同意声明。
2、面向用户的权限检查(针对旧版应用)
如果您的应用以 Android 5.1(API 级别 22)或更低版本为目标平台,则当用户首次在 Android Q 上运行该应用时,他们会看到一个权限屏幕,如图 1 所示。此屏幕可以让用户撤消系统先前在安装时授予您应用的访问权限。
3、身体活动识别
新增敏感权限:ACTIVITY_RECOGNITION,Android Q为需要检测用户移动的应用程序(例如步行,骑自行车或车辆)引入了新的ACTIVITY_RECOGNITION运行时权限。注意:除非用户已授予您的应用此权限,否则Google Play服务中的某些库(例如活动识别API)不会提供结果。该特性只影响TargetSdkVersion>=Q的应用
三、非SDK接口管控
1、非SDK接口的定义
SDK接口:https://developer.android.com/reference/packages,能查到的接口都是SDK接口;
非SDK接口:除了谷歌开放的SDK接口之外的其他JAVA接口都是非SDK接口。
2、应用滥用非SDK接口的危害
这些非SDK接口在大版本之间的变化可能很频繁,带来兼容性问题。
名单类型 |
影响 |
greylist |
targetSDK>=P时,警告。 |
greylist-max-o |
targetSDK<P时,警告;>=P时,不允许调用。 |
greylist-max-p |
targetSDK<Q时,警告;>=Q时,不允许调用。 |
blacklist |
所有三方应用不允许调用。 |
3、影响范围
所有三方应用都可能会受到影响,从名单变化来看,黑名单接口大大增加,Q版本有很多非SDK接口被删除,都会导致应用出现兼容性问题,影响评估很大,需要所有应用排查和整改。
4、检查应用的非SDK接口
- 构建targetSdkVersion为Q的可调式应用
- adb logcat ---- “Accessing hidden field Landroid/os/Message…”
- 使用StrictMode API
- detectNonSdkApiUsage() + penaltyListener()
- 处理onVmViolation回调
- Veridex静态分析工具
- AOSP 中提供源代码及预编译可执行文件
- 跟随每次Q Beta 版本发布更新
- 不支持JNI调用,对反射调用的检测结果不完全准确