android.os.FileUriExposedException: file.jpg exposed beyond app through ClipData.Item.getUri()

谁都会走 提交于 2019-11-28 17:28:25
rahul sondarva

Besides the solution using the FileProvider, there is another way to work around this. Simply put

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

in Application.onCreate() method. In this way the VM ignores the file URI exposure.

This info is from: FileUriExposedException

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.

So if your app/build.gradle file's compileSdkVersion (build target) is Android N (API level 24) or greater, this error is thrown if you write a file that can possibly get accessed by other apps. Most importantly, here is how you are supposed to do it moving forward:

taken from here: FileProvider

Change:

return Uri.fromFile(mediaFile);

to be

return FileProvider.getUriForFile(getApplicationContext(), getPackageName()+".fileprovider", mediaFile);

Note: if you control mydomain.com you could also replace getPackageName()+".fileprovider" with "com.mydomain.fileprovider" (the same goes for your AndroidManifest.xml below.

Also you need to add the following to your AndroidManifest.xml file right before your </application> tag

    <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/filepaths" />
    </provider>

Then you need to add a file named filepaths.xml to your app/src/main/res/xml directory with the following contents

<paths>
    <external-files-path name="Pictures" path="Pictures" />
</paths>

Note: for anybody else, we used external-files-path above, since Omer used getExternalFilesDir(Environment.DIRECTORY_PICTURES) in the code. For any other location, please check FileProvider under the "Specifying Available Files" section and change external-files-path to one of the following based on where your files are located:

files-path
cache-path
external-path
external-files-path
external-cache-path

Also, revise Pictures above to be your folder name.

One important anti-pattern to avoid is you should NOT use if (Build.VERSION.SDK_INT < 24) { to allow you to do it the old way, because it is not their Android version that requires this, it's your build version (I missed this the first time I coded it).

I know this is more work, however, this allows Android to allow only the other app you're sharing with, temporary access to the file, which is more secure for the user's privacy.

Add the below code where the SharingIntent called:-

if(Build.VERSION.SDK_INT>=24){
                    try{
                        Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
                        m.invoke(null);
                        shareImage(Uri.fromFile(new File(Path)));
                    }catch(Exception e){
                        e.printStackTrace();
                    }
                }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!