前几天手一痒,把项目的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)