TakePhoto和蒲公英(pgyer)的android.support.v4.content.FileProvider冲突

一 前言

先介绍一下两个框架:

1 TakePhoto

一款用于在Android设备上获取照片(拍照或从相册、文件中选择)、裁剪图片、压缩图片的开源工具库

2 蒲公英

免费的应用托管平台|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也是这个原因)

三 解决方案

1 先看看对比二者的AndroidManifest.xml:

TakePhoto:

<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>
蒲公英:
<!-- <provider -->
<!-- android:name="android.support.v4.content.FileProvider" -->
<!-- android:authorities="com.pgyersdk.fileProvider" -->
<!-- android:exported="false" -->
<!-- android:grantUriPermissions="true"> -->
<!-- <meta-data -->
<!-- android:name="android.support.FILE_PROVIDER_PATHS" -->
<!-- android:resource="@xml/provider_paths" /> -->
<!-- </provider> -->

对!你没有看错,蒲公英中并没有把android.support.v4.content.FileProvider的注册写死,需要我们在自己的项目里配置。TakePhoto虽然在一定程度上使用了模板化代码的写法(${applicationId}),但终究是写在了框架中了。因此就是在这里受到了限制。

2 再看两者的provider.xml文件

TakePhoto:(file_paths.xml)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <root-path path="" name="camera_photos" />
    </paths>
</resources>

蒲公英:(provider_paths.xml)

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="files_root"
        path="Android/data/com/pgyersdk" />
    <external-path
        name="external_storage_root"
        path="." />
</paths>

其实内容道无所谓,可以合并。主要还是文件名不同。由于前面看AndroidManifest.xml中看到TakePhoto是写死的,蒲公英是可以自定义的。那么这次要用TakePhoto的文件名。

合并后的xml文件(file_paths.xml)

<?xml version="1.0" encoding="utf-8"?>
<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() {
             }
         });

这样就大功告成了。

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
### 回答1: 我可以提供一些建议,但具体实现取决于你的技术能力和小程序的要求。可以尝试使用HTML5的canvas对象,用它的drawImage方法从相机获取图片,然后再使用toDataURL方法将图像转换为base64编码。 ### 回答2: 微信小程序开发中,CameraContext.takePhoto()是用于拍摄照片的方法。 首先,我们需要先创建一个CameraContext对象,通过wx.createCameraContext()方法进行创建。然后,调用takePhoto()方法拍摄照片。拍摄完成后,一个图片文件的临时路径将返回给我们,可以使用这个路径进行后续的操作,比如显示照片或上传到服务器。 使用CameraContext.takePhoto()方法时,可以传入一个对象作为参数,用于指定拍摄照片的配置。这个对象可以包含参数如下: - quality: 设置照片的质量,范围为0-1,默认为1。 - success: 当拍摄照片成功时的回调函数。 - fail: 当拍摄照片失败时的回调函数。 - complete: 无论拍摄照片成功或失败,都会调用的回调函数。 例如,我们可以在点击拍照按钮时调用CameraContext.takePhoto()方法拍摄照片,并将照片临时路径存储到data中: ```javascript // 创建CameraContext对象 const cameraContext = wx.createCameraContext(); // 拍照按钮点击事件 takePhoto: function() { cameraContext.takePhoto({ // 设置照片质量为高质量 quality: 1, success: (res) => { // 拍照成功,将照片临时路径存储到data中 this.setData({ photoPath: res.tempImagePath }); }, fail: (err) => { // 拍照失败的处理逻辑 console.error("拍照失败", err); } }); } ``` 以上就是使用CameraContext.takePhoto()方法进行拍照的简单示例。根据实际需求,我们可以根据返回的照片临时路径进行后续的处理。 ### 回答3: 微信小程序开发中,可以使用CameraContext.takePhoto()方法来拍摄照片。该方法可以调用摄像头进行拍照操作,并将拍摄后的照片保存到相册或临时文件夹中。 使用该方法前,需要先创建一个CameraContext实例,并指定摄像头类型。然后通过调用takePhoto()方法来触发拍摄照片的操作。在方法中可以设置参数,如quality表示照片质量,success表示成功回调函数,fail表示失败回调函数。 通过这个方法,我们可以实现微信小程序中的拍照功能。用户只需要点击拍照按钮,就可以调用takePhoto()方法进行拍照,然后获取并保存照片。 在拍摄成功后,可以通过success回调函数来处理照片的相关操作,如在页面上显示照片预览,或者将照片上传到服务器等。 总结来说,微信小程序开发中的CameraContext.takePhoto()方法是拍摄照片的核心方法,通过调用该方法可以实现拍照功能,并对拍摄后的照片进行一系列的处理操作,为用户提供更好的使用体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值