前幾天手一癢,把項目的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)