Android 10 更新内容与适配

Posted ZhangQiang-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 10 更新内容与适配相关的知识,希望对你有一定的参考价值。

Android 10 更新内容与适配


功能更新与API

  1. 手机温度监控
  2. webview渲染程序检测
  3. 设置面板
  4. 快捷方式改进
  5. 深色主题

6. 其他拓展功能与API
 

跟随系统版本的变更内容

  1. 非SDK接口调用限制
  2. 手势导航
  3. WLAN直连广播不生效
  4. 旧版 android 系统为目标平台的应用的警告

 

Target 29 变更内容

  1. 全屏 Intent 的权限变更:USE_FULL_SCREEN_INTENT
  2. 后台位置权限
  3. 后台启动 Activity 的限制
  4. /proc/net 文件系统的访问权限限制
  5. 不可重置的设备标识符实施了限制
  6. 剪贴板数据的访问权限
  7. 启用和停用 WLAN 实施了限制
  8. 直接访问已配置的 WLAN 网络实施了限制
  9. 一些电话 API、蓝牙 API 和 WLAN API 需要精确位置权限
  10. 外部存储访问权限限制与适配

 

 

 

 

功能更新与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"

 

6.其他拓展功能与API


捕获播放的音频

 

共享音频输入

 

对点对点连接

 

跟随系统版本的变更内容

 

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接口
       从结果来看,扫描结果较多,但结果中重复且包含源码,三方SDKLint 库中黑名单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 更新内容与适配的主要内容,如果未能解决你的问题,请参考以下文章

Android MVVM框架使用(十三)UI更新 (App启动白屏优化适配Android10.0深色模式)

Android深色模式适配-想法1.0

iOS深色模式适配

带有远程视图的 Android 10 上的黑暗通知

谈谈Flutter适配深色模式

谈谈Flutter适配深色模式