Android 10 更新内容与适配
Posted ZhangQiang-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 10 更新内容与适配相关的知识,希望对你有一定的参考价值。
Android 10 更新内容与适配
功能更新与API
- 手机温度监控
- webview渲染程序检测
- 设置面板
- 快捷方式改进
- 深色主题
6. 其他拓展功能与API
跟随系统版本的变更内容
- 非SDK接口调用限制
- 手势导航
- WLAN直连广播不生效
- 旧版 android 系统为目标平台的应用的警告
Target 29 变更内容
- 全屏 Intent 的权限变更:USE_FULL_SCREEN_INTENT
- 后台位置权限
- 后台启动 Activity 的限制
- /proc/net 文件系统的访问权限限制
- 不可重置的设备标识符实施了限制
- 剪贴板数据的访问权限
- 启用和停用 WLAN 实施了限制
- 直接访问已配置的 WLAN 网络实施了限制
- 一些电话 API、蓝牙 API 和 WLAN API 需要精确位置权限
- 外部存储访问权限限制与适配
功能更新与API
1.手机温度监控(目前只在Pixel设备受支持)
在 Android 10 中,应用可以使用 Thermal API 监控设备变化情况,并在设备过热时采取措施维持低电耗状态,使设备恢复到正常温度。
PowerManager manager = (PowerManager) getSystemService(Context.POWER_SERVICE);
//监听手机热值状态
manager.addThermalStatusListener(new PowerManager.OnThermalStatusChangedListener()
@Override
public void onThermalStatusChanged(int status)
//温度改变时调用 常量 0-6 数值越大,温度越高
);
2.webview渲染程序检测
Android 10 引入了 WebViewRenderProcessClient 抽象类,应用可以使用该抽象类检测 WebView 是否无响应。
//WebView 渲染程序检测
WebView view;
view.setWebViewRenderProcessClient(new WebViewRenderProcessClient()
@Override
public void onRenderProcessUnresponsive(@NonNull WebView view,
@Nullable WebViewRenderProcess renderer)
//无响应时触发,webview是单进程时,renderer 为null
@Override
public void onRenderProcessResponsive(@NonNull WebView view,
@Nullable WebViewRenderProcess renderer)
//如果 WebView 仍然无响应,则系统会定期调用 onRenderProcessUnresponsive()
(频率不高于每 5 秒一次),
/ 但不会执行其他任何操作。如果 WebView 再次无响应,
系统只调用 onRenderProcessResponsive() 一次
);
功能更新与API
3.设置面板
Android 10 引入了“设置面板”,让应用能够在自身环境中向用户显示设置。这样一来,用户无需通过转到设置来更改 NFC 或移动数据等设置,而能继续留在原来的应用中。
使用方式:
//ACTION_INTERNET_CONNECTIVITY //网络链接设置
//ACTION_NFC NFC 设置界面
//ACTION_WIFI Wi-Fi设置界面
//ACTION_VOLUME 音量设置界面
Intent panelIntent = new Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY);
startActivityForResult(panelIntent, 0);
4.快捷方式改进
ShortcutManagerCompat 是一个新版 AndroidX API,它可以向后兼容旧版 DirectShare API。
使用isRequestPinShortcutSupported 判断是否可以添加快捷方式,并使用requestPinShortcut请求添加到桌面
5.深色主题
Android 10 (API 级别 29) 及更高版本中提供深色主题背景。
适配方案( Force Dark):
其主题背景中设置 android:forceDarkAllowed="true"
捕获播放的音频
共享音频输入
对点对点连接
跟随系统版本的变更内容
1.非SDK接口调用限制
在调用针对Android 9/10 的限制API,或者黑名单API时,会出现超出预期行为(抛出异常或返回NULL),直接影响后续操作与业务逻辑。
排查方法: 使用veridex工具命令:appcompat.sh --dex-file=**.apk --imprecise >> **.txt 导出结果数据到文件,结果如下:
#295: Reflection blacklist Landroid/bluetooth/BluetoothAdapter;->mContext potential use(s):
Lcom/hook/ViewInvocationHandler;->invoke(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
Lorg/hulk/mediation/pangolin/adapter/PangolinInterstitialAd$PangolinStaticInterstitialAd;->hookDialog(Lcom/bytedance/sdk/openadsdk/TTInteractionAd;Landroid/app/Activity;)V
Lorg/hulk/ssplib/SspInterstitialAdLoader;→(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V
526 in greylist //灰名单,即当前版本仍能使用的非SDK接口,但在下一版本中可能变成被限制的非SDK接口 ,不用关注
239 in blacklist //黑名单,使用了就会报错。项目中必须解决的非SDK接口
1216 in greylist-max-o 在targetSDK<=O中能使用,但是在targetSDK>O中被限制的非SDK接口
81 in greylist-max-p 在targetSDK<=P中能使用,但是在targetSDK>P中被限制的非SDK接口
从结果来看,扫描结果较多,但结果中重复且包含源码,三方SDK,Lint 库中黑名单API调用信息,所以只关注自己应用包名下的信息即可。
解决思路:
更改限制API的调用, 如果一定使用限制API使用,做try catch 处理,并做调用失败的业务逻辑处理
跟随系统版本的变更内容
2.手势导航
从 Android 10 开始,用户可以在设备中启用手势导航。用户启用后,手势导航会影响设备上的所有应用。例如,如果用户从屏幕边缘向内滑动,系统会将该手势解读为“返回”导航
3.WLAN直连广播不生效
WIFI_P2P_CONNECTION_CHANGED_ACTION
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
4.旧版 Android 系统为目标平台的应用的警告
在搭载 Android 10 或更高版本的设备上,如果用户首次运行以 Android 5.1(API 级别 22)或更低版本为目标平台的应用,则会看到警告。如果此应用要求用户授予权限,则系统会先向用户提供调整应用权限的机会,然后才会允许此应用首次运行。
Target 29 变更内容
1.全屏 Intent 发送通知的权限变更:USE_FULL_SCREEN_INTENT
权限需清单文件注册,系统自动授权,调用全屏通知会有以下两种场景:
1.如果用户设备被锁定,会显示全屏 Activity,覆盖锁屏。
2.如果用户设备处于解锁状态,通知以展开形式显示,其中包含用于处理或关闭通知的选项。
2.后台位置权限:ACCESS_BACKGROUND_LOCATION
*危险权限
Android 10 中增加后台定位权限,如果没有此权限,则该应用只能在前台或者前台服务(类型为location)时,才能获取到位置信息。
对应关系:
3.后台启动 Activity 的限制
从 Android 10 开始,系统会增加针对从后台启动 Activity 的限制,但下情景除外:
应用具有可见窗口,例如前台 Activity
应用的某个 Activity 刚在不久前启动
....
4./proc/net 文件系统的访问权限限制
Android 10 或更高版本的设备上,应用无法访问 /proc/net,其中包含与设备的网络状态相关的信息。
解决方案:
官方推荐使用NetworkStatsManager 或 ConnectivityManager 类。
5.不可重置的设备标识符实施了限制
从 Android 10 开始,应用必须具有 READ_PRIVILEGED_PHONE_STATE 特许权限才能访问设备的不可重置标识符(包含 IMEI 和序列号)。
*该权限为特许权限,google play 无法声明
影响接口:
Build
getSerial()
TelephonyManager
getImei()
getDeviceId()
getMeid()
getSimSerialNumber()
getSubscriberId()
强行调用影响:
A.如果应用以 Android 10 或更高版本为目标平台,则会发生 SecurityException。
B.如果应用以 Android 9(API 级别 28)或更低版本为目标平台,则相应方法会返回 null 或占位符数据(具有 READ_PHONE_STATE 权限)。否则,会发生 SecurityException。
6.剪贴板数据的访问权限
除非是输入法应用或者应用在前台,否则无法访问剪切板数据
7.启用和停用 WLAN 实施了限制
以 Android 10 或更高版本为目标平台的应用无法启用或停用 WLAN。WifiManager.setWifiEnabled() 方法始终返回 false。
解决方案:
跳转到设置页面,用户主动操作。
8.直接访问已配置的 WLAN 网络实施了限制
getConfiguredNetworks() //返回空列表
addNetwork() 和 updateNetwork()始终返回 -1
(removeNetwork()、reassociate()、enableNetwork()、disableNetwork()、reconnect() 和 disconnect())始终返回 false
。
使用 WifiNetworkSuggestion 对象。可以分别通过调用 addNetworkSuggestions() 和 removeNetworkSuggestions()
9.一些电话 API、蓝牙 API 和 WLAN API 需要精确位置权限
Android 10 或更高版本为目标平台,则它必须具有 ACCESS_FINE_LOCATION 权限才能使用 WLAN、WLAN 感知或蓝牙 API 中的一些方法
10.外部存储访问权限限制与适配
对于以 Android 10 及更高版本为目标平台的应用,其访问权限限定为应用私有目录。共有目录不再具有访问权限,并更改了一些其他细节限制:图片文件中地理位置信息默认不提供,查询MediaProvider 获得的DATA字段不再可靠,文件增加Pending 状态等。
解决方法:
A.兼容模式:
在清单文件application 中添加requestLegacyExternalStorage = true
该属性标记应用继续延续Android10以前的存储模式,对外部存储文件等依然有访问权限,但大概率在接下来的大版本中会废弃此方案。
B.适配方式(推荐):
1.文件读取
使用 MediaStore 接口访问公共目录中的多媒体文件,或使用SAF框架(System Access Framework)访问公共目录所有文件
a.使用SAF框架调用系统文件选择器进行文件获取,在应用onActivityResult中获取到文件URI,间接拿到文件的IO流或DocumentFile对象进行操作。
b.使用SAF向用户申请文件或者目录的读写权限(后面介绍)
2.文件创建
a.使用SAF框架在任意目录创建文件(用户手动选择目录),在activityResult返回中获取文件Uri,以来文件uri进行文件IO写入操作。
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
// 文件类型
intent.setType("text/plain");
// 文件名称
intent.putExtra(Intent.EXTRA_TITLE, filename);
startActivityForResult(intent, WRITE_REQUEST_CODE);
b.使用SAF向用户申请目录读写权限(后面介绍)
3.文件写入
同(文件创建)
4.文件删除
a.有SD读写权限,明确知道文件路径,使用File.delete 依然可以使用
b. 如果文件是媒体文件(且是应用自身创建的文件),MediaStore 获取文件Uri,可以删除。
c.使用SAF框架向用户申请目录的读写权限(后面介绍)
共有目录的操作权限申请与适配
Android 并不是完全限制用户读取外部访问,而是给用户了选择行,由用户来判断是否需要向应用授权共有目录读写。
a. 权限的申请
使用SAF框架进行文件或者文件夹的授权,代码如下
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_FOR_DIR);
在activityResult
final int takeFlags = data.getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(data.getData(), takeFlags);
// 保存获取的目录权限
SharedPref.setString(this, "uriTree", data.getData().toString());
DocumentFile file = DocumentFile.fromTreeUri(this, data.getData());
B.权限的生命周期
在手机重启后,应用就丢失了该目录的操作权限,所以要保存目录uri到本地文件。
C.权限的判断
//获取所有授权文件列表
getContentResolver().getPersistedUriPermissions();
//判断授权列表中是否包含本地存储uri,是否有读写权限
if(item.equals("本地存储uri")&&
item.isReadPermission()&&item.isWritePermission())
DocumentFile操作:
SAF授权用户文件权限后,依赖Uri进行文件权限的操作:
DocumentFile file = DocumentFile.fromTreeUri(this, data.getData());
DocumentFile file = DocumentFile.fromTreeUri(this, data.getData());
file.listFiles();//获取子文件/文件夹
file.getName();//获取文件/文件夹名称
file.delete();//删除文件
file.createFile()//创建文件;
以上是关于Android 10 更新内容与适配的主要内容,如果未能解决你的问题,请参考以下文章