关于Bugly版本兼容Android7.0 FileProvider与PhotoPicker冲突问题

    xiaoxiao2021-03-25  101

    前几天小米5也推送了基于android7.0的MIUI8.2.1版本。相信后面将会越来越多的手机升级到这个版本。做为android开发者,即将面对的也就是兼容android7.0系统。这不,说着兼容,问题就来了。项目中使用的bugly版本更新出现了bug,一直重复下载新版本。通过bugly的SDK说明,我们可以看到,需要配置FileProvider

    显然,FileProvider是android7.0引入的新特性。

    通过官网说明我们知道,FileProvider是contentProvider一个特殊子类,它的作用是加强访问一个应用文件的安全性。意思也就是不通过FileProvider获取uri,通过以前的file:///Uri访问就会报错了。

    例如,访问相册的时候,以前的写法

    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File file = createImageFile(); Uri photoFile = Uri.fromFile(file); if (photoFile != null) { takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoFile);

    这段代码在android7.0以下版本是没啥问题的,但是在android7.0运行会遇到FileUriExposedException异常。

    显然就要按android7.0说明的方式配置FileProvider,然后再android7.0的系统通过FileProvider. getUriForFile()获取

    首先是在manifest.xml配置provider

    <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/__picker_provider_paths"/> </provider>

    然后在res下面创建xml目录,同时在xml目录创建配置的__picker_provider_paths.xml文件

    <paths> <external-path name="external_storage_root" path="."/> <files-path name="files" path="."/> </paths>

    然后上面的Uri通过FileProvider获取

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { String authority = mContext.getApplicationInfo().packageName + ".fileProvider"; photoFile = FileProvider.getUriForFile(this.mContext.getApplicationContext(), authority, file); } else { photoFile = Uri.fromFile(file); }

    上面是以PhotoPicker获取相册照片代码为例,但是如果我们再在app的manifest.xml按bugly官网配置的话,这要项目就会build报错,

    原因是fileProvider对应一个应用是唯一的,所以我们可以通过以下配置解决

    <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileProvider" android:exported="false" android:grantUriPermissions="true" tools:replace="name,authorities,exported,grantUriPermissions"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" tools:replace="name,resource"/> </provider>

    然后把PhotoPicker的xml配置copy到app的provider_path.xml

    <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- /storage/emulated/0/Download/${applicationId}/.beta/apk--> <external-path name="beta_external_path" path="Download/${applicationId}/.beta/apk"/> <!--/storage/emulated/0/Android/data/${applicationId}/files/apk/--> <external-path name="beta_external_files_path" path="Android/data/${applicationId}/files/apk/"/> <external-path name="external_storage_root" path="."/> <files-path name="files" path="."/> </paths>

    这样就解决了它两的冲突问题,通过tools:replace替换掉其他的provider配置。同时photoPicker的manifest不配置配置都无所谓了。但是photoPicker源码里面配置的是

    android:authorities="${applicationId}.provider" String authority = mContext.getApplicationInfo().packageName + ".provider";

    这要就不得不改下源码了,把provider改成fileProvider了。

    注意

    加上混淆代码

    #bugly -dontwarn com.tencent.bugly.** -keep public class com.tencent.bugly.**{*;} -keep class android.support.**{*;}

    使用了资源混淆AndResGuard框架的还要在白名单里面加上

    whiteList = ["R.string.strUpgradeDialog*"]

    一定要加上这几句混淆代码和白名单,要不然还是一样循环下载

    转载请注明原文地址: https://ju.6miu.com/read-36001.html

    最新回复(0)