GB 移动小组

FileUriExposedException异常处理

2017-03-15  本文已影响108人  寒冬_腊月

前几天手一痒,把项目的targetSdkVersion改成最新的25, 今天打开App,发现拍照功能不正常, 网上查了很多资料,总结如下:

官方对FileUriExposedException的解释

The exception that is thrown when an application exposes a file:// Uri to another app. This exposure is discouraged since the receiving app may not have access to the shared path. For example, the receiving app may not have requested the READ_EXTERNAL_STORAGE runtime permission, or the platform may be sharing the Uri across user profile boundaries.Instead, apps should use content:// Uris so the platform can extend temporary permission for the receiving app to access the resource.This is only thrown for applications targeting N or higher. Applications targeting earlier SDK versions are allowed to share file:// Uri, but it's strongly discouraged.

解决步骤

step 1:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    <application
        ...
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>
    </application>
</manifest>

step 2:
添加 provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="cache" path="."/>
</paths>

step 3:

 Intent intentTmp = new Intent("android.media.action.IMAGE_CAPTURE");
                    intentTmp.putExtra(MediaStore.EXTRA_OUTPUT,
                            getCaptureImageOutputUri(mContext));
                    intentTmp.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    startActivityForResult(intentTmp, REQUESTCODE_FROM_CAMERA);
 public Uri getCaptureImageOutputUri(@NonNull Context context) {
        Uri outputFileUri = null;
        File getImage = context.getExternalCacheDir();
        if (getImage != null) {
            if (Build.VERSION.SDK_INT >= 24) {
                outputFileUri = FileProvider.getUriForFile(context,
                        context.getApplicationContext().getPackageName() + ".provider",
                        new File(getImage.getPath(), photoNameString));
            } else {
                outputFileUri = Uri.fromFile(new File(getImage.getPath(), photoNameString));
            }
        }

        return outputFileUri;
    }

ps:上面的代码如果不做if (Build.VERSION.SDK_INT >= 24)这个判断,会出现下面权限问题

 Caused by: java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{4293c3b8 3545:com.android.camera/u0a9} (pid=3545, uid=10009) that is not exported from uid 10056
       at android.os.Parcel.readException(Parcel.java:1425)
       at android.os.Parcel.readException(Parcel.java:1379)
       at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:2354)
       at android.app.ActivityThread.acquireProvider(ActivityThread.java:4292)
       at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:1749)

参考:

Google 官网
Stackoverflow

上一篇 下一篇

猜你喜欢

热点阅读