先介绍一下两个框架:
一款用于在Android设备上获取照片(拍照或从相册、文件中选择)、裁剪图片、压缩图片的开源工具库
免费的应用托管平台|App应用众测分发
1 Android7.0及以上拍照时,由于出于安全考虑,Android 7.0[API24]以及以上版本不支持file://,使用content://URI
详见:Android7.0拍照失败FileUriExposedException
因此TakePhoto作为一款主打拍照的框架自然也适配了Android7.0.使用了android.support.v4.content.FileProvider。
2 蒲公英平台在应用自动更新时,需要获取下载在Download文件夹下的apk安装包。为了提高私有文件的安全性,面向 Android 7.0 或更高版本的应用私有目录被限制访问。
官方文档:Android7.0 - 系统权限更改(上面说到拍照需要用FileProvider也是这个原因)
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
provider>
对!你没有看错,蒲公英中并没有把android.support.v4.content.FileProvider的注册写死,需要我们在自己的项目里配置。TakePhoto虽然在一定程度上使用了模板化代码的写法(${applicationId}),但终究是写在了框架中了。因此就是在这里受到了限制。
<resources>
<paths>
<root-path path="" name="camera_photos" />
paths>
resources>
<paths>
<external-path
name="files_root"
path="Android/data/com/pgyersdk" />
<external-path
name="external_storage_root"
path="." />
paths>
其实内容道无所谓,可以合并。主要还是文件名不同。由于前面看AndroidManifest.xml中看到TakePhoto是写死的,蒲公英是可以自定义的。那么这次要用TakePhoto的文件名。
<resources>
<paths>
<root-path
name="camera_photos"
path="" />
<external-path
name="files_root"
path="Android/data/com/pgyersdk" />
<external-path
name="external_storage_root"
path="." />
paths>
resources>
现在可以把AndroidManifest.xml的android.support.v4.content.FileProvider搞定了。基于前面的的结论,一切以TakePhoto为主。那么在自己项目的AndroidManifest.xml中应该这么写:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.relish.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/file_paths"
tools:replace="name,resource" />
provider>
还没结束,还有注意在调用蒲公英的应用更新的代码时,:
PgyUpdateManager.register(MainActivity.this, "com.example.relish.fileprovider",//这里填写注册在Manifest.xml里android:authorities中的值
new UpdateManagerListener() {
@Override
public void onUpdateAvailable(final String result) {
// 将新版本信息封装到AppBean中
final AppBean appBean = getAppBeanFromString(result);
new AlertDialog.Builder(MainActivity.this)
.setTitle(R.string.update)
.setMessage(getString(R.string.latest_version) + appBean.getVersionName() + "\n"
+ appBean.getReleaseNote())
.setNegativeButton(
R.string.ensure,
(dialog, which) -> startDownloadTask(
MainActivity.this,
appBean.getDownloadURL())).show();
}
@Override
public void onNoUpdateAvailable() {
}
});
这样就大功告成了。