通过 ClipData.Item.getUri 暴露在应用程序之外

在 Android 文件系统中添加了新功能之后,我试图修复一个问题,但是我得到了这个错误:

android.os.FileUriExposedException: file:///storage/emulated/0/MyApp/Camera_20180105_172234.jpg exposed beyond app through ClipData.Item.getUri()

所以我希望有人能帮我解决这个问题:)

谢谢

private Uri getTempUri() {
// Create an image file name
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
String dt = sdf.format(new Date());
imageFile = null;
imageFile = new File(Environment.getExternalStorageDirectory()
+ "/MyApp/", "Camera_" + dt + ".jpg");
AppLog.Log(
TAG,
"New Camera Image Path:- "
+ Environment.getExternalStorageDirectory()
+ "/MyApp/" + "Camera_" + dt + ".jpg");
File file = new File(Environment.getExternalStorageDirectory() + "/MyApp");
if (!file.exists()) {
file.mkdir();
}
imagePath = Environment.getExternalStorageDirectory() + "/MyApp/"
+ "Camera_" + dt + ".jpg";
imageUri = Uri.fromFile(imageFile);
return imageUri;
}
113374 次浏览

在开始相机或文件浏览之前添加以下代码块

    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());

请参考转介链接 严格模式及其解释所有的使用和技术细节。

对于 sdk24及以上版本,如果您需要获取应用程序存储之外的文件的 Uri,则会出现这个错误。
Del Solutions 允许您更改策略以允许这样做,并且它工作得很好。 < br > < br > 但是,如果你想遵循谷歌的指导方针,而不必改变应用程序的 API 策略,你必须使用一个 FileProvider。

首先,要获取文件的 URI,您需要使用 FileProvider.getUriForFile ()方法:

Uri imageUri = FileProvider.getUriForFile(
MainActivity.this,
"com.example.homefolder.example.provider", //(use your app signature + ".provider" )
imageFile);

然后您需要在您的 android 清单中配置您的提供程序:

<application>
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.homefolder.example.provider"
android:exported="false"
android:grantUriPermissions="true">
<!-- ressource file to create -->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths">
</meta-data>
</provider>
</application>

(在“ authority”中,使用与 getUriForFile ()方法的第二个参数(应用程序签名 + “ . Provider”)相同的值)

最后,您需要创建资源文件: “ file _ path”。 这个文件需要在 res/xml 目录下创建(您可能也需要创建这个目录) :

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

没有必要的 提供者配置到 AndroidManifest 只有相机和存储权限应该被允许。使用以下代码启动摄像机:

final int REQUEST_ACTION_CAMERA = 9;
void openCamra() {
Intent cameraImgIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);


cameraImgIntent.putExtra(MediaStore.EXTRA_OUTPUT,
FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID +".provider",
new File("your_file_name_with_dir")));
startActivityForResult(cameraImgIntent, REQUEST_ACTION_CAMERA);
}

捕捉到图像后,你可以在以下地方找到你捕捉到的图像:

"your_file_name_with_dir"

在... 中加入代码

onCreate(Budle savedInstancesState){
if (Build.VERSION.SDK_INT >= 24) {
try {
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}
}