android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through...












574















The app is crashing when I'm trying to open a file. It works below Android Nougat, but on Android Nougat it crashes. It only crashes when I try to open a file from the SD card, not from the system partition. Some permission problem?



Sample code:



File file = new File("/storage/emulated/0/test.txt");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "text/*");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent); // Crashes on this line


Log:




android.os.FileUriExposedException:
file:///storage/emulated/0/test.txt exposed beyond app through
Intent.getData()




Edit:



When targeting Android Nougat, file:// URIs are not allowed anymore. We should use content:// URIs instead. However, my app needs to open files in root directories. Any ideas?










share|improve this question




















  • 8





    I feel like this was a mistake which makes life unnecessarily difficult for app developers. Having to bundle a "FileProvider" and "authority" with each app, seems like Enterprisey boilerplate. Having to add a flag to every file intent seems awkward and possibly unnecessary. Breaking the elegant concept of "paths" is unpleasant. And what's the benefit? Selectively granting storage access to apps (while most apps have full sdcard access, especially ones that work on files)?

    – jimbo1qaz
    Sep 17 '18 at 11:36













  • try this , small and perfect code stackoverflow.com/a/52695444/4997704

    – Binesh Kumar
    Oct 8 '18 at 4:38











  • Best practise of File Provider androidwave.com/capture-image-from-camera-gallery

    – Surya Prakash Kushawah
    Jan 4 at 13:29
















574















The app is crashing when I'm trying to open a file. It works below Android Nougat, but on Android Nougat it crashes. It only crashes when I try to open a file from the SD card, not from the system partition. Some permission problem?



Sample code:



File file = new File("/storage/emulated/0/test.txt");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "text/*");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent); // Crashes on this line


Log:




android.os.FileUriExposedException:
file:///storage/emulated/0/test.txt exposed beyond app through
Intent.getData()




Edit:



When targeting Android Nougat, file:// URIs are not allowed anymore. We should use content:// URIs instead. However, my app needs to open files in root directories. Any ideas?










share|improve this question




















  • 8





    I feel like this was a mistake which makes life unnecessarily difficult for app developers. Having to bundle a "FileProvider" and "authority" with each app, seems like Enterprisey boilerplate. Having to add a flag to every file intent seems awkward and possibly unnecessary. Breaking the elegant concept of "paths" is unpleasant. And what's the benefit? Selectively granting storage access to apps (while most apps have full sdcard access, especially ones that work on files)?

    – jimbo1qaz
    Sep 17 '18 at 11:36













  • try this , small and perfect code stackoverflow.com/a/52695444/4997704

    – Binesh Kumar
    Oct 8 '18 at 4:38











  • Best practise of File Provider androidwave.com/capture-image-from-camera-gallery

    – Surya Prakash Kushawah
    Jan 4 at 13:29














574












574








574


227






The app is crashing when I'm trying to open a file. It works below Android Nougat, but on Android Nougat it crashes. It only crashes when I try to open a file from the SD card, not from the system partition. Some permission problem?



Sample code:



File file = new File("/storage/emulated/0/test.txt");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "text/*");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent); // Crashes on this line


Log:




android.os.FileUriExposedException:
file:///storage/emulated/0/test.txt exposed beyond app through
Intent.getData()




Edit:



When targeting Android Nougat, file:// URIs are not allowed anymore. We should use content:// URIs instead. However, my app needs to open files in root directories. Any ideas?










share|improve this question
















The app is crashing when I'm trying to open a file. It works below Android Nougat, but on Android Nougat it crashes. It only crashes when I try to open a file from the SD card, not from the system partition. Some permission problem?



Sample code:



File file = new File("/storage/emulated/0/test.txt");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "text/*");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent); // Crashes on this line


Log:




android.os.FileUriExposedException:
file:///storage/emulated/0/test.txt exposed beyond app through
Intent.getData()




Edit:



When targeting Android Nougat, file:// URIs are not allowed anymore. We should use content:// URIs instead. However, my app needs to open files in root directories. Any ideas?







android android-file android-7.0-nougat






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 2 '18 at 17:32







Thomas Vos

















asked Jul 5 '16 at 9:51









Thomas VosThomas Vos

4,39041851




4,39041851








  • 8





    I feel like this was a mistake which makes life unnecessarily difficult for app developers. Having to bundle a "FileProvider" and "authority" with each app, seems like Enterprisey boilerplate. Having to add a flag to every file intent seems awkward and possibly unnecessary. Breaking the elegant concept of "paths" is unpleasant. And what's the benefit? Selectively granting storage access to apps (while most apps have full sdcard access, especially ones that work on files)?

    – jimbo1qaz
    Sep 17 '18 at 11:36













  • try this , small and perfect code stackoverflow.com/a/52695444/4997704

    – Binesh Kumar
    Oct 8 '18 at 4:38











  • Best practise of File Provider androidwave.com/capture-image-from-camera-gallery

    – Surya Prakash Kushawah
    Jan 4 at 13:29














  • 8





    I feel like this was a mistake which makes life unnecessarily difficult for app developers. Having to bundle a "FileProvider" and "authority" with each app, seems like Enterprisey boilerplate. Having to add a flag to every file intent seems awkward and possibly unnecessary. Breaking the elegant concept of "paths" is unpleasant. And what's the benefit? Selectively granting storage access to apps (while most apps have full sdcard access, especially ones that work on files)?

    – jimbo1qaz
    Sep 17 '18 at 11:36













  • try this , small and perfect code stackoverflow.com/a/52695444/4997704

    – Binesh Kumar
    Oct 8 '18 at 4:38











  • Best practise of File Provider androidwave.com/capture-image-from-camera-gallery

    – Surya Prakash Kushawah
    Jan 4 at 13:29








8




8





I feel like this was a mistake which makes life unnecessarily difficult for app developers. Having to bundle a "FileProvider" and "authority" with each app, seems like Enterprisey boilerplate. Having to add a flag to every file intent seems awkward and possibly unnecessary. Breaking the elegant concept of "paths" is unpleasant. And what's the benefit? Selectively granting storage access to apps (while most apps have full sdcard access, especially ones that work on files)?

– jimbo1qaz
Sep 17 '18 at 11:36







I feel like this was a mistake which makes life unnecessarily difficult for app developers. Having to bundle a "FileProvider" and "authority" with each app, seems like Enterprisey boilerplate. Having to add a flag to every file intent seems awkward and possibly unnecessary. Breaking the elegant concept of "paths" is unpleasant. And what's the benefit? Selectively granting storage access to apps (while most apps have full sdcard access, especially ones that work on files)?

– jimbo1qaz
Sep 17 '18 at 11:36















try this , small and perfect code stackoverflow.com/a/52695444/4997704

– Binesh Kumar
Oct 8 '18 at 4:38





try this , small and perfect code stackoverflow.com/a/52695444/4997704

– Binesh Kumar
Oct 8 '18 at 4:38













Best practise of File Provider androidwave.com/capture-image-from-camera-gallery

– Surya Prakash Kushawah
Jan 4 at 13:29





Best practise of File Provider androidwave.com/capture-image-from-camera-gallery

– Surya Prakash Kushawah
Jan 4 at 13:29












19 Answers
19






active

oldest

votes


















1046














If your targetSdkVersion >= 24, then we have to use FileProvider class to give access to the particular file or folder to make them accessible for other apps. We create our own class inheriting FileProvider in order to make sure our FileProvider doesn't conflict with FileProviders declared in imported dependencies as described here.



Steps to replace file:// URI with content:// URI:





  • Add a class extending FileProvider



    public class GenericFileProvider extends FileProvider {}


  • Add a FileProvider <provider> tag in AndroidManifest.xml under <application> tag. Specify a unique authority for the android:authorities attribute to avoid conflicts, imported dependencies might specify ${applicationId}.provider and other commonly used authorities.



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



  • Then create a provider_paths.xml file in res/xml folder. Folder may be needed to created if it doesn't exist. The content of the file is shown below. It describes that we would like to share access to the External Storage at root folder (path=".") with the name external_files.


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




  • The final step is to change the line of code below in



    Uri photoURI = Uri.fromFile(createImageFile());


    to



    Uri photoURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".my.package.name.provider", createImageFile());



  • Edit: If you're using an intent to make the system open your file, you may need to add the following line of code:



    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);



Please refer, full code and solution has been explained here.






share|improve this answer





















  • 49





    I just needed to add intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

    – alorma
    Nov 22 '16 at 15:11








  • 21





    Will it work for all Android versions, or just from API 24?

    – android developer
    Nov 24 '16 at 17:43






  • 5





    this article helped me medium.com/@ali.muzaffar/…

    – AbdulMomen عبدالمؤمن
    Mar 18 '17 at 16:41






  • 9





    @rockhammer I just tested this with Android 5.0, 6.0, 7.1 and 8.1, it works in all cases. So the (Build.VERSION.SDK_INT > M) condition is useless.

    – Sébastien
    Dec 13 '17 at 17:20






  • 39





    FileProvider should be extended only if you want to override any of the default behavior, otherwise use android:name="android.support.v4.content.FileProvider". See developer.android.com/reference/android/support/v4/content/…

    – JP Ventura
    Jan 15 '18 at 21:56



















268














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(). In this way the VM ignores the file URI exposure.



Method



builder.detectFileUriExposure()


enables the file exposure check, which is also the default behavior if we don't setup a VmPolicy.



I encountered a problem that if I use a content:// URI to send something, some apps just can't understand it. And downgrading the target SDK version is not allowed. In this case my solution is useful.



Update:



As mentioned in the comment, StrictMode is diagnostic tool, and is not supposed to be used for this problem. When I posted this answer a year ago, many apps can only receive File uris. They just crash when I tried to send a FileProvider uri to them. This is fixed in most apps now, so we should go with the FileProvider solution.






share|improve this answer





















  • 1





    @LaurynasG From API 18 to 23, android does not check for file uri exposure by default. Calling this method enables this check. From API 24, android does this check by default. But we can disable it by setting a new VmPolicy.

    – hqzxzwb
    Jul 19 '17 at 18:31






  • 1





    @hqzxzwb Thanks you saved my time. +1 vote for u.

    – Sagar Aghara
    Dec 23 '17 at 5:47






  • 1





    How this can solve this problem however , StrictMode is a diagnostic tools that should be enabled in developer mode not release mode ???

    – Imene Noomene
    Jan 4 '18 at 15:02






  • 1





    @ImeneNoomene Actually we are disabling StrictMode here. It seems reasonable that StrictMode should not be enabled in release mode, but in fact Android enables some StrictMode options by default regardless of debug mode or release mode. But one way or another, this answer was meant only to be a workaround back when some target apps were not prepared for receiving content uris. Now that most apps have added support for content uris, we should use the FileProvider pattern.

    – hqzxzwb
    Jan 4 '18 at 15:54






  • 2





    @ImeneNoomene I am totally with you in your outrage. You're right, this is a diagnostic tool, or at least it was ages ago when I added it to my projects. This is super frustrating! StrictMode.enableDefaults();, which I run only on my development builds keeps this crash from happening - so I now have a production application which crashes but it doesn't crash when in development. So basically, enabling a diagnostic tool here hides a serious issue. Thanks @hqzxzwb for helping me demystify this.

    – Jon
    Jan 5 '18 at 19:08





















135














If your app targets API 24+, and you still want/need to use file:// intents, you can use hacky way to disable the runtime check:



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


Method StrictMode.disableDeathOnFileUriExposure is hidden and documented as:



/**
* Used by lame internal apps that haven't done the hard work to get
* themselves off file:// Uris yet.
*/


Problem is that my app is not lame, but rather doesn't want to be crippled by using content:// intents which are not understood by many apps out there. For example, opening mp3 file with content:// scheme offers much fewer apps than when opening same over file:// scheme. I don't want to pay for Google's design faults by limiting my app's functionality.



Google wants developers to use content scheme, but the system is not prepared for this, for years apps were made to use Files not "content", files can be edited and saved back, while files served over content scheme can't be (can they?).






share|improve this answer





















  • 3





    "while files served over content scheme can't be (can they?)." -- sure, if you have write access to the content. ContentResolver has both openInputStream() and openOutputStream(). A less-hacky way of doing this is to just configure the VM rules yourself, and do not enable the file Uri rule.

    – CommonsWare
    Feb 25 '17 at 17:13






  • 1





    Exactly. It is hard work when you built your entire app, then find out after targeting 25 all of your camera methods break. This works for me until I get time to do it the right way.

    – Matt W
    May 25 '17 at 23:11






  • 5





    Works on Android 7. Thanks

    – Anton Kizema
    May 29 '17 at 14:18






  • 4





    Works on Android 8 too, tested on Huawei Nexus 6P.

    – Gonzalo Ledezma Torres
    Aug 7 '17 at 15:40






  • 4





    I confirm this is working on production (I have more then 500,000 users), currently version 8.1 is the highest version, and it works on it.

    – Eli
    Apr 22 '18 at 12:26



















107














If targetSdkVersion is higher than 24, then FileProvider is used to grant access.



Create an xml file(Path: resxml) provider_paths.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>





Add a Provider in AndroidManifest.xml



    <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>


and replace



Uri uri = Uri.fromFile(fileImagePath);


to



Uri uri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider",fileImagePath);


Edit: While you're including the URI with an Intent make sure to add below line:



intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);


and you are good to go. Hope it helps.






share|improve this answer





















  • 1





    @MaksimKniazev Can you describe your error in brief? So that I can help you.

    – Pankaj Lilan
    Nov 16 '17 at 11:47






  • 1





    @PankajLilan, I did exactly what did you said. But everytime that I open my pdf in the other application it appears blank (its saving correctly). Should I need to edit the xml? I already added the FLAG_GRANT_READ_URI_PERMISSION as well;

    – Felipe Castilhos
    Mar 7 '18 at 18:14






  • 1





    My mistake, I was adding the permission to the wrong intent. This is the best and the simpliest right answer. Thank you!

    – Felipe Castilhos
    Mar 7 '18 at 19:10








  • 2





    It throws exception java.lang.IllegalArgumentException: Failed to find configured root that contains / My file path is /storage/emulated/0/GSMManage_DCIM/Documents/Device7298file_74.pdf. can you please help ?

    – Jagdish Bhavsar
    Mar 8 '18 at 13:07








  • 1





    Don't know why but I had to add both READ and WRITE permissions : target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) target.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

    – box
    Oct 22 '18 at 8:54



















81














If your targetSdkVersion is 24 or higher, you can not use file: Uri values in Intents on Android 7.0+ devices.



Your choices are:




  1. Drop your targetSdkVersion to 23 or lower, or


  2. Put your content on internal storage, then use FileProvider to make it available selectively to other apps



For example:



Intent i=new Intent(Intent.ACTION_VIEW, FileProvider.getUriForFile(this, AUTHORITY, f));

i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(i);


(from this sample project)






share|improve this answer
























  • Thanks for the answer. What happens when I use this with files on the /system partition? Every app should be able to acces this partition without root.

    – Thomas Vos
    Jul 5 '16 at 12:56






  • 2





    @SuperThomasLab: I would not count on everything in /system being world-readable. That being said, my guess is that you will still get this exception. I suspect that they are just checking the scheme and are not trying to determine if the file truly is world-readable. However, FileProvider will not help you, as you cannot teach it to serve from /system. You could create a custom strategy for my StreamProvider, or roll your own ContentProvider, to get past the problem.

    – CommonsWare
    Jul 5 '16 at 13:11











  • Still thinking how I'm going to solve this.. The app I am updating with Android N support is a root browser. But now you can't open any files anymore in root directories. (/data, /system), because of this "good change".

    – Thomas Vos
    Jul 5 '16 at 16:11






  • 1





    what are the most important drawbacks to dropping targetSdkVersion to 23? thnx

    – rommex
    Jun 29 '17 at 14:06






  • 2





    @rommex: I do not know what qualifies as "most important". For example, users who work in split-screen mode or on freeform multi-window devices (Chromebooks, Samsung DeX) will be told that your app may not work with multi-window. Whether that is important or not is up to you.

    – CommonsWare
    Jun 29 '17 at 14:34



















44














First you need to add a provider to your AndroidManifest



  <application
...>
<activity>
....
</activity>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.your.package.fileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>


now create a file in xml resource folder (if using android studio you can hit Alt + Enter after highlighting file_paths and select create a xml resource option)



Next in the file_paths file enter



<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path path="Android/data/com.your.package/" name="files_root" />
<external-path path="." name="external_storage_root" />
</paths>


This example is for external-path you can refere here for more options.
This will allow you to share files which are in that folder and its sub-folder.



Now all that's left is to create the intent as follows:



    MimeTypeMap mime = MimeTypeMap.getSingleton();
String ext = newFile.getName().substring(newFile.getName().lastIndexOf(".") + 1);
String type = mime.getMimeTypeFromExtension(ext);
try {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(getContext(), "com.your.package.fileProvider", newFile);
intent.setDataAndType(contentUri, type);
} else {
intent.setDataAndType(Uri.fromFile(newFile), type);
}
startActivityForResult(intent, ACTIVITY_VIEW_ATTACHMENT);
} catch (ActivityNotFoundException anfe) {
Toast.makeText(getContext(), "No activity found to open this attachment.", Toast.LENGTH_LONG).show();
}


EDIT: I added the root folder of the sd card in the file_paths. I have tested this code and it does work.






share|improve this answer





















  • 1





    Thank you for this. I also want to let you know that there is a better way to get the file extension. String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString()); Also, I recommend anyone looking for answers to read through FileProvider first and understand what you are dealing with here with file permissions in Android N and above. There are options for internal storage vs. external storage and also for regular files-path vs. cache-paths.

    – praneetloke
    Dec 31 '16 at 16:57








  • 1





    I was getting the following exception: java.lang.IllegalArgumentException: Failed to find configured root ... and the only thing that worked was <files-path path="." name="files_root" /> on the xml file instead of <external-path .... My file was saved in the internal storage.

    – MScott
    Jun 30 '17 at 20:07



















25














@palash k answer is correct and worked for internal storage files, but in my case I want to open files from external storage also, my app crashed when open file from external storage like sdcard and usb, but I manage to solve the issue by modifying provider_paths.xml from the accepted answer



change the provider_paths.xml like below



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

<external-path path="Android/data/${applicationId}/" name="files_root" />

<root-path
name="root"
path="/" />

</paths>


and in java class(No change as the accepted answer just a small edit)



Uri uri=FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID+".provider", File)


This help me to fix the crash for files from external storages, Hope this will help some one having same issue as mine
:)






share|improve this answer





















  • 1





    Where did you find about <root-path please ? It's working. <external-path path="Android/data/${applicationId}/" name="files_root" /> had no effect for open files from external storage.

    – t0m
    Mar 16 '17 at 11:23













  • i find this from various search results, let me check again and get back to u asap

    – Ramz
    Mar 16 '17 at 11:40











  • also the external storage you mention is sd card or inbuilt storage?

    – Ramz
    Mar 16 '17 at 11:41











  • Sorry for inaccuracy. I meant Android/data/${applicationId}/ in SDcard.

    – t0m
    Mar 20 '17 at 8:36






  • 1





    Need to add this to the intent: intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

    – s-hunter
    Feb 17 '18 at 15:25



















19














Just paste the below code in activity onCreate()



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


It will ignore URI exposure






share|improve this answer
























  • this is one of the solutions but not the standard one. Stil people who downvoted the answers are wrong as the this is also working code with the working solution.

    – saksham
    Apr 18 '18 at 10:16



















18














Using the fileProvider is the way to go.
But you can use this simple workaround:




WARNING: It will be fixed in next Android release -
https://issuetracker.google.com/issues/37122890#comment4




replace:



startActivity(intent);


by



startActivity(Intent.createChooser(intent, "Your title"));





share|improve this answer





















  • 7





    The chooser will be patched soon by Google to contain same check. This is not a solution.

    – Pointer Null
    Feb 24 '17 at 11:31











  • This one works but will not work in future android versions.

    – Diljeet
    Apr 25 '17 at 7:28






  • 2





    this dont work on android 8 and upper

    – ArMo 372
    Apr 9 '18 at 6:25



















13














My Solution was to 'Uri.parse' the File Path as String, instead of using Uri.fromFile().



String storage = Environment.getExternalStorageDirectory().toString() + "/test.txt";
File file = new File(storage);
Uri uri;
if (Build.VERSION.SDK_INT < 24) {
uri = Uri.fromFile(file);
} else {
uri = Uri.parse(file.getPath()); // My work-around for new SDKs, causes ActivityNotFoundException in API 10.
}
Intent viewFile = new Intent(Intent.ACTION_VIEW);
viewFile.setDataAndType(uri, "text/plain");
startActivity(viewFile);


Seems that fromFile() uses A file pointer, which I suppose could be insecure when memory addresses are exposed to all apps. But A file path String never hurt anybody, so it works without throwing FileUriExposedException.



Tested on API levels 9 to 26! Does not require FileProvider, nor the Android Support Library at all.






share|improve this answer


























  • I wish I'd seen this first. I didn't prove it worked for me, but it's so much less cumbersome than FileProvider.

    – Dale
    Nov 20 '18 at 16:52











  • A note on why this actually works: It's not the File pointer that casues the issue, but the fact that the exception only occurs if you have a path with 'file://', which is automatically prepended with fromFile, but not with parse.

    – Xmister
    Jan 24 at 9:53













  • This does not get exception, but it can't send the file to the related app either. So, not worked for me.

    – Serdar Samancıoğlu
    Mar 14 at 14:11





















12














I used Palash's answer given above but it was somewhat incomplete, I had to provide permission like this



Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(this, getPackageName() + ".provider", new File(path));

List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}else {
uri = Uri.fromFile(new File(path));
}

intent.setDataAndType(uri, "application/vnd.android.package-archive");

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(intent);





share|improve this answer































    11














    Just paste the below code in activity onCreate().



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


    It will ignore URI exposure.



    Happy coding :-)






    share|improve this answer

































      3














      I don't know why, I did everything exactly the same as Pkosta (https://stackoverflow.com/a/38858040 ) but kept getting error:



      java.lang.SecurityException: Permission Denial: opening provider redacted from ProcessRecord{redacted} (redacted) that is not exported from uid redacted



      I wasted hours on this issue. The culprit? Kotlin.



      val playIntent = Intent(Intent.ACTION_VIEW, uri)
      intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)


      intent was actually setting getIntent().addFlags instead of operating on my newly declared playIntent.






      share|improve this answer































        2














        For downloading pdf from server , add below code in your service class. Hope this is helpful for you.



        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName + ".pdf");
        intent = new Intent(Intent.ACTION_VIEW);
        //Log.e("pathOpen", file.getPath());

        Uri contentUri;
        contentUri = Uri.fromFile(file);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);

        if (Build.VERSION.SDK_INT >= 24) {

        Uri apkURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", file);
        intent.setDataAndType(apkURI, "application/pdf");
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

        } else {

        intent.setDataAndType(contentUri, "application/pdf");
        }


        And yes , don't forget to add permissions and provider in your manifest.



        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

        <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>





        share|improve this answer


























        • what is @xml/provider_paths ?

          – Heisenberg
          Nov 30 '18 at 12:35



















        0














        add this two line in onCreate



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


        Share method



        File dir = new File(Environment.getExternalStorageDirectory(), "ColorStory");

        File imgFile = new File(dir, "0.png");

        Intent sendIntent = new Intent(Intent.ACTION_VIEW);
        sendIntent.setType("image/*");
        sendIntent.setAction(Intent.ACTION_SEND);
        sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + imgFile));
        sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        startActivity(Intent.createChooser(sendIntent, "Share images..."));





        share|improve this answer

































          -1














          https://stackoverflow.com/a/38858040/395097 this answer is complete.



          This answer is for - you already have an app which was targeting below 24, and now you are upgrading to targetSDKVersion >= 24.



          In Android N, only the file uri exposed to 3rd party app is changed. (Not the way we were using it before). So change only the places where you are sharing the path with 3rd party app (Camera in my case)



          In our app we were sending uri to Camera app, in that location we are expecting the camera app to store the captured image.




          1. For android N, we generate new Content:// uri based url pointing to
            file.

          2. We generate usual File api based path for the same (using older method).


          Now we have 2 different uri for same file. #1 is shared with Camera app. If the camera intent is success, we can access the image from #2.



          Hope this helps.






          share|improve this answer



















          • 1





            You are referencing a answer already posted here, if you need to complete it, comment in the answer plz.

            – IgniteCoders
            May 9 '18 at 18:12








          • 1





            @IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.

            – Aram
            May 10 '18 at 6:46



















          -1














          Xamarin.Android



          Note: The path xml/provider_paths.xml (.axml) couldn't be resolved, even after making the xml folder under Resources (maybe it can be put in an existing location like Values, didn't try), so I resorted to this which works for now. Testing showed that it only needs to be called once per application run (which makes sense being that it changes the operational state of the host VM).



          Note: xml needs to be capitalized, so Resources/Xml/provider_paths.xml



          Java.Lang.ClassLoader cl = _this.Context.ClassLoader;
          Java.Lang.Class strictMode = cl.LoadClass("android.os.StrictMode");
          System.IntPtr ptrStrictMode = JNIEnv.FindClass("android/os/StrictMode");
          var method = JNIEnv.GetStaticMethodID(ptrStrictMode, "disableDeathOnFileUriExposure", "()V");
          JNIEnv.CallStaticVoidMethod(strictMode.Handle, method);





          share|improve this answer

































            -1














            @Pkosta 's answer is one way of doing this.



            Besides using FileProvider, you can also insert the file into MediaStore (especially for image and video files), because files in MediaStore are accessible to every app:




            The MediaStore is primarily aimed at video, audio and image MIME types, however beginning with Android 3.0 (API level 11) it can also store non-media types (see MediaStore.Files for more info). Files can be inserted into the MediaStore using scanFile() after which a content:// style Uri suitable for sharing is passed to the provided onScanCompleted() callback. Note that once added to the system MediaStore the content is accessible to any app on the device.




            For example, you can insert a video file to MediaStore like this:



            ContentValues values = new ContentValues();
            values.put(MediaStore.Video.Media.DATA, videoFilePath);
            Uri contentUri = context.getContentResolver().insert(
            MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);


            contentUri is like content://media/external/video/media/183473, which can be passed directly to Intent.putExtra:



            intent.setType("video/*");
            intent.putExtra(Intent.EXTRA_STREAM, contentUri);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            activity.startActivity(intent);


            This works for me, and save the hassles of using FileProvider.






            share|improve this answer































              -2














              In my case I got rid of the exception by replacing SetDataAndType with just SetData.






              share|improve this answer























                Your Answer






                StackExchange.ifUsing("editor", function () {
                StackExchange.using("externalEditor", function () {
                StackExchange.using("snippets", function () {
                StackExchange.snippets.init();
                });
                });
                }, "code-snippets");

                StackExchange.ready(function() {
                var channelOptions = {
                tags: "".split(" "),
                id: "1"
                };
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function() {
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled) {
                StackExchange.using("snippets", function() {
                createEditor();
                });
                }
                else {
                createEditor();
                }
                });

                function createEditor() {
                StackExchange.prepareEditor({
                heartbeatType: 'answer',
                autoActivateHeartbeat: false,
                convertImagesToLinks: true,
                noModals: true,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: 10,
                bindNavPrevention: true,
                postfix: "",
                imageUploader: {
                brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                allowUrls: true
                },
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                });


                }
                });














                draft saved

                draft discarded


















                StackExchange.ready(
                function () {
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f38200282%2fandroid-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed%23new-answer', 'question_page');
                }
                );

                Post as a guest















                Required, but never shown

























                19 Answers
                19






                active

                oldest

                votes








                19 Answers
                19






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes









                1046














                If your targetSdkVersion >= 24, then we have to use FileProvider class to give access to the particular file or folder to make them accessible for other apps. We create our own class inheriting FileProvider in order to make sure our FileProvider doesn't conflict with FileProviders declared in imported dependencies as described here.



                Steps to replace file:// URI with content:// URI:





                • Add a class extending FileProvider



                  public class GenericFileProvider extends FileProvider {}


                • Add a FileProvider <provider> tag in AndroidManifest.xml under <application> tag. Specify a unique authority for the android:authorities attribute to avoid conflicts, imported dependencies might specify ${applicationId}.provider and other commonly used authorities.



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



                • Then create a provider_paths.xml file in res/xml folder. Folder may be needed to created if it doesn't exist. The content of the file is shown below. It describes that we would like to share access to the External Storage at root folder (path=".") with the name external_files.


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




                • The final step is to change the line of code below in



                  Uri photoURI = Uri.fromFile(createImageFile());


                  to



                  Uri photoURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".my.package.name.provider", createImageFile());



                • Edit: If you're using an intent to make the system open your file, you may need to add the following line of code:



                  intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);



                Please refer, full code and solution has been explained here.






                share|improve this answer





















                • 49





                  I just needed to add intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                  – alorma
                  Nov 22 '16 at 15:11








                • 21





                  Will it work for all Android versions, or just from API 24?

                  – android developer
                  Nov 24 '16 at 17:43






                • 5





                  this article helped me medium.com/@ali.muzaffar/…

                  – AbdulMomen عبدالمؤمن
                  Mar 18 '17 at 16:41






                • 9





                  @rockhammer I just tested this with Android 5.0, 6.0, 7.1 and 8.1, it works in all cases. So the (Build.VERSION.SDK_INT > M) condition is useless.

                  – Sébastien
                  Dec 13 '17 at 17:20






                • 39





                  FileProvider should be extended only if you want to override any of the default behavior, otherwise use android:name="android.support.v4.content.FileProvider". See developer.android.com/reference/android/support/v4/content/…

                  – JP Ventura
                  Jan 15 '18 at 21:56
















                1046














                If your targetSdkVersion >= 24, then we have to use FileProvider class to give access to the particular file or folder to make them accessible for other apps. We create our own class inheriting FileProvider in order to make sure our FileProvider doesn't conflict with FileProviders declared in imported dependencies as described here.



                Steps to replace file:// URI with content:// URI:





                • Add a class extending FileProvider



                  public class GenericFileProvider extends FileProvider {}


                • Add a FileProvider <provider> tag in AndroidManifest.xml under <application> tag. Specify a unique authority for the android:authorities attribute to avoid conflicts, imported dependencies might specify ${applicationId}.provider and other commonly used authorities.



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



                • Then create a provider_paths.xml file in res/xml folder. Folder may be needed to created if it doesn't exist. The content of the file is shown below. It describes that we would like to share access to the External Storage at root folder (path=".") with the name external_files.


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




                • The final step is to change the line of code below in



                  Uri photoURI = Uri.fromFile(createImageFile());


                  to



                  Uri photoURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".my.package.name.provider", createImageFile());



                • Edit: If you're using an intent to make the system open your file, you may need to add the following line of code:



                  intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);



                Please refer, full code and solution has been explained here.






                share|improve this answer





















                • 49





                  I just needed to add intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                  – alorma
                  Nov 22 '16 at 15:11








                • 21





                  Will it work for all Android versions, or just from API 24?

                  – android developer
                  Nov 24 '16 at 17:43






                • 5





                  this article helped me medium.com/@ali.muzaffar/…

                  – AbdulMomen عبدالمؤمن
                  Mar 18 '17 at 16:41






                • 9





                  @rockhammer I just tested this with Android 5.0, 6.0, 7.1 and 8.1, it works in all cases. So the (Build.VERSION.SDK_INT > M) condition is useless.

                  – Sébastien
                  Dec 13 '17 at 17:20






                • 39





                  FileProvider should be extended only if you want to override any of the default behavior, otherwise use android:name="android.support.v4.content.FileProvider". See developer.android.com/reference/android/support/v4/content/…

                  – JP Ventura
                  Jan 15 '18 at 21:56














                1046












                1046








                1046







                If your targetSdkVersion >= 24, then we have to use FileProvider class to give access to the particular file or folder to make them accessible for other apps. We create our own class inheriting FileProvider in order to make sure our FileProvider doesn't conflict with FileProviders declared in imported dependencies as described here.



                Steps to replace file:// URI with content:// URI:





                • Add a class extending FileProvider



                  public class GenericFileProvider extends FileProvider {}


                • Add a FileProvider <provider> tag in AndroidManifest.xml under <application> tag. Specify a unique authority for the android:authorities attribute to avoid conflicts, imported dependencies might specify ${applicationId}.provider and other commonly used authorities.



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



                • Then create a provider_paths.xml file in res/xml folder. Folder may be needed to created if it doesn't exist. The content of the file is shown below. It describes that we would like to share access to the External Storage at root folder (path=".") with the name external_files.


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




                • The final step is to change the line of code below in



                  Uri photoURI = Uri.fromFile(createImageFile());


                  to



                  Uri photoURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".my.package.name.provider", createImageFile());



                • Edit: If you're using an intent to make the system open your file, you may need to add the following line of code:



                  intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);



                Please refer, full code and solution has been explained here.






                share|improve this answer















                If your targetSdkVersion >= 24, then we have to use FileProvider class to give access to the particular file or folder to make them accessible for other apps. We create our own class inheriting FileProvider in order to make sure our FileProvider doesn't conflict with FileProviders declared in imported dependencies as described here.



                Steps to replace file:// URI with content:// URI:





                • Add a class extending FileProvider



                  public class GenericFileProvider extends FileProvider {}


                • Add a FileProvider <provider> tag in AndroidManifest.xml under <application> tag. Specify a unique authority for the android:authorities attribute to avoid conflicts, imported dependencies might specify ${applicationId}.provider and other commonly used authorities.



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



                • Then create a provider_paths.xml file in res/xml folder. Folder may be needed to created if it doesn't exist. The content of the file is shown below. It describes that we would like to share access to the External Storage at root folder (path=".") with the name external_files.


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




                • The final step is to change the line of code below in



                  Uri photoURI = Uri.fromFile(createImageFile());


                  to



                  Uri photoURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".my.package.name.provider", createImageFile());



                • Edit: If you're using an intent to make the system open your file, you may need to add the following line of code:



                  intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);



                Please refer, full code and solution has been explained here.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Oct 30 '18 at 1:38









                jachguate

                15.5k14586




                15.5k14586










                answered Aug 9 '16 at 18:33









                PkostaPkosta

                10.7k167




                10.7k167








                • 49





                  I just needed to add intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                  – alorma
                  Nov 22 '16 at 15:11








                • 21





                  Will it work for all Android versions, or just from API 24?

                  – android developer
                  Nov 24 '16 at 17:43






                • 5





                  this article helped me medium.com/@ali.muzaffar/…

                  – AbdulMomen عبدالمؤمن
                  Mar 18 '17 at 16:41






                • 9





                  @rockhammer I just tested this with Android 5.0, 6.0, 7.1 and 8.1, it works in all cases. So the (Build.VERSION.SDK_INT > M) condition is useless.

                  – Sébastien
                  Dec 13 '17 at 17:20






                • 39





                  FileProvider should be extended only if you want to override any of the default behavior, otherwise use android:name="android.support.v4.content.FileProvider". See developer.android.com/reference/android/support/v4/content/…

                  – JP Ventura
                  Jan 15 '18 at 21:56














                • 49





                  I just needed to add intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                  – alorma
                  Nov 22 '16 at 15:11








                • 21





                  Will it work for all Android versions, or just from API 24?

                  – android developer
                  Nov 24 '16 at 17:43






                • 5





                  this article helped me medium.com/@ali.muzaffar/…

                  – AbdulMomen عبدالمؤمن
                  Mar 18 '17 at 16:41






                • 9





                  @rockhammer I just tested this with Android 5.0, 6.0, 7.1 and 8.1, it works in all cases. So the (Build.VERSION.SDK_INT > M) condition is useless.

                  – Sébastien
                  Dec 13 '17 at 17:20






                • 39





                  FileProvider should be extended only if you want to override any of the default behavior, otherwise use android:name="android.support.v4.content.FileProvider". See developer.android.com/reference/android/support/v4/content/…

                  – JP Ventura
                  Jan 15 '18 at 21:56








                49




                49





                I just needed to add intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                – alorma
                Nov 22 '16 at 15:11







                I just needed to add intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                – alorma
                Nov 22 '16 at 15:11






                21




                21





                Will it work for all Android versions, or just from API 24?

                – android developer
                Nov 24 '16 at 17:43





                Will it work for all Android versions, or just from API 24?

                – android developer
                Nov 24 '16 at 17:43




                5




                5





                this article helped me medium.com/@ali.muzaffar/…

                – AbdulMomen عبدالمؤمن
                Mar 18 '17 at 16:41





                this article helped me medium.com/@ali.muzaffar/…

                – AbdulMomen عبدالمؤمن
                Mar 18 '17 at 16:41




                9




                9





                @rockhammer I just tested this with Android 5.0, 6.0, 7.1 and 8.1, it works in all cases. So the (Build.VERSION.SDK_INT > M) condition is useless.

                – Sébastien
                Dec 13 '17 at 17:20





                @rockhammer I just tested this with Android 5.0, 6.0, 7.1 and 8.1, it works in all cases. So the (Build.VERSION.SDK_INT > M) condition is useless.

                – Sébastien
                Dec 13 '17 at 17:20




                39




                39





                FileProvider should be extended only if you want to override any of the default behavior, otherwise use android:name="android.support.v4.content.FileProvider". See developer.android.com/reference/android/support/v4/content/…

                – JP Ventura
                Jan 15 '18 at 21:56





                FileProvider should be extended only if you want to override any of the default behavior, otherwise use android:name="android.support.v4.content.FileProvider". See developer.android.com/reference/android/support/v4/content/…

                – JP Ventura
                Jan 15 '18 at 21:56













                268














                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(). In this way the VM ignores the file URI exposure.



                Method



                builder.detectFileUriExposure()


                enables the file exposure check, which is also the default behavior if we don't setup a VmPolicy.



                I encountered a problem that if I use a content:// URI to send something, some apps just can't understand it. And downgrading the target SDK version is not allowed. In this case my solution is useful.



                Update:



                As mentioned in the comment, StrictMode is diagnostic tool, and is not supposed to be used for this problem. When I posted this answer a year ago, many apps can only receive File uris. They just crash when I tried to send a FileProvider uri to them. This is fixed in most apps now, so we should go with the FileProvider solution.






                share|improve this answer





















                • 1





                  @LaurynasG From API 18 to 23, android does not check for file uri exposure by default. Calling this method enables this check. From API 24, android does this check by default. But we can disable it by setting a new VmPolicy.

                  – hqzxzwb
                  Jul 19 '17 at 18:31






                • 1





                  @hqzxzwb Thanks you saved my time. +1 vote for u.

                  – Sagar Aghara
                  Dec 23 '17 at 5:47






                • 1





                  How this can solve this problem however , StrictMode is a diagnostic tools that should be enabled in developer mode not release mode ???

                  – Imene Noomene
                  Jan 4 '18 at 15:02






                • 1





                  @ImeneNoomene Actually we are disabling StrictMode here. It seems reasonable that StrictMode should not be enabled in release mode, but in fact Android enables some StrictMode options by default regardless of debug mode or release mode. But one way or another, this answer was meant only to be a workaround back when some target apps were not prepared for receiving content uris. Now that most apps have added support for content uris, we should use the FileProvider pattern.

                  – hqzxzwb
                  Jan 4 '18 at 15:54






                • 2





                  @ImeneNoomene I am totally with you in your outrage. You're right, this is a diagnostic tool, or at least it was ages ago when I added it to my projects. This is super frustrating! StrictMode.enableDefaults();, which I run only on my development builds keeps this crash from happening - so I now have a production application which crashes but it doesn't crash when in development. So basically, enabling a diagnostic tool here hides a serious issue. Thanks @hqzxzwb for helping me demystify this.

                  – Jon
                  Jan 5 '18 at 19:08


















                268














                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(). In this way the VM ignores the file URI exposure.



                Method



                builder.detectFileUriExposure()


                enables the file exposure check, which is also the default behavior if we don't setup a VmPolicy.



                I encountered a problem that if I use a content:// URI to send something, some apps just can't understand it. And downgrading the target SDK version is not allowed. In this case my solution is useful.



                Update:



                As mentioned in the comment, StrictMode is diagnostic tool, and is not supposed to be used for this problem. When I posted this answer a year ago, many apps can only receive File uris. They just crash when I tried to send a FileProvider uri to them. This is fixed in most apps now, so we should go with the FileProvider solution.






                share|improve this answer





















                • 1





                  @LaurynasG From API 18 to 23, android does not check for file uri exposure by default. Calling this method enables this check. From API 24, android does this check by default. But we can disable it by setting a new VmPolicy.

                  – hqzxzwb
                  Jul 19 '17 at 18:31






                • 1





                  @hqzxzwb Thanks you saved my time. +1 vote for u.

                  – Sagar Aghara
                  Dec 23 '17 at 5:47






                • 1





                  How this can solve this problem however , StrictMode is a diagnostic tools that should be enabled in developer mode not release mode ???

                  – Imene Noomene
                  Jan 4 '18 at 15:02






                • 1





                  @ImeneNoomene Actually we are disabling StrictMode here. It seems reasonable that StrictMode should not be enabled in release mode, but in fact Android enables some StrictMode options by default regardless of debug mode or release mode. But one way or another, this answer was meant only to be a workaround back when some target apps were not prepared for receiving content uris. Now that most apps have added support for content uris, we should use the FileProvider pattern.

                  – hqzxzwb
                  Jan 4 '18 at 15:54






                • 2





                  @ImeneNoomene I am totally with you in your outrage. You're right, this is a diagnostic tool, or at least it was ages ago when I added it to my projects. This is super frustrating! StrictMode.enableDefaults();, which I run only on my development builds keeps this crash from happening - so I now have a production application which crashes but it doesn't crash when in development. So basically, enabling a diagnostic tool here hides a serious issue. Thanks @hqzxzwb for helping me demystify this.

                  – Jon
                  Jan 5 '18 at 19:08
















                268












                268








                268







                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(). In this way the VM ignores the file URI exposure.



                Method



                builder.detectFileUriExposure()


                enables the file exposure check, which is also the default behavior if we don't setup a VmPolicy.



                I encountered a problem that if I use a content:// URI to send something, some apps just can't understand it. And downgrading the target SDK version is not allowed. In this case my solution is useful.



                Update:



                As mentioned in the comment, StrictMode is diagnostic tool, and is not supposed to be used for this problem. When I posted this answer a year ago, many apps can only receive File uris. They just crash when I tried to send a FileProvider uri to them. This is fixed in most apps now, so we should go with the FileProvider solution.






                share|improve this answer















                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(). In this way the VM ignores the file URI exposure.



                Method



                builder.detectFileUriExposure()


                enables the file exposure check, which is also the default behavior if we don't setup a VmPolicy.



                I encountered a problem that if I use a content:// URI to send something, some apps just can't understand it. And downgrading the target SDK version is not allowed. In this case my solution is useful.



                Update:



                As mentioned in the comment, StrictMode is diagnostic tool, and is not supposed to be used for this problem. When I posted this answer a year ago, many apps can only receive File uris. They just crash when I tried to send a FileProvider uri to them. This is fixed in most apps now, so we should go with the FileProvider solution.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jan 6 '18 at 10:56

























                answered Nov 18 '16 at 10:31









                hqzxzwbhqzxzwb

                2,7371512




                2,7371512








                • 1





                  @LaurynasG From API 18 to 23, android does not check for file uri exposure by default. Calling this method enables this check. From API 24, android does this check by default. But we can disable it by setting a new VmPolicy.

                  – hqzxzwb
                  Jul 19 '17 at 18:31






                • 1





                  @hqzxzwb Thanks you saved my time. +1 vote for u.

                  – Sagar Aghara
                  Dec 23 '17 at 5:47






                • 1





                  How this can solve this problem however , StrictMode is a diagnostic tools that should be enabled in developer mode not release mode ???

                  – Imene Noomene
                  Jan 4 '18 at 15:02






                • 1





                  @ImeneNoomene Actually we are disabling StrictMode here. It seems reasonable that StrictMode should not be enabled in release mode, but in fact Android enables some StrictMode options by default regardless of debug mode or release mode. But one way or another, this answer was meant only to be a workaround back when some target apps were not prepared for receiving content uris. Now that most apps have added support for content uris, we should use the FileProvider pattern.

                  – hqzxzwb
                  Jan 4 '18 at 15:54






                • 2





                  @ImeneNoomene I am totally with you in your outrage. You're right, this is a diagnostic tool, or at least it was ages ago when I added it to my projects. This is super frustrating! StrictMode.enableDefaults();, which I run only on my development builds keeps this crash from happening - so I now have a production application which crashes but it doesn't crash when in development. So basically, enabling a diagnostic tool here hides a serious issue. Thanks @hqzxzwb for helping me demystify this.

                  – Jon
                  Jan 5 '18 at 19:08
















                • 1





                  @LaurynasG From API 18 to 23, android does not check for file uri exposure by default. Calling this method enables this check. From API 24, android does this check by default. But we can disable it by setting a new VmPolicy.

                  – hqzxzwb
                  Jul 19 '17 at 18:31






                • 1





                  @hqzxzwb Thanks you saved my time. +1 vote for u.

                  – Sagar Aghara
                  Dec 23 '17 at 5:47






                • 1





                  How this can solve this problem however , StrictMode is a diagnostic tools that should be enabled in developer mode not release mode ???

                  – Imene Noomene
                  Jan 4 '18 at 15:02






                • 1





                  @ImeneNoomene Actually we are disabling StrictMode here. It seems reasonable that StrictMode should not be enabled in release mode, but in fact Android enables some StrictMode options by default regardless of debug mode or release mode. But one way or another, this answer was meant only to be a workaround back when some target apps were not prepared for receiving content uris. Now that most apps have added support for content uris, we should use the FileProvider pattern.

                  – hqzxzwb
                  Jan 4 '18 at 15:54






                • 2





                  @ImeneNoomene I am totally with you in your outrage. You're right, this is a diagnostic tool, or at least it was ages ago when I added it to my projects. This is super frustrating! StrictMode.enableDefaults();, which I run only on my development builds keeps this crash from happening - so I now have a production application which crashes but it doesn't crash when in development. So basically, enabling a diagnostic tool here hides a serious issue. Thanks @hqzxzwb for helping me demystify this.

                  – Jon
                  Jan 5 '18 at 19:08










                1




                1





                @LaurynasG From API 18 to 23, android does not check for file uri exposure by default. Calling this method enables this check. From API 24, android does this check by default. But we can disable it by setting a new VmPolicy.

                – hqzxzwb
                Jul 19 '17 at 18:31





                @LaurynasG From API 18 to 23, android does not check for file uri exposure by default. Calling this method enables this check. From API 24, android does this check by default. But we can disable it by setting a new VmPolicy.

                – hqzxzwb
                Jul 19 '17 at 18:31




                1




                1





                @hqzxzwb Thanks you saved my time. +1 vote for u.

                – Sagar Aghara
                Dec 23 '17 at 5:47





                @hqzxzwb Thanks you saved my time. +1 vote for u.

                – Sagar Aghara
                Dec 23 '17 at 5:47




                1




                1





                How this can solve this problem however , StrictMode is a diagnostic tools that should be enabled in developer mode not release mode ???

                – Imene Noomene
                Jan 4 '18 at 15:02





                How this can solve this problem however , StrictMode is a diagnostic tools that should be enabled in developer mode not release mode ???

                – Imene Noomene
                Jan 4 '18 at 15:02




                1




                1





                @ImeneNoomene Actually we are disabling StrictMode here. It seems reasonable that StrictMode should not be enabled in release mode, but in fact Android enables some StrictMode options by default regardless of debug mode or release mode. But one way or another, this answer was meant only to be a workaround back when some target apps were not prepared for receiving content uris. Now that most apps have added support for content uris, we should use the FileProvider pattern.

                – hqzxzwb
                Jan 4 '18 at 15:54





                @ImeneNoomene Actually we are disabling StrictMode here. It seems reasonable that StrictMode should not be enabled in release mode, but in fact Android enables some StrictMode options by default regardless of debug mode or release mode. But one way or another, this answer was meant only to be a workaround back when some target apps were not prepared for receiving content uris. Now that most apps have added support for content uris, we should use the FileProvider pattern.

                – hqzxzwb
                Jan 4 '18 at 15:54




                2




                2





                @ImeneNoomene I am totally with you in your outrage. You're right, this is a diagnostic tool, or at least it was ages ago when I added it to my projects. This is super frustrating! StrictMode.enableDefaults();, which I run only on my development builds keeps this crash from happening - so I now have a production application which crashes but it doesn't crash when in development. So basically, enabling a diagnostic tool here hides a serious issue. Thanks @hqzxzwb for helping me demystify this.

                – Jon
                Jan 5 '18 at 19:08







                @ImeneNoomene I am totally with you in your outrage. You're right, this is a diagnostic tool, or at least it was ages ago when I added it to my projects. This is super frustrating! StrictMode.enableDefaults();, which I run only on my development builds keeps this crash from happening - so I now have a production application which crashes but it doesn't crash when in development. So basically, enabling a diagnostic tool here hides a serious issue. Thanks @hqzxzwb for helping me demystify this.

                – Jon
                Jan 5 '18 at 19:08













                135














                If your app targets API 24+, and you still want/need to use file:// intents, you can use hacky way to disable the runtime check:



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


                Method StrictMode.disableDeathOnFileUriExposure is hidden and documented as:



                /**
                * Used by lame internal apps that haven't done the hard work to get
                * themselves off file:// Uris yet.
                */


                Problem is that my app is not lame, but rather doesn't want to be crippled by using content:// intents which are not understood by many apps out there. For example, opening mp3 file with content:// scheme offers much fewer apps than when opening same over file:// scheme. I don't want to pay for Google's design faults by limiting my app's functionality.



                Google wants developers to use content scheme, but the system is not prepared for this, for years apps were made to use Files not "content", files can be edited and saved back, while files served over content scheme can't be (can they?).






                share|improve this answer





















                • 3





                  "while files served over content scheme can't be (can they?)." -- sure, if you have write access to the content. ContentResolver has both openInputStream() and openOutputStream(). A less-hacky way of doing this is to just configure the VM rules yourself, and do not enable the file Uri rule.

                  – CommonsWare
                  Feb 25 '17 at 17:13






                • 1





                  Exactly. It is hard work when you built your entire app, then find out after targeting 25 all of your camera methods break. This works for me until I get time to do it the right way.

                  – Matt W
                  May 25 '17 at 23:11






                • 5





                  Works on Android 7. Thanks

                  – Anton Kizema
                  May 29 '17 at 14:18






                • 4





                  Works on Android 8 too, tested on Huawei Nexus 6P.

                  – Gonzalo Ledezma Torres
                  Aug 7 '17 at 15:40






                • 4





                  I confirm this is working on production (I have more then 500,000 users), currently version 8.1 is the highest version, and it works on it.

                  – Eli
                  Apr 22 '18 at 12:26
















                135














                If your app targets API 24+, and you still want/need to use file:// intents, you can use hacky way to disable the runtime check:



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


                Method StrictMode.disableDeathOnFileUriExposure is hidden and documented as:



                /**
                * Used by lame internal apps that haven't done the hard work to get
                * themselves off file:// Uris yet.
                */


                Problem is that my app is not lame, but rather doesn't want to be crippled by using content:// intents which are not understood by many apps out there. For example, opening mp3 file with content:// scheme offers much fewer apps than when opening same over file:// scheme. I don't want to pay for Google's design faults by limiting my app's functionality.



                Google wants developers to use content scheme, but the system is not prepared for this, for years apps were made to use Files not "content", files can be edited and saved back, while files served over content scheme can't be (can they?).






                share|improve this answer





















                • 3





                  "while files served over content scheme can't be (can they?)." -- sure, if you have write access to the content. ContentResolver has both openInputStream() and openOutputStream(). A less-hacky way of doing this is to just configure the VM rules yourself, and do not enable the file Uri rule.

                  – CommonsWare
                  Feb 25 '17 at 17:13






                • 1





                  Exactly. It is hard work when you built your entire app, then find out after targeting 25 all of your camera methods break. This works for me until I get time to do it the right way.

                  – Matt W
                  May 25 '17 at 23:11






                • 5





                  Works on Android 7. Thanks

                  – Anton Kizema
                  May 29 '17 at 14:18






                • 4





                  Works on Android 8 too, tested on Huawei Nexus 6P.

                  – Gonzalo Ledezma Torres
                  Aug 7 '17 at 15:40






                • 4





                  I confirm this is working on production (I have more then 500,000 users), currently version 8.1 is the highest version, and it works on it.

                  – Eli
                  Apr 22 '18 at 12:26














                135












                135








                135







                If your app targets API 24+, and you still want/need to use file:// intents, you can use hacky way to disable the runtime check:



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


                Method StrictMode.disableDeathOnFileUriExposure is hidden and documented as:



                /**
                * Used by lame internal apps that haven't done the hard work to get
                * themselves off file:// Uris yet.
                */


                Problem is that my app is not lame, but rather doesn't want to be crippled by using content:// intents which are not understood by many apps out there. For example, opening mp3 file with content:// scheme offers much fewer apps than when opening same over file:// scheme. I don't want to pay for Google's design faults by limiting my app's functionality.



                Google wants developers to use content scheme, but the system is not prepared for this, for years apps were made to use Files not "content", files can be edited and saved back, while files served over content scheme can't be (can they?).






                share|improve this answer















                If your app targets API 24+, and you still want/need to use file:// intents, you can use hacky way to disable the runtime check:



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


                Method StrictMode.disableDeathOnFileUriExposure is hidden and documented as:



                /**
                * Used by lame internal apps that haven't done the hard work to get
                * themselves off file:// Uris yet.
                */


                Problem is that my app is not lame, but rather doesn't want to be crippled by using content:// intents which are not understood by many apps out there. For example, opening mp3 file with content:// scheme offers much fewer apps than when opening same over file:// scheme. I don't want to pay for Google's design faults by limiting my app's functionality.



                Google wants developers to use content scheme, but the system is not prepared for this, for years apps were made to use Files not "content", files can be edited and saved back, while files served over content scheme can't be (can they?).







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Feb 24 '17 at 11:29

























                answered Feb 24 '17 at 11:21









                Pointer NullPointer Null

                29k136997




                29k136997








                • 3





                  "while files served over content scheme can't be (can they?)." -- sure, if you have write access to the content. ContentResolver has both openInputStream() and openOutputStream(). A less-hacky way of doing this is to just configure the VM rules yourself, and do not enable the file Uri rule.

                  – CommonsWare
                  Feb 25 '17 at 17:13






                • 1





                  Exactly. It is hard work when you built your entire app, then find out after targeting 25 all of your camera methods break. This works for me until I get time to do it the right way.

                  – Matt W
                  May 25 '17 at 23:11






                • 5





                  Works on Android 7. Thanks

                  – Anton Kizema
                  May 29 '17 at 14:18






                • 4





                  Works on Android 8 too, tested on Huawei Nexus 6P.

                  – Gonzalo Ledezma Torres
                  Aug 7 '17 at 15:40






                • 4





                  I confirm this is working on production (I have more then 500,000 users), currently version 8.1 is the highest version, and it works on it.

                  – Eli
                  Apr 22 '18 at 12:26














                • 3





                  "while files served over content scheme can't be (can they?)." -- sure, if you have write access to the content. ContentResolver has both openInputStream() and openOutputStream(). A less-hacky way of doing this is to just configure the VM rules yourself, and do not enable the file Uri rule.

                  – CommonsWare
                  Feb 25 '17 at 17:13






                • 1





                  Exactly. It is hard work when you built your entire app, then find out after targeting 25 all of your camera methods break. This works for me until I get time to do it the right way.

                  – Matt W
                  May 25 '17 at 23:11






                • 5





                  Works on Android 7. Thanks

                  – Anton Kizema
                  May 29 '17 at 14:18






                • 4





                  Works on Android 8 too, tested on Huawei Nexus 6P.

                  – Gonzalo Ledezma Torres
                  Aug 7 '17 at 15:40






                • 4





                  I confirm this is working on production (I have more then 500,000 users), currently version 8.1 is the highest version, and it works on it.

                  – Eli
                  Apr 22 '18 at 12:26








                3




                3





                "while files served over content scheme can't be (can they?)." -- sure, if you have write access to the content. ContentResolver has both openInputStream() and openOutputStream(). A less-hacky way of doing this is to just configure the VM rules yourself, and do not enable the file Uri rule.

                – CommonsWare
                Feb 25 '17 at 17:13





                "while files served over content scheme can't be (can they?)." -- sure, if you have write access to the content. ContentResolver has both openInputStream() and openOutputStream(). A less-hacky way of doing this is to just configure the VM rules yourself, and do not enable the file Uri rule.

                – CommonsWare
                Feb 25 '17 at 17:13




                1




                1





                Exactly. It is hard work when you built your entire app, then find out after targeting 25 all of your camera methods break. This works for me until I get time to do it the right way.

                – Matt W
                May 25 '17 at 23:11





                Exactly. It is hard work when you built your entire app, then find out after targeting 25 all of your camera methods break. This works for me until I get time to do it the right way.

                – Matt W
                May 25 '17 at 23:11




                5




                5





                Works on Android 7. Thanks

                – Anton Kizema
                May 29 '17 at 14:18





                Works on Android 7. Thanks

                – Anton Kizema
                May 29 '17 at 14:18




                4




                4





                Works on Android 8 too, tested on Huawei Nexus 6P.

                – Gonzalo Ledezma Torres
                Aug 7 '17 at 15:40





                Works on Android 8 too, tested on Huawei Nexus 6P.

                – Gonzalo Ledezma Torres
                Aug 7 '17 at 15:40




                4




                4





                I confirm this is working on production (I have more then 500,000 users), currently version 8.1 is the highest version, and it works on it.

                – Eli
                Apr 22 '18 at 12:26





                I confirm this is working on production (I have more then 500,000 users), currently version 8.1 is the highest version, and it works on it.

                – Eli
                Apr 22 '18 at 12:26











                107














                If targetSdkVersion is higher than 24, then FileProvider is used to grant access.



                Create an xml file(Path: resxml) provider_paths.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>





                Add a Provider in AndroidManifest.xml



                    <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>


                and replace



                Uri uri = Uri.fromFile(fileImagePath);


                to



                Uri uri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider",fileImagePath);


                Edit: While you're including the URI with an Intent make sure to add below line:



                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);


                and you are good to go. Hope it helps.






                share|improve this answer





















                • 1





                  @MaksimKniazev Can you describe your error in brief? So that I can help you.

                  – Pankaj Lilan
                  Nov 16 '17 at 11:47






                • 1





                  @PankajLilan, I did exactly what did you said. But everytime that I open my pdf in the other application it appears blank (its saving correctly). Should I need to edit the xml? I already added the FLAG_GRANT_READ_URI_PERMISSION as well;

                  – Felipe Castilhos
                  Mar 7 '18 at 18:14






                • 1





                  My mistake, I was adding the permission to the wrong intent. This is the best and the simpliest right answer. Thank you!

                  – Felipe Castilhos
                  Mar 7 '18 at 19:10








                • 2





                  It throws exception java.lang.IllegalArgumentException: Failed to find configured root that contains / My file path is /storage/emulated/0/GSMManage_DCIM/Documents/Device7298file_74.pdf. can you please help ?

                  – Jagdish Bhavsar
                  Mar 8 '18 at 13:07








                • 1





                  Don't know why but I had to add both READ and WRITE permissions : target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) target.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

                  – box
                  Oct 22 '18 at 8:54
















                107














                If targetSdkVersion is higher than 24, then FileProvider is used to grant access.



                Create an xml file(Path: resxml) provider_paths.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>





                Add a Provider in AndroidManifest.xml



                    <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>


                and replace



                Uri uri = Uri.fromFile(fileImagePath);


                to



                Uri uri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider",fileImagePath);


                Edit: While you're including the URI with an Intent make sure to add below line:



                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);


                and you are good to go. Hope it helps.






                share|improve this answer





















                • 1





                  @MaksimKniazev Can you describe your error in brief? So that I can help you.

                  – Pankaj Lilan
                  Nov 16 '17 at 11:47






                • 1





                  @PankajLilan, I did exactly what did you said. But everytime that I open my pdf in the other application it appears blank (its saving correctly). Should I need to edit the xml? I already added the FLAG_GRANT_READ_URI_PERMISSION as well;

                  – Felipe Castilhos
                  Mar 7 '18 at 18:14






                • 1





                  My mistake, I was adding the permission to the wrong intent. This is the best and the simpliest right answer. Thank you!

                  – Felipe Castilhos
                  Mar 7 '18 at 19:10








                • 2





                  It throws exception java.lang.IllegalArgumentException: Failed to find configured root that contains / My file path is /storage/emulated/0/GSMManage_DCIM/Documents/Device7298file_74.pdf. can you please help ?

                  – Jagdish Bhavsar
                  Mar 8 '18 at 13:07








                • 1





                  Don't know why but I had to add both READ and WRITE permissions : target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) target.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

                  – box
                  Oct 22 '18 at 8:54














                107












                107








                107







                If targetSdkVersion is higher than 24, then FileProvider is used to grant access.



                Create an xml file(Path: resxml) provider_paths.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>





                Add a Provider in AndroidManifest.xml



                    <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>


                and replace



                Uri uri = Uri.fromFile(fileImagePath);


                to



                Uri uri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider",fileImagePath);


                Edit: While you're including the URI with an Intent make sure to add below line:



                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);


                and you are good to go. Hope it helps.






                share|improve this answer















                If targetSdkVersion is higher than 24, then FileProvider is used to grant access.



                Create an xml file(Path: resxml) provider_paths.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>





                Add a Provider in AndroidManifest.xml



                    <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>


                and replace



                Uri uri = Uri.fromFile(fileImagePath);


                to



                Uri uri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider",fileImagePath);


                Edit: While you're including the URI with an Intent make sure to add below line:



                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);


                and you are good to go. Hope it helps.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jan 23 at 11:34

























                answered Aug 18 '17 at 7:58









                Pankaj LilanPankaj Lilan

                2,18911533




                2,18911533








                • 1





                  @MaksimKniazev Can you describe your error in brief? So that I can help you.

                  – Pankaj Lilan
                  Nov 16 '17 at 11:47






                • 1





                  @PankajLilan, I did exactly what did you said. But everytime that I open my pdf in the other application it appears blank (its saving correctly). Should I need to edit the xml? I already added the FLAG_GRANT_READ_URI_PERMISSION as well;

                  – Felipe Castilhos
                  Mar 7 '18 at 18:14






                • 1





                  My mistake, I was adding the permission to the wrong intent. This is the best and the simpliest right answer. Thank you!

                  – Felipe Castilhos
                  Mar 7 '18 at 19:10








                • 2





                  It throws exception java.lang.IllegalArgumentException: Failed to find configured root that contains / My file path is /storage/emulated/0/GSMManage_DCIM/Documents/Device7298file_74.pdf. can you please help ?

                  – Jagdish Bhavsar
                  Mar 8 '18 at 13:07








                • 1





                  Don't know why but I had to add both READ and WRITE permissions : target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) target.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

                  – box
                  Oct 22 '18 at 8:54














                • 1





                  @MaksimKniazev Can you describe your error in brief? So that I can help you.

                  – Pankaj Lilan
                  Nov 16 '17 at 11:47






                • 1





                  @PankajLilan, I did exactly what did you said. But everytime that I open my pdf in the other application it appears blank (its saving correctly). Should I need to edit the xml? I already added the FLAG_GRANT_READ_URI_PERMISSION as well;

                  – Felipe Castilhos
                  Mar 7 '18 at 18:14






                • 1





                  My mistake, I was adding the permission to the wrong intent. This is the best and the simpliest right answer. Thank you!

                  – Felipe Castilhos
                  Mar 7 '18 at 19:10








                • 2





                  It throws exception java.lang.IllegalArgumentException: Failed to find configured root that contains / My file path is /storage/emulated/0/GSMManage_DCIM/Documents/Device7298file_74.pdf. can you please help ?

                  – Jagdish Bhavsar
                  Mar 8 '18 at 13:07








                • 1





                  Don't know why but I had to add both READ and WRITE permissions : target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) target.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

                  – box
                  Oct 22 '18 at 8:54








                1




                1





                @MaksimKniazev Can you describe your error in brief? So that I can help you.

                – Pankaj Lilan
                Nov 16 '17 at 11:47





                @MaksimKniazev Can you describe your error in brief? So that I can help you.

                – Pankaj Lilan
                Nov 16 '17 at 11:47




                1




                1





                @PankajLilan, I did exactly what did you said. But everytime that I open my pdf in the other application it appears blank (its saving correctly). Should I need to edit the xml? I already added the FLAG_GRANT_READ_URI_PERMISSION as well;

                – Felipe Castilhos
                Mar 7 '18 at 18:14





                @PankajLilan, I did exactly what did you said. But everytime that I open my pdf in the other application it appears blank (its saving correctly). Should I need to edit the xml? I already added the FLAG_GRANT_READ_URI_PERMISSION as well;

                – Felipe Castilhos
                Mar 7 '18 at 18:14




                1




                1





                My mistake, I was adding the permission to the wrong intent. This is the best and the simpliest right answer. Thank you!

                – Felipe Castilhos
                Mar 7 '18 at 19:10







                My mistake, I was adding the permission to the wrong intent. This is the best and the simpliest right answer. Thank you!

                – Felipe Castilhos
                Mar 7 '18 at 19:10






                2




                2





                It throws exception java.lang.IllegalArgumentException: Failed to find configured root that contains / My file path is /storage/emulated/0/GSMManage_DCIM/Documents/Device7298file_74.pdf. can you please help ?

                – Jagdish Bhavsar
                Mar 8 '18 at 13:07







                It throws exception java.lang.IllegalArgumentException: Failed to find configured root that contains / My file path is /storage/emulated/0/GSMManage_DCIM/Documents/Device7298file_74.pdf. can you please help ?

                – Jagdish Bhavsar
                Mar 8 '18 at 13:07






                1




                1





                Don't know why but I had to add both READ and WRITE permissions : target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) target.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

                – box
                Oct 22 '18 at 8:54





                Don't know why but I had to add both READ and WRITE permissions : target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) target.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

                – box
                Oct 22 '18 at 8:54











                81














                If your targetSdkVersion is 24 or higher, you can not use file: Uri values in Intents on Android 7.0+ devices.



                Your choices are:




                1. Drop your targetSdkVersion to 23 or lower, or


                2. Put your content on internal storage, then use FileProvider to make it available selectively to other apps



                For example:



                Intent i=new Intent(Intent.ACTION_VIEW, FileProvider.getUriForFile(this, AUTHORITY, f));

                i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                startActivity(i);


                (from this sample project)






                share|improve this answer
























                • Thanks for the answer. What happens when I use this with files on the /system partition? Every app should be able to acces this partition without root.

                  – Thomas Vos
                  Jul 5 '16 at 12:56






                • 2





                  @SuperThomasLab: I would not count on everything in /system being world-readable. That being said, my guess is that you will still get this exception. I suspect that they are just checking the scheme and are not trying to determine if the file truly is world-readable. However, FileProvider will not help you, as you cannot teach it to serve from /system. You could create a custom strategy for my StreamProvider, or roll your own ContentProvider, to get past the problem.

                  – CommonsWare
                  Jul 5 '16 at 13:11











                • Still thinking how I'm going to solve this.. The app I am updating with Android N support is a root browser. But now you can't open any files anymore in root directories. (/data, /system), because of this "good change".

                  – Thomas Vos
                  Jul 5 '16 at 16:11






                • 1





                  what are the most important drawbacks to dropping targetSdkVersion to 23? thnx

                  – rommex
                  Jun 29 '17 at 14:06






                • 2





                  @rommex: I do not know what qualifies as "most important". For example, users who work in split-screen mode or on freeform multi-window devices (Chromebooks, Samsung DeX) will be told that your app may not work with multi-window. Whether that is important or not is up to you.

                  – CommonsWare
                  Jun 29 '17 at 14:34
















                81














                If your targetSdkVersion is 24 or higher, you can not use file: Uri values in Intents on Android 7.0+ devices.



                Your choices are:




                1. Drop your targetSdkVersion to 23 or lower, or


                2. Put your content on internal storage, then use FileProvider to make it available selectively to other apps



                For example:



                Intent i=new Intent(Intent.ACTION_VIEW, FileProvider.getUriForFile(this, AUTHORITY, f));

                i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                startActivity(i);


                (from this sample project)






                share|improve this answer
























                • Thanks for the answer. What happens when I use this with files on the /system partition? Every app should be able to acces this partition without root.

                  – Thomas Vos
                  Jul 5 '16 at 12:56






                • 2





                  @SuperThomasLab: I would not count on everything in /system being world-readable. That being said, my guess is that you will still get this exception. I suspect that they are just checking the scheme and are not trying to determine if the file truly is world-readable. However, FileProvider will not help you, as you cannot teach it to serve from /system. You could create a custom strategy for my StreamProvider, or roll your own ContentProvider, to get past the problem.

                  – CommonsWare
                  Jul 5 '16 at 13:11











                • Still thinking how I'm going to solve this.. The app I am updating with Android N support is a root browser. But now you can't open any files anymore in root directories. (/data, /system), because of this "good change".

                  – Thomas Vos
                  Jul 5 '16 at 16:11






                • 1





                  what are the most important drawbacks to dropping targetSdkVersion to 23? thnx

                  – rommex
                  Jun 29 '17 at 14:06






                • 2





                  @rommex: I do not know what qualifies as "most important". For example, users who work in split-screen mode or on freeform multi-window devices (Chromebooks, Samsung DeX) will be told that your app may not work with multi-window. Whether that is important or not is up to you.

                  – CommonsWare
                  Jun 29 '17 at 14:34














                81












                81








                81







                If your targetSdkVersion is 24 or higher, you can not use file: Uri values in Intents on Android 7.0+ devices.



                Your choices are:




                1. Drop your targetSdkVersion to 23 or lower, or


                2. Put your content on internal storage, then use FileProvider to make it available selectively to other apps



                For example:



                Intent i=new Intent(Intent.ACTION_VIEW, FileProvider.getUriForFile(this, AUTHORITY, f));

                i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                startActivity(i);


                (from this sample project)






                share|improve this answer













                If your targetSdkVersion is 24 or higher, you can not use file: Uri values in Intents on Android 7.0+ devices.



                Your choices are:




                1. Drop your targetSdkVersion to 23 or lower, or


                2. Put your content on internal storage, then use FileProvider to make it available selectively to other apps



                For example:



                Intent i=new Intent(Intent.ACTION_VIEW, FileProvider.getUriForFile(this, AUTHORITY, f));

                i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                startActivity(i);


                (from this sample project)







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jul 5 '16 at 12:42









                CommonsWareCommonsWare

                778k13918961943




                778k13918961943













                • Thanks for the answer. What happens when I use this with files on the /system partition? Every app should be able to acces this partition without root.

                  – Thomas Vos
                  Jul 5 '16 at 12:56






                • 2





                  @SuperThomasLab: I would not count on everything in /system being world-readable. That being said, my guess is that you will still get this exception. I suspect that they are just checking the scheme and are not trying to determine if the file truly is world-readable. However, FileProvider will not help you, as you cannot teach it to serve from /system. You could create a custom strategy for my StreamProvider, or roll your own ContentProvider, to get past the problem.

                  – CommonsWare
                  Jul 5 '16 at 13:11











                • Still thinking how I'm going to solve this.. The app I am updating with Android N support is a root browser. But now you can't open any files anymore in root directories. (/data, /system), because of this "good change".

                  – Thomas Vos
                  Jul 5 '16 at 16:11






                • 1





                  what are the most important drawbacks to dropping targetSdkVersion to 23? thnx

                  – rommex
                  Jun 29 '17 at 14:06






                • 2





                  @rommex: I do not know what qualifies as "most important". For example, users who work in split-screen mode or on freeform multi-window devices (Chromebooks, Samsung DeX) will be told that your app may not work with multi-window. Whether that is important or not is up to you.

                  – CommonsWare
                  Jun 29 '17 at 14:34



















                • Thanks for the answer. What happens when I use this with files on the /system partition? Every app should be able to acces this partition without root.

                  – Thomas Vos
                  Jul 5 '16 at 12:56






                • 2





                  @SuperThomasLab: I would not count on everything in /system being world-readable. That being said, my guess is that you will still get this exception. I suspect that they are just checking the scheme and are not trying to determine if the file truly is world-readable. However, FileProvider will not help you, as you cannot teach it to serve from /system. You could create a custom strategy for my StreamProvider, or roll your own ContentProvider, to get past the problem.

                  – CommonsWare
                  Jul 5 '16 at 13:11











                • Still thinking how I'm going to solve this.. The app I am updating with Android N support is a root browser. But now you can't open any files anymore in root directories. (/data, /system), because of this "good change".

                  – Thomas Vos
                  Jul 5 '16 at 16:11






                • 1





                  what are the most important drawbacks to dropping targetSdkVersion to 23? thnx

                  – rommex
                  Jun 29 '17 at 14:06






                • 2





                  @rommex: I do not know what qualifies as "most important". For example, users who work in split-screen mode or on freeform multi-window devices (Chromebooks, Samsung DeX) will be told that your app may not work with multi-window. Whether that is important or not is up to you.

                  – CommonsWare
                  Jun 29 '17 at 14:34

















                Thanks for the answer. What happens when I use this with files on the /system partition? Every app should be able to acces this partition without root.

                – Thomas Vos
                Jul 5 '16 at 12:56





                Thanks for the answer. What happens when I use this with files on the /system partition? Every app should be able to acces this partition without root.

                – Thomas Vos
                Jul 5 '16 at 12:56




                2




                2





                @SuperThomasLab: I would not count on everything in /system being world-readable. That being said, my guess is that you will still get this exception. I suspect that they are just checking the scheme and are not trying to determine if the file truly is world-readable. However, FileProvider will not help you, as you cannot teach it to serve from /system. You could create a custom strategy for my StreamProvider, or roll your own ContentProvider, to get past the problem.

                – CommonsWare
                Jul 5 '16 at 13:11





                @SuperThomasLab: I would not count on everything in /system being world-readable. That being said, my guess is that you will still get this exception. I suspect that they are just checking the scheme and are not trying to determine if the file truly is world-readable. However, FileProvider will not help you, as you cannot teach it to serve from /system. You could create a custom strategy for my StreamProvider, or roll your own ContentProvider, to get past the problem.

                – CommonsWare
                Jul 5 '16 at 13:11













                Still thinking how I'm going to solve this.. The app I am updating with Android N support is a root browser. But now you can't open any files anymore in root directories. (/data, /system), because of this "good change".

                – Thomas Vos
                Jul 5 '16 at 16:11





                Still thinking how I'm going to solve this.. The app I am updating with Android N support is a root browser. But now you can't open any files anymore in root directories. (/data, /system), because of this "good change".

                – Thomas Vos
                Jul 5 '16 at 16:11




                1




                1





                what are the most important drawbacks to dropping targetSdkVersion to 23? thnx

                – rommex
                Jun 29 '17 at 14:06





                what are the most important drawbacks to dropping targetSdkVersion to 23? thnx

                – rommex
                Jun 29 '17 at 14:06




                2




                2





                @rommex: I do not know what qualifies as "most important". For example, users who work in split-screen mode or on freeform multi-window devices (Chromebooks, Samsung DeX) will be told that your app may not work with multi-window. Whether that is important or not is up to you.

                – CommonsWare
                Jun 29 '17 at 14:34





                @rommex: I do not know what qualifies as "most important". For example, users who work in split-screen mode or on freeform multi-window devices (Chromebooks, Samsung DeX) will be told that your app may not work with multi-window. Whether that is important or not is up to you.

                – CommonsWare
                Jun 29 '17 at 14:34











                44














                First you need to add a provider to your AndroidManifest



                  <application
                ...>
                <activity>
                ....
                </activity>
                <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="com.your.package.fileProvider"
                android:grantUriPermissions="true"
                android:exported="false">
                <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
                </provider>
                </application>


                now create a file in xml resource folder (if using android studio you can hit Alt + Enter after highlighting file_paths and select create a xml resource option)



                Next in the file_paths file enter



                <?xml version="1.0" encoding="utf-8"?>
                <paths>
                <external-path path="Android/data/com.your.package/" name="files_root" />
                <external-path path="." name="external_storage_root" />
                </paths>


                This example is for external-path you can refere here for more options.
                This will allow you to share files which are in that folder and its sub-folder.



                Now all that's left is to create the intent as follows:



                    MimeTypeMap mime = MimeTypeMap.getSingleton();
                String ext = newFile.getName().substring(newFile.getName().lastIndexOf(".") + 1);
                String type = mime.getMimeTypeFromExtension(ext);
                try {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                Uri contentUri = FileProvider.getUriForFile(getContext(), "com.your.package.fileProvider", newFile);
                intent.setDataAndType(contentUri, type);
                } else {
                intent.setDataAndType(Uri.fromFile(newFile), type);
                }
                startActivityForResult(intent, ACTIVITY_VIEW_ATTACHMENT);
                } catch (ActivityNotFoundException anfe) {
                Toast.makeText(getContext(), "No activity found to open this attachment.", Toast.LENGTH_LONG).show();
                }


                EDIT: I added the root folder of the sd card in the file_paths. I have tested this code and it does work.






                share|improve this answer





















                • 1





                  Thank you for this. I also want to let you know that there is a better way to get the file extension. String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString()); Also, I recommend anyone looking for answers to read through FileProvider first and understand what you are dealing with here with file permissions in Android N and above. There are options for internal storage vs. external storage and also for regular files-path vs. cache-paths.

                  – praneetloke
                  Dec 31 '16 at 16:57








                • 1





                  I was getting the following exception: java.lang.IllegalArgumentException: Failed to find configured root ... and the only thing that worked was <files-path path="." name="files_root" /> on the xml file instead of <external-path .... My file was saved in the internal storage.

                  – MScott
                  Jun 30 '17 at 20:07
















                44














                First you need to add a provider to your AndroidManifest



                  <application
                ...>
                <activity>
                ....
                </activity>
                <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="com.your.package.fileProvider"
                android:grantUriPermissions="true"
                android:exported="false">
                <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
                </provider>
                </application>


                now create a file in xml resource folder (if using android studio you can hit Alt + Enter after highlighting file_paths and select create a xml resource option)



                Next in the file_paths file enter



                <?xml version="1.0" encoding="utf-8"?>
                <paths>
                <external-path path="Android/data/com.your.package/" name="files_root" />
                <external-path path="." name="external_storage_root" />
                </paths>


                This example is for external-path you can refere here for more options.
                This will allow you to share files which are in that folder and its sub-folder.



                Now all that's left is to create the intent as follows:



                    MimeTypeMap mime = MimeTypeMap.getSingleton();
                String ext = newFile.getName().substring(newFile.getName().lastIndexOf(".") + 1);
                String type = mime.getMimeTypeFromExtension(ext);
                try {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                Uri contentUri = FileProvider.getUriForFile(getContext(), "com.your.package.fileProvider", newFile);
                intent.setDataAndType(contentUri, type);
                } else {
                intent.setDataAndType(Uri.fromFile(newFile), type);
                }
                startActivityForResult(intent, ACTIVITY_VIEW_ATTACHMENT);
                } catch (ActivityNotFoundException anfe) {
                Toast.makeText(getContext(), "No activity found to open this attachment.", Toast.LENGTH_LONG).show();
                }


                EDIT: I added the root folder of the sd card in the file_paths. I have tested this code and it does work.






                share|improve this answer





















                • 1





                  Thank you for this. I also want to let you know that there is a better way to get the file extension. String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString()); Also, I recommend anyone looking for answers to read through FileProvider first and understand what you are dealing with here with file permissions in Android N and above. There are options for internal storage vs. external storage and also for regular files-path vs. cache-paths.

                  – praneetloke
                  Dec 31 '16 at 16:57








                • 1





                  I was getting the following exception: java.lang.IllegalArgumentException: Failed to find configured root ... and the only thing that worked was <files-path path="." name="files_root" /> on the xml file instead of <external-path .... My file was saved in the internal storage.

                  – MScott
                  Jun 30 '17 at 20:07














                44












                44








                44







                First you need to add a provider to your AndroidManifest



                  <application
                ...>
                <activity>
                ....
                </activity>
                <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="com.your.package.fileProvider"
                android:grantUriPermissions="true"
                android:exported="false">
                <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
                </provider>
                </application>


                now create a file in xml resource folder (if using android studio you can hit Alt + Enter after highlighting file_paths and select create a xml resource option)



                Next in the file_paths file enter



                <?xml version="1.0" encoding="utf-8"?>
                <paths>
                <external-path path="Android/data/com.your.package/" name="files_root" />
                <external-path path="." name="external_storage_root" />
                </paths>


                This example is for external-path you can refere here for more options.
                This will allow you to share files which are in that folder and its sub-folder.



                Now all that's left is to create the intent as follows:



                    MimeTypeMap mime = MimeTypeMap.getSingleton();
                String ext = newFile.getName().substring(newFile.getName().lastIndexOf(".") + 1);
                String type = mime.getMimeTypeFromExtension(ext);
                try {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                Uri contentUri = FileProvider.getUriForFile(getContext(), "com.your.package.fileProvider", newFile);
                intent.setDataAndType(contentUri, type);
                } else {
                intent.setDataAndType(Uri.fromFile(newFile), type);
                }
                startActivityForResult(intent, ACTIVITY_VIEW_ATTACHMENT);
                } catch (ActivityNotFoundException anfe) {
                Toast.makeText(getContext(), "No activity found to open this attachment.", Toast.LENGTH_LONG).show();
                }


                EDIT: I added the root folder of the sd card in the file_paths. I have tested this code and it does work.






                share|improve this answer















                First you need to add a provider to your AndroidManifest



                  <application
                ...>
                <activity>
                ....
                </activity>
                <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="com.your.package.fileProvider"
                android:grantUriPermissions="true"
                android:exported="false">
                <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
                </provider>
                </application>


                now create a file in xml resource folder (if using android studio you can hit Alt + Enter after highlighting file_paths and select create a xml resource option)



                Next in the file_paths file enter



                <?xml version="1.0" encoding="utf-8"?>
                <paths>
                <external-path path="Android/data/com.your.package/" name="files_root" />
                <external-path path="." name="external_storage_root" />
                </paths>


                This example is for external-path you can refere here for more options.
                This will allow you to share files which are in that folder and its sub-folder.



                Now all that's left is to create the intent as follows:



                    MimeTypeMap mime = MimeTypeMap.getSingleton();
                String ext = newFile.getName().substring(newFile.getName().lastIndexOf(".") + 1);
                String type = mime.getMimeTypeFromExtension(ext);
                try {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                Uri contentUri = FileProvider.getUriForFile(getContext(), "com.your.package.fileProvider", newFile);
                intent.setDataAndType(contentUri, type);
                } else {
                intent.setDataAndType(Uri.fromFile(newFile), type);
                }
                startActivityForResult(intent, ACTIVITY_VIEW_ATTACHMENT);
                } catch (ActivityNotFoundException anfe) {
                Toast.makeText(getContext(), "No activity found to open this attachment.", Toast.LENGTH_LONG).show();
                }


                EDIT: I added the root folder of the sd card in the file_paths. I have tested this code and it does work.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Aug 12 '16 at 19:59

























                answered Aug 12 '16 at 19:45









                Karn PatelKarn Patel

                441311




                441311








                • 1





                  Thank you for this. I also want to let you know that there is a better way to get the file extension. String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString()); Also, I recommend anyone looking for answers to read through FileProvider first and understand what you are dealing with here with file permissions in Android N and above. There are options for internal storage vs. external storage and also for regular files-path vs. cache-paths.

                  – praneetloke
                  Dec 31 '16 at 16:57








                • 1





                  I was getting the following exception: java.lang.IllegalArgumentException: Failed to find configured root ... and the only thing that worked was <files-path path="." name="files_root" /> on the xml file instead of <external-path .... My file was saved in the internal storage.

                  – MScott
                  Jun 30 '17 at 20:07














                • 1





                  Thank you for this. I also want to let you know that there is a better way to get the file extension. String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString()); Also, I recommend anyone looking for answers to read through FileProvider first and understand what you are dealing with here with file permissions in Android N and above. There are options for internal storage vs. external storage and also for regular files-path vs. cache-paths.

                  – praneetloke
                  Dec 31 '16 at 16:57








                • 1





                  I was getting the following exception: java.lang.IllegalArgumentException: Failed to find configured root ... and the only thing that worked was <files-path path="." name="files_root" /> on the xml file instead of <external-path .... My file was saved in the internal storage.

                  – MScott
                  Jun 30 '17 at 20:07








                1




                1





                Thank you for this. I also want to let you know that there is a better way to get the file extension. String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString()); Also, I recommend anyone looking for answers to read through FileProvider first and understand what you are dealing with here with file permissions in Android N and above. There are options for internal storage vs. external storage and also for regular files-path vs. cache-paths.

                – praneetloke
                Dec 31 '16 at 16:57







                Thank you for this. I also want to let you know that there is a better way to get the file extension. String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString()); Also, I recommend anyone looking for answers to read through FileProvider first and understand what you are dealing with here with file permissions in Android N and above. There are options for internal storage vs. external storage and also for regular files-path vs. cache-paths.

                – praneetloke
                Dec 31 '16 at 16:57






                1




                1





                I was getting the following exception: java.lang.IllegalArgumentException: Failed to find configured root ... and the only thing that worked was <files-path path="." name="files_root" /> on the xml file instead of <external-path .... My file was saved in the internal storage.

                – MScott
                Jun 30 '17 at 20:07





                I was getting the following exception: java.lang.IllegalArgumentException: Failed to find configured root ... and the only thing that worked was <files-path path="." name="files_root" /> on the xml file instead of <external-path .... My file was saved in the internal storage.

                – MScott
                Jun 30 '17 at 20:07











                25














                @palash k answer is correct and worked for internal storage files, but in my case I want to open files from external storage also, my app crashed when open file from external storage like sdcard and usb, but I manage to solve the issue by modifying provider_paths.xml from the accepted answer



                change the provider_paths.xml like below



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

                <external-path path="Android/data/${applicationId}/" name="files_root" />

                <root-path
                name="root"
                path="/" />

                </paths>


                and in java class(No change as the accepted answer just a small edit)



                Uri uri=FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID+".provider", File)


                This help me to fix the crash for files from external storages, Hope this will help some one having same issue as mine
                :)






                share|improve this answer





















                • 1





                  Where did you find about <root-path please ? It's working. <external-path path="Android/data/${applicationId}/" name="files_root" /> had no effect for open files from external storage.

                  – t0m
                  Mar 16 '17 at 11:23













                • i find this from various search results, let me check again and get back to u asap

                  – Ramz
                  Mar 16 '17 at 11:40











                • also the external storage you mention is sd card or inbuilt storage?

                  – Ramz
                  Mar 16 '17 at 11:41











                • Sorry for inaccuracy. I meant Android/data/${applicationId}/ in SDcard.

                  – t0m
                  Mar 20 '17 at 8:36






                • 1





                  Need to add this to the intent: intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                  – s-hunter
                  Feb 17 '18 at 15:25
















                25














                @palash k answer is correct and worked for internal storage files, but in my case I want to open files from external storage also, my app crashed when open file from external storage like sdcard and usb, but I manage to solve the issue by modifying provider_paths.xml from the accepted answer



                change the provider_paths.xml like below



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

                <external-path path="Android/data/${applicationId}/" name="files_root" />

                <root-path
                name="root"
                path="/" />

                </paths>


                and in java class(No change as the accepted answer just a small edit)



                Uri uri=FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID+".provider", File)


                This help me to fix the crash for files from external storages, Hope this will help some one having same issue as mine
                :)






                share|improve this answer





















                • 1





                  Where did you find about <root-path please ? It's working. <external-path path="Android/data/${applicationId}/" name="files_root" /> had no effect for open files from external storage.

                  – t0m
                  Mar 16 '17 at 11:23













                • i find this from various search results, let me check again and get back to u asap

                  – Ramz
                  Mar 16 '17 at 11:40











                • also the external storage you mention is sd card or inbuilt storage?

                  – Ramz
                  Mar 16 '17 at 11:41











                • Sorry for inaccuracy. I meant Android/data/${applicationId}/ in SDcard.

                  – t0m
                  Mar 20 '17 at 8:36






                • 1





                  Need to add this to the intent: intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                  – s-hunter
                  Feb 17 '18 at 15:25














                25












                25








                25







                @palash k answer is correct and worked for internal storage files, but in my case I want to open files from external storage also, my app crashed when open file from external storage like sdcard and usb, but I manage to solve the issue by modifying provider_paths.xml from the accepted answer



                change the provider_paths.xml like below



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

                <external-path path="Android/data/${applicationId}/" name="files_root" />

                <root-path
                name="root"
                path="/" />

                </paths>


                and in java class(No change as the accepted answer just a small edit)



                Uri uri=FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID+".provider", File)


                This help me to fix the crash for files from external storages, Hope this will help some one having same issue as mine
                :)






                share|improve this answer















                @palash k answer is correct and worked for internal storage files, but in my case I want to open files from external storage also, my app crashed when open file from external storage like sdcard and usb, but I manage to solve the issue by modifying provider_paths.xml from the accepted answer



                change the provider_paths.xml like below



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

                <external-path path="Android/data/${applicationId}/" name="files_root" />

                <root-path
                name="root"
                path="/" />

                </paths>


                and in java class(No change as the accepted answer just a small edit)



                Uri uri=FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID+".provider", File)


                This help me to fix the crash for files from external storages, Hope this will help some one having same issue as mine
                :)







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Feb 20 '17 at 21:24









                Vini.g.fer

                4,94093460




                4,94093460










                answered Jan 15 '17 at 11:59









                RamzRamz

                5,40665082




                5,40665082








                • 1





                  Where did you find about <root-path please ? It's working. <external-path path="Android/data/${applicationId}/" name="files_root" /> had no effect for open files from external storage.

                  – t0m
                  Mar 16 '17 at 11:23













                • i find this from various search results, let me check again and get back to u asap

                  – Ramz
                  Mar 16 '17 at 11:40











                • also the external storage you mention is sd card or inbuilt storage?

                  – Ramz
                  Mar 16 '17 at 11:41











                • Sorry for inaccuracy. I meant Android/data/${applicationId}/ in SDcard.

                  – t0m
                  Mar 20 '17 at 8:36






                • 1





                  Need to add this to the intent: intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                  – s-hunter
                  Feb 17 '18 at 15:25














                • 1





                  Where did you find about <root-path please ? It's working. <external-path path="Android/data/${applicationId}/" name="files_root" /> had no effect for open files from external storage.

                  – t0m
                  Mar 16 '17 at 11:23













                • i find this from various search results, let me check again and get back to u asap

                  – Ramz
                  Mar 16 '17 at 11:40











                • also the external storage you mention is sd card or inbuilt storage?

                  – Ramz
                  Mar 16 '17 at 11:41











                • Sorry for inaccuracy. I meant Android/data/${applicationId}/ in SDcard.

                  – t0m
                  Mar 20 '17 at 8:36






                • 1





                  Need to add this to the intent: intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                  – s-hunter
                  Feb 17 '18 at 15:25








                1




                1





                Where did you find about <root-path please ? It's working. <external-path path="Android/data/${applicationId}/" name="files_root" /> had no effect for open files from external storage.

                – t0m
                Mar 16 '17 at 11:23







                Where did you find about <root-path please ? It's working. <external-path path="Android/data/${applicationId}/" name="files_root" /> had no effect for open files from external storage.

                – t0m
                Mar 16 '17 at 11:23















                i find this from various search results, let me check again and get back to u asap

                – Ramz
                Mar 16 '17 at 11:40





                i find this from various search results, let me check again and get back to u asap

                – Ramz
                Mar 16 '17 at 11:40













                also the external storage you mention is sd card or inbuilt storage?

                – Ramz
                Mar 16 '17 at 11:41





                also the external storage you mention is sd card or inbuilt storage?

                – Ramz
                Mar 16 '17 at 11:41













                Sorry for inaccuracy. I meant Android/data/${applicationId}/ in SDcard.

                – t0m
                Mar 20 '17 at 8:36





                Sorry for inaccuracy. I meant Android/data/${applicationId}/ in SDcard.

                – t0m
                Mar 20 '17 at 8:36




                1




                1





                Need to add this to the intent: intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                – s-hunter
                Feb 17 '18 at 15:25





                Need to add this to the intent: intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                – s-hunter
                Feb 17 '18 at 15:25











                19














                Just paste the below code in activity onCreate()



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


                It will ignore URI exposure






                share|improve this answer
























                • this is one of the solutions but not the standard one. Stil people who downvoted the answers are wrong as the this is also working code with the working solution.

                  – saksham
                  Apr 18 '18 at 10:16
















                19














                Just paste the below code in activity onCreate()



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


                It will ignore URI exposure






                share|improve this answer
























                • this is one of the solutions but not the standard one. Stil people who downvoted the answers are wrong as the this is also working code with the working solution.

                  – saksham
                  Apr 18 '18 at 10:16














                19












                19








                19







                Just paste the below code in activity onCreate()



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


                It will ignore URI exposure






                share|improve this answer













                Just paste the below code in activity onCreate()



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


                It will ignore URI exposure







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 16 '18 at 6:50









                Kaushal SachanKaushal Sachan

                27734




                27734













                • this is one of the solutions but not the standard one. Stil people who downvoted the answers are wrong as the this is also working code with the working solution.

                  – saksham
                  Apr 18 '18 at 10:16



















                • this is one of the solutions but not the standard one. Stil people who downvoted the answers are wrong as the this is also working code with the working solution.

                  – saksham
                  Apr 18 '18 at 10:16

















                this is one of the solutions but not the standard one. Stil people who downvoted the answers are wrong as the this is also working code with the working solution.

                – saksham
                Apr 18 '18 at 10:16





                this is one of the solutions but not the standard one. Stil people who downvoted the answers are wrong as the this is also working code with the working solution.

                – saksham
                Apr 18 '18 at 10:16











                18














                Using the fileProvider is the way to go.
                But you can use this simple workaround:




                WARNING: It will be fixed in next Android release -
                https://issuetracker.google.com/issues/37122890#comment4




                replace:



                startActivity(intent);


                by



                startActivity(Intent.createChooser(intent, "Your title"));





                share|improve this answer





















                • 7





                  The chooser will be patched soon by Google to contain same check. This is not a solution.

                  – Pointer Null
                  Feb 24 '17 at 11:31











                • This one works but will not work in future android versions.

                  – Diljeet
                  Apr 25 '17 at 7:28






                • 2





                  this dont work on android 8 and upper

                  – ArMo 372
                  Apr 9 '18 at 6:25
















                18














                Using the fileProvider is the way to go.
                But you can use this simple workaround:




                WARNING: It will be fixed in next Android release -
                https://issuetracker.google.com/issues/37122890#comment4




                replace:



                startActivity(intent);


                by



                startActivity(Intent.createChooser(intent, "Your title"));





                share|improve this answer





















                • 7





                  The chooser will be patched soon by Google to contain same check. This is not a solution.

                  – Pointer Null
                  Feb 24 '17 at 11:31











                • This one works but will not work in future android versions.

                  – Diljeet
                  Apr 25 '17 at 7:28






                • 2





                  this dont work on android 8 and upper

                  – ArMo 372
                  Apr 9 '18 at 6:25














                18












                18








                18







                Using the fileProvider is the way to go.
                But you can use this simple workaround:




                WARNING: It will be fixed in next Android release -
                https://issuetracker.google.com/issues/37122890#comment4




                replace:



                startActivity(intent);


                by



                startActivity(Intent.createChooser(intent, "Your title"));





                share|improve this answer















                Using the fileProvider is the way to go.
                But you can use this simple workaround:




                WARNING: It will be fixed in next Android release -
                https://issuetracker.google.com/issues/37122890#comment4




                replace:



                startActivity(intent);


                by



                startActivity(Intent.createChooser(intent, "Your title"));






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Apr 14 '17 at 7:59









                Maksim Ostrovidov

                6,03732752




                6,03732752










                answered Feb 8 '17 at 3:02









                SimonSimon

                588619




                588619








                • 7





                  The chooser will be patched soon by Google to contain same check. This is not a solution.

                  – Pointer Null
                  Feb 24 '17 at 11:31











                • This one works but will not work in future android versions.

                  – Diljeet
                  Apr 25 '17 at 7:28






                • 2





                  this dont work on android 8 and upper

                  – ArMo 372
                  Apr 9 '18 at 6:25














                • 7





                  The chooser will be patched soon by Google to contain same check. This is not a solution.

                  – Pointer Null
                  Feb 24 '17 at 11:31











                • This one works but will not work in future android versions.

                  – Diljeet
                  Apr 25 '17 at 7:28






                • 2





                  this dont work on android 8 and upper

                  – ArMo 372
                  Apr 9 '18 at 6:25








                7




                7





                The chooser will be patched soon by Google to contain same check. This is not a solution.

                – Pointer Null
                Feb 24 '17 at 11:31





                The chooser will be patched soon by Google to contain same check. This is not a solution.

                – Pointer Null
                Feb 24 '17 at 11:31













                This one works but will not work in future android versions.

                – Diljeet
                Apr 25 '17 at 7:28





                This one works but will not work in future android versions.

                – Diljeet
                Apr 25 '17 at 7:28




                2




                2





                this dont work on android 8 and upper

                – ArMo 372
                Apr 9 '18 at 6:25





                this dont work on android 8 and upper

                – ArMo 372
                Apr 9 '18 at 6:25











                13














                My Solution was to 'Uri.parse' the File Path as String, instead of using Uri.fromFile().



                String storage = Environment.getExternalStorageDirectory().toString() + "/test.txt";
                File file = new File(storage);
                Uri uri;
                if (Build.VERSION.SDK_INT < 24) {
                uri = Uri.fromFile(file);
                } else {
                uri = Uri.parse(file.getPath()); // My work-around for new SDKs, causes ActivityNotFoundException in API 10.
                }
                Intent viewFile = new Intent(Intent.ACTION_VIEW);
                viewFile.setDataAndType(uri, "text/plain");
                startActivity(viewFile);


                Seems that fromFile() uses A file pointer, which I suppose could be insecure when memory addresses are exposed to all apps. But A file path String never hurt anybody, so it works without throwing FileUriExposedException.



                Tested on API levels 9 to 26! Does not require FileProvider, nor the Android Support Library at all.






                share|improve this answer


























                • I wish I'd seen this first. I didn't prove it worked for me, but it's so much less cumbersome than FileProvider.

                  – Dale
                  Nov 20 '18 at 16:52











                • A note on why this actually works: It's not the File pointer that casues the issue, but the fact that the exception only occurs if you have a path with 'file://', which is automatically prepended with fromFile, but not with parse.

                  – Xmister
                  Jan 24 at 9:53













                • This does not get exception, but it can't send the file to the related app either. So, not worked for me.

                  – Serdar Samancıoğlu
                  Mar 14 at 14:11


















                13














                My Solution was to 'Uri.parse' the File Path as String, instead of using Uri.fromFile().



                String storage = Environment.getExternalStorageDirectory().toString() + "/test.txt";
                File file = new File(storage);
                Uri uri;
                if (Build.VERSION.SDK_INT < 24) {
                uri = Uri.fromFile(file);
                } else {
                uri = Uri.parse(file.getPath()); // My work-around for new SDKs, causes ActivityNotFoundException in API 10.
                }
                Intent viewFile = new Intent(Intent.ACTION_VIEW);
                viewFile.setDataAndType(uri, "text/plain");
                startActivity(viewFile);


                Seems that fromFile() uses A file pointer, which I suppose could be insecure when memory addresses are exposed to all apps. But A file path String never hurt anybody, so it works without throwing FileUriExposedException.



                Tested on API levels 9 to 26! Does not require FileProvider, nor the Android Support Library at all.






                share|improve this answer


























                • I wish I'd seen this first. I didn't prove it worked for me, but it's so much less cumbersome than FileProvider.

                  – Dale
                  Nov 20 '18 at 16:52











                • A note on why this actually works: It's not the File pointer that casues the issue, but the fact that the exception only occurs if you have a path with 'file://', which is automatically prepended with fromFile, but not with parse.

                  – Xmister
                  Jan 24 at 9:53













                • This does not get exception, but it can't send the file to the related app either. So, not worked for me.

                  – Serdar Samancıoğlu
                  Mar 14 at 14:11
















                13












                13








                13







                My Solution was to 'Uri.parse' the File Path as String, instead of using Uri.fromFile().



                String storage = Environment.getExternalStorageDirectory().toString() + "/test.txt";
                File file = new File(storage);
                Uri uri;
                if (Build.VERSION.SDK_INT < 24) {
                uri = Uri.fromFile(file);
                } else {
                uri = Uri.parse(file.getPath()); // My work-around for new SDKs, causes ActivityNotFoundException in API 10.
                }
                Intent viewFile = new Intent(Intent.ACTION_VIEW);
                viewFile.setDataAndType(uri, "text/plain");
                startActivity(viewFile);


                Seems that fromFile() uses A file pointer, which I suppose could be insecure when memory addresses are exposed to all apps. But A file path String never hurt anybody, so it works without throwing FileUriExposedException.



                Tested on API levels 9 to 26! Does not require FileProvider, nor the Android Support Library at all.






                share|improve this answer















                My Solution was to 'Uri.parse' the File Path as String, instead of using Uri.fromFile().



                String storage = Environment.getExternalStorageDirectory().toString() + "/test.txt";
                File file = new File(storage);
                Uri uri;
                if (Build.VERSION.SDK_INT < 24) {
                uri = Uri.fromFile(file);
                } else {
                uri = Uri.parse(file.getPath()); // My work-around for new SDKs, causes ActivityNotFoundException in API 10.
                }
                Intent viewFile = new Intent(Intent.ACTION_VIEW);
                viewFile.setDataAndType(uri, "text/plain");
                startActivity(viewFile);


                Seems that fromFile() uses A file pointer, which I suppose could be insecure when memory addresses are exposed to all apps. But A file path String never hurt anybody, so it works without throwing FileUriExposedException.



                Tested on API levels 9 to 26! Does not require FileProvider, nor the Android Support Library at all.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 21 '18 at 18:24

























                answered Oct 22 '18 at 9:15









                CrazyJ36CrazyJ36

                13913




                13913













                • I wish I'd seen this first. I didn't prove it worked for me, but it's so much less cumbersome than FileProvider.

                  – Dale
                  Nov 20 '18 at 16:52











                • A note on why this actually works: It's not the File pointer that casues the issue, but the fact that the exception only occurs if you have a path with 'file://', which is automatically prepended with fromFile, but not with parse.

                  – Xmister
                  Jan 24 at 9:53













                • This does not get exception, but it can't send the file to the related app either. So, not worked for me.

                  – Serdar Samancıoğlu
                  Mar 14 at 14:11





















                • I wish I'd seen this first. I didn't prove it worked for me, but it's so much less cumbersome than FileProvider.

                  – Dale
                  Nov 20 '18 at 16:52











                • A note on why this actually works: It's not the File pointer that casues the issue, but the fact that the exception only occurs if you have a path with 'file://', which is automatically prepended with fromFile, but not with parse.

                  – Xmister
                  Jan 24 at 9:53













                • This does not get exception, but it can't send the file to the related app either. So, not worked for me.

                  – Serdar Samancıoğlu
                  Mar 14 at 14:11



















                I wish I'd seen this first. I didn't prove it worked for me, but it's so much less cumbersome than FileProvider.

                – Dale
                Nov 20 '18 at 16:52





                I wish I'd seen this first. I didn't prove it worked for me, but it's so much less cumbersome than FileProvider.

                – Dale
                Nov 20 '18 at 16:52













                A note on why this actually works: It's not the File pointer that casues the issue, but the fact that the exception only occurs if you have a path with 'file://', which is automatically prepended with fromFile, but not with parse.

                – Xmister
                Jan 24 at 9:53







                A note on why this actually works: It's not the File pointer that casues the issue, but the fact that the exception only occurs if you have a path with 'file://', which is automatically prepended with fromFile, but not with parse.

                – Xmister
                Jan 24 at 9:53















                This does not get exception, but it can't send the file to the related app either. So, not worked for me.

                – Serdar Samancıoğlu
                Mar 14 at 14:11







                This does not get exception, but it can't send the file to the related app either. So, not worked for me.

                – Serdar Samancıoğlu
                Mar 14 at 14:11













                12














                I used Palash's answer given above but it was somewhat incomplete, I had to provide permission like this



                Intent intent = new Intent(Intent.ACTION_VIEW);
                Uri uri;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                uri = FileProvider.getUriForFile(this, getPackageName() + ".provider", new File(path));

                List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
                for (ResolveInfo resolveInfo : resInfoList) {
                String packageName = resolveInfo.activityInfo.packageName;
                grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                }
                }else {
                uri = Uri.fromFile(new File(path));
                }

                intent.setDataAndType(uri, "application/vnd.android.package-archive");

                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                startActivity(intent);





                share|improve this answer




























                  12














                  I used Palash's answer given above but it was somewhat incomplete, I had to provide permission like this



                  Intent intent = new Intent(Intent.ACTION_VIEW);
                  Uri uri;
                  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                  uri = FileProvider.getUriForFile(this, getPackageName() + ".provider", new File(path));

                  List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
                  for (ResolveInfo resolveInfo : resInfoList) {
                  String packageName = resolveInfo.activityInfo.packageName;
                  grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                  }
                  }else {
                  uri = Uri.fromFile(new File(path));
                  }

                  intent.setDataAndType(uri, "application/vnd.android.package-archive");

                  intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                  startActivity(intent);





                  share|improve this answer


























                    12












                    12








                    12







                    I used Palash's answer given above but it was somewhat incomplete, I had to provide permission like this



                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    Uri uri;
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    uri = FileProvider.getUriForFile(this, getPackageName() + ".provider", new File(path));

                    List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
                    for (ResolveInfo resolveInfo : resInfoList) {
                    String packageName = resolveInfo.activityInfo.packageName;
                    grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    }
                    }else {
                    uri = Uri.fromFile(new File(path));
                    }

                    intent.setDataAndType(uri, "application/vnd.android.package-archive");

                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                    startActivity(intent);





                    share|improve this answer













                    I used Palash's answer given above but it was somewhat incomplete, I had to provide permission like this



                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    Uri uri;
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    uri = FileProvider.getUriForFile(this, getPackageName() + ".provider", new File(path));

                    List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
                    for (ResolveInfo resolveInfo : resInfoList) {
                    String packageName = resolveInfo.activityInfo.packageName;
                    grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    }
                    }else {
                    uri = Uri.fromFile(new File(path));
                    }

                    intent.setDataAndType(uri, "application/vnd.android.package-archive");

                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                    startActivity(intent);






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Dec 11 '16 at 16:05









                    MaxMax

                    7,31933652




                    7,31933652























                        11














                        Just paste the below code in activity onCreate().



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


                        It will ignore URI exposure.



                        Happy coding :-)






                        share|improve this answer






























                          11














                          Just paste the below code in activity onCreate().



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


                          It will ignore URI exposure.



                          Happy coding :-)






                          share|improve this answer




























                            11












                            11








                            11







                            Just paste the below code in activity onCreate().



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


                            It will ignore URI exposure.



                            Happy coding :-)






                            share|improve this answer















                            Just paste the below code in activity onCreate().



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


                            It will ignore URI exposure.



                            Happy coding :-)







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Feb 13 at 23:46









                            Math

                            94




                            94










                            answered Sep 20 '18 at 9:15









                            Ripdaman SinghRipdaman Singh

                            18914




                            18914























                                3














                                I don't know why, I did everything exactly the same as Pkosta (https://stackoverflow.com/a/38858040 ) but kept getting error:



                                java.lang.SecurityException: Permission Denial: opening provider redacted from ProcessRecord{redacted} (redacted) that is not exported from uid redacted



                                I wasted hours on this issue. The culprit? Kotlin.



                                val playIntent = Intent(Intent.ACTION_VIEW, uri)
                                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)


                                intent was actually setting getIntent().addFlags instead of operating on my newly declared playIntent.






                                share|improve this answer




























                                  3














                                  I don't know why, I did everything exactly the same as Pkosta (https://stackoverflow.com/a/38858040 ) but kept getting error:



                                  java.lang.SecurityException: Permission Denial: opening provider redacted from ProcessRecord{redacted} (redacted) that is not exported from uid redacted



                                  I wasted hours on this issue. The culprit? Kotlin.



                                  val playIntent = Intent(Intent.ACTION_VIEW, uri)
                                  intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)


                                  intent was actually setting getIntent().addFlags instead of operating on my newly declared playIntent.






                                  share|improve this answer


























                                    3












                                    3








                                    3







                                    I don't know why, I did everything exactly the same as Pkosta (https://stackoverflow.com/a/38858040 ) but kept getting error:



                                    java.lang.SecurityException: Permission Denial: opening provider redacted from ProcessRecord{redacted} (redacted) that is not exported from uid redacted



                                    I wasted hours on this issue. The culprit? Kotlin.



                                    val playIntent = Intent(Intent.ACTION_VIEW, uri)
                                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)


                                    intent was actually setting getIntent().addFlags instead of operating on my newly declared playIntent.






                                    share|improve this answer













                                    I don't know why, I did everything exactly the same as Pkosta (https://stackoverflow.com/a/38858040 ) but kept getting error:



                                    java.lang.SecurityException: Permission Denial: opening provider redacted from ProcessRecord{redacted} (redacted) that is not exported from uid redacted



                                    I wasted hours on this issue. The culprit? Kotlin.



                                    val playIntent = Intent(Intent.ACTION_VIEW, uri)
                                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)


                                    intent was actually setting getIntent().addFlags instead of operating on my newly declared playIntent.







                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Sep 17 '18 at 12:59









                                    jimbo1qazjimbo1qaz

                                    820925




                                    820925























                                        2














                                        For downloading pdf from server , add below code in your service class. Hope this is helpful for you.



                                        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName + ".pdf");
                                        intent = new Intent(Intent.ACTION_VIEW);
                                        //Log.e("pathOpen", file.getPath());

                                        Uri contentUri;
                                        contentUri = Uri.fromFile(file);
                                        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);

                                        if (Build.VERSION.SDK_INT >= 24) {

                                        Uri apkURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", file);
                                        intent.setDataAndType(apkURI, "application/pdf");
                                        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                                        } else {

                                        intent.setDataAndType(contentUri, "application/pdf");
                                        }


                                        And yes , don't forget to add permissions and provider in your manifest.



                                        <uses-permission android:name="android.permission.INTERNET" />
                                        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
                                        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

                                        <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>





                                        share|improve this answer


























                                        • what is @xml/provider_paths ?

                                          – Heisenberg
                                          Nov 30 '18 at 12:35
















                                        2














                                        For downloading pdf from server , add below code in your service class. Hope this is helpful for you.



                                        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName + ".pdf");
                                        intent = new Intent(Intent.ACTION_VIEW);
                                        //Log.e("pathOpen", file.getPath());

                                        Uri contentUri;
                                        contentUri = Uri.fromFile(file);
                                        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);

                                        if (Build.VERSION.SDK_INT >= 24) {

                                        Uri apkURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", file);
                                        intent.setDataAndType(apkURI, "application/pdf");
                                        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                                        } else {

                                        intent.setDataAndType(contentUri, "application/pdf");
                                        }


                                        And yes , don't forget to add permissions and provider in your manifest.



                                        <uses-permission android:name="android.permission.INTERNET" />
                                        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
                                        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

                                        <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>





                                        share|improve this answer


























                                        • what is @xml/provider_paths ?

                                          – Heisenberg
                                          Nov 30 '18 at 12:35














                                        2












                                        2








                                        2







                                        For downloading pdf from server , add below code in your service class. Hope this is helpful for you.



                                        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName + ".pdf");
                                        intent = new Intent(Intent.ACTION_VIEW);
                                        //Log.e("pathOpen", file.getPath());

                                        Uri contentUri;
                                        contentUri = Uri.fromFile(file);
                                        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);

                                        if (Build.VERSION.SDK_INT >= 24) {

                                        Uri apkURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", file);
                                        intent.setDataAndType(apkURI, "application/pdf");
                                        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                                        } else {

                                        intent.setDataAndType(contentUri, "application/pdf");
                                        }


                                        And yes , don't forget to add permissions and provider in your manifest.



                                        <uses-permission android:name="android.permission.INTERNET" />
                                        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
                                        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

                                        <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>





                                        share|improve this answer















                                        For downloading pdf from server , add below code in your service class. Hope this is helpful for you.



                                        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName + ".pdf");
                                        intent = new Intent(Intent.ACTION_VIEW);
                                        //Log.e("pathOpen", file.getPath());

                                        Uri contentUri;
                                        contentUri = Uri.fromFile(file);
                                        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);

                                        if (Build.VERSION.SDK_INT >= 24) {

                                        Uri apkURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", file);
                                        intent.setDataAndType(apkURI, "application/pdf");
                                        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                                        } else {

                                        intent.setDataAndType(contentUri, "application/pdf");
                                        }


                                        And yes , don't forget to add permissions and provider in your manifest.



                                        <uses-permission android:name="android.permission.INTERNET" />
                                        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
                                        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

                                        <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>






                                        share|improve this answer














                                        share|improve this answer



                                        share|improve this answer








                                        edited Jul 28 '18 at 12:23

























                                        answered Jul 28 '18 at 11:57









                                        Bhoomika ChauhanBhoomika Chauhan

                                        413




                                        413













                                        • what is @xml/provider_paths ?

                                          – Heisenberg
                                          Nov 30 '18 at 12:35



















                                        • what is @xml/provider_paths ?

                                          – Heisenberg
                                          Nov 30 '18 at 12:35

















                                        what is @xml/provider_paths ?

                                        – Heisenberg
                                        Nov 30 '18 at 12:35





                                        what is @xml/provider_paths ?

                                        – Heisenberg
                                        Nov 30 '18 at 12:35











                                        0














                                        add this two line in onCreate



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


                                        Share method



                                        File dir = new File(Environment.getExternalStorageDirectory(), "ColorStory");

                                        File imgFile = new File(dir, "0.png");

                                        Intent sendIntent = new Intent(Intent.ACTION_VIEW);
                                        sendIntent.setType("image/*");
                                        sendIntent.setAction(Intent.ACTION_SEND);
                                        sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + imgFile));
                                        sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                                        startActivity(Intent.createChooser(sendIntent, "Share images..."));





                                        share|improve this answer






























                                          0














                                          add this two line in onCreate



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


                                          Share method



                                          File dir = new File(Environment.getExternalStorageDirectory(), "ColorStory");

                                          File imgFile = new File(dir, "0.png");

                                          Intent sendIntent = new Intent(Intent.ACTION_VIEW);
                                          sendIntent.setType("image/*");
                                          sendIntent.setAction(Intent.ACTION_SEND);
                                          sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + imgFile));
                                          sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                                          startActivity(Intent.createChooser(sendIntent, "Share images..."));





                                          share|improve this answer




























                                            0












                                            0








                                            0







                                            add this two line in onCreate



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


                                            Share method



                                            File dir = new File(Environment.getExternalStorageDirectory(), "ColorStory");

                                            File imgFile = new File(dir, "0.png");

                                            Intent sendIntent = new Intent(Intent.ACTION_VIEW);
                                            sendIntent.setType("image/*");
                                            sendIntent.setAction(Intent.ACTION_SEND);
                                            sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + imgFile));
                                            sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                                            startActivity(Intent.createChooser(sendIntent, "Share images..."));





                                            share|improve this answer















                                            add this two line in onCreate



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


                                            Share method



                                            File dir = new File(Environment.getExternalStorageDirectory(), "ColorStory");

                                            File imgFile = new File(dir, "0.png");

                                            Intent sendIntent = new Intent(Intent.ACTION_VIEW);
                                            sendIntent.setType("image/*");
                                            sendIntent.setAction(Intent.ACTION_SEND);
                                            sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + imgFile));
                                            sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                                            startActivity(Intent.createChooser(sendIntent, "Share images..."));






                                            share|improve this answer














                                            share|improve this answer



                                            share|improve this answer








                                            edited 20 hours ago

























                                            answered Mar 13 at 9:17









                                            Khairun NaharKhairun Nahar

                                            11




                                            11























                                                -1














                                                https://stackoverflow.com/a/38858040/395097 this answer is complete.



                                                This answer is for - you already have an app which was targeting below 24, and now you are upgrading to targetSDKVersion >= 24.



                                                In Android N, only the file uri exposed to 3rd party app is changed. (Not the way we were using it before). So change only the places where you are sharing the path with 3rd party app (Camera in my case)



                                                In our app we were sending uri to Camera app, in that location we are expecting the camera app to store the captured image.




                                                1. For android N, we generate new Content:// uri based url pointing to
                                                  file.

                                                2. We generate usual File api based path for the same (using older method).


                                                Now we have 2 different uri for same file. #1 is shared with Camera app. If the camera intent is success, we can access the image from #2.



                                                Hope this helps.






                                                share|improve this answer



















                                                • 1





                                                  You are referencing a answer already posted here, if you need to complete it, comment in the answer plz.

                                                  – IgniteCoders
                                                  May 9 '18 at 18:12








                                                • 1





                                                  @IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.

                                                  – Aram
                                                  May 10 '18 at 6:46
















                                                -1














                                                https://stackoverflow.com/a/38858040/395097 this answer is complete.



                                                This answer is for - you already have an app which was targeting below 24, and now you are upgrading to targetSDKVersion >= 24.



                                                In Android N, only the file uri exposed to 3rd party app is changed. (Not the way we were using it before). So change only the places where you are sharing the path with 3rd party app (Camera in my case)



                                                In our app we were sending uri to Camera app, in that location we are expecting the camera app to store the captured image.




                                                1. For android N, we generate new Content:// uri based url pointing to
                                                  file.

                                                2. We generate usual File api based path for the same (using older method).


                                                Now we have 2 different uri for same file. #1 is shared with Camera app. If the camera intent is success, we can access the image from #2.



                                                Hope this helps.






                                                share|improve this answer



















                                                • 1





                                                  You are referencing a answer already posted here, if you need to complete it, comment in the answer plz.

                                                  – IgniteCoders
                                                  May 9 '18 at 18:12








                                                • 1





                                                  @IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.

                                                  – Aram
                                                  May 10 '18 at 6:46














                                                -1












                                                -1








                                                -1







                                                https://stackoverflow.com/a/38858040/395097 this answer is complete.



                                                This answer is for - you already have an app which was targeting below 24, and now you are upgrading to targetSDKVersion >= 24.



                                                In Android N, only the file uri exposed to 3rd party app is changed. (Not the way we were using it before). So change only the places where you are sharing the path with 3rd party app (Camera in my case)



                                                In our app we were sending uri to Camera app, in that location we are expecting the camera app to store the captured image.




                                                1. For android N, we generate new Content:// uri based url pointing to
                                                  file.

                                                2. We generate usual File api based path for the same (using older method).


                                                Now we have 2 different uri for same file. #1 is shared with Camera app. If the camera intent is success, we can access the image from #2.



                                                Hope this helps.






                                                share|improve this answer













                                                https://stackoverflow.com/a/38858040/395097 this answer is complete.



                                                This answer is for - you already have an app which was targeting below 24, and now you are upgrading to targetSDKVersion >= 24.



                                                In Android N, only the file uri exposed to 3rd party app is changed. (Not the way we were using it before). So change only the places where you are sharing the path with 3rd party app (Camera in my case)



                                                In our app we were sending uri to Camera app, in that location we are expecting the camera app to store the captured image.




                                                1. For android N, we generate new Content:// uri based url pointing to
                                                  file.

                                                2. We generate usual File api based path for the same (using older method).


                                                Now we have 2 different uri for same file. #1 is shared with Camera app. If the camera intent is success, we can access the image from #2.



                                                Hope this helps.







                                                share|improve this answer












                                                share|improve this answer



                                                share|improve this answer










                                                answered Apr 30 '18 at 7:20









                                                AramAram

                                                277119




                                                277119








                                                • 1





                                                  You are referencing a answer already posted here, if you need to complete it, comment in the answer plz.

                                                  – IgniteCoders
                                                  May 9 '18 at 18:12








                                                • 1





                                                  @IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.

                                                  – Aram
                                                  May 10 '18 at 6:46














                                                • 1





                                                  You are referencing a answer already posted here, if you need to complete it, comment in the answer plz.

                                                  – IgniteCoders
                                                  May 9 '18 at 18:12








                                                • 1





                                                  @IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.

                                                  – Aram
                                                  May 10 '18 at 6:46








                                                1




                                                1





                                                You are referencing a answer already posted here, if you need to complete it, comment in the answer plz.

                                                – IgniteCoders
                                                May 9 '18 at 18:12







                                                You are referencing a answer already posted here, if you need to complete it, comment in the answer plz.

                                                – IgniteCoders
                                                May 9 '18 at 18:12






                                                1




                                                1





                                                @IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.

                                                – Aram
                                                May 10 '18 at 6:46





                                                @IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.

                                                – Aram
                                                May 10 '18 at 6:46











                                                -1














                                                Xamarin.Android



                                                Note: The path xml/provider_paths.xml (.axml) couldn't be resolved, even after making the xml folder under Resources (maybe it can be put in an existing location like Values, didn't try), so I resorted to this which works for now. Testing showed that it only needs to be called once per application run (which makes sense being that it changes the operational state of the host VM).



                                                Note: xml needs to be capitalized, so Resources/Xml/provider_paths.xml



                                                Java.Lang.ClassLoader cl = _this.Context.ClassLoader;
                                                Java.Lang.Class strictMode = cl.LoadClass("android.os.StrictMode");
                                                System.IntPtr ptrStrictMode = JNIEnv.FindClass("android/os/StrictMode");
                                                var method = JNIEnv.GetStaticMethodID(ptrStrictMode, "disableDeathOnFileUriExposure", "()V");
                                                JNIEnv.CallStaticVoidMethod(strictMode.Handle, method);





                                                share|improve this answer






























                                                  -1














                                                  Xamarin.Android



                                                  Note: The path xml/provider_paths.xml (.axml) couldn't be resolved, even after making the xml folder under Resources (maybe it can be put in an existing location like Values, didn't try), so I resorted to this which works for now. Testing showed that it only needs to be called once per application run (which makes sense being that it changes the operational state of the host VM).



                                                  Note: xml needs to be capitalized, so Resources/Xml/provider_paths.xml



                                                  Java.Lang.ClassLoader cl = _this.Context.ClassLoader;
                                                  Java.Lang.Class strictMode = cl.LoadClass("android.os.StrictMode");
                                                  System.IntPtr ptrStrictMode = JNIEnv.FindClass("android/os/StrictMode");
                                                  var method = JNIEnv.GetStaticMethodID(ptrStrictMode, "disableDeathOnFileUriExposure", "()V");
                                                  JNIEnv.CallStaticVoidMethod(strictMode.Handle, method);





                                                  share|improve this answer




























                                                    -1












                                                    -1








                                                    -1







                                                    Xamarin.Android



                                                    Note: The path xml/provider_paths.xml (.axml) couldn't be resolved, even after making the xml folder under Resources (maybe it can be put in an existing location like Values, didn't try), so I resorted to this which works for now. Testing showed that it only needs to be called once per application run (which makes sense being that it changes the operational state of the host VM).



                                                    Note: xml needs to be capitalized, so Resources/Xml/provider_paths.xml



                                                    Java.Lang.ClassLoader cl = _this.Context.ClassLoader;
                                                    Java.Lang.Class strictMode = cl.LoadClass("android.os.StrictMode");
                                                    System.IntPtr ptrStrictMode = JNIEnv.FindClass("android/os/StrictMode");
                                                    var method = JNIEnv.GetStaticMethodID(ptrStrictMode, "disableDeathOnFileUriExposure", "()V");
                                                    JNIEnv.CallStaticVoidMethod(strictMode.Handle, method);





                                                    share|improve this answer















                                                    Xamarin.Android



                                                    Note: The path xml/provider_paths.xml (.axml) couldn't be resolved, even after making the xml folder under Resources (maybe it can be put in an existing location like Values, didn't try), so I resorted to this which works for now. Testing showed that it only needs to be called once per application run (which makes sense being that it changes the operational state of the host VM).



                                                    Note: xml needs to be capitalized, so Resources/Xml/provider_paths.xml



                                                    Java.Lang.ClassLoader cl = _this.Context.ClassLoader;
                                                    Java.Lang.Class strictMode = cl.LoadClass("android.os.StrictMode");
                                                    System.IntPtr ptrStrictMode = JNIEnv.FindClass("android/os/StrictMode");
                                                    var method = JNIEnv.GetStaticMethodID(ptrStrictMode, "disableDeathOnFileUriExposure", "()V");
                                                    JNIEnv.CallStaticVoidMethod(strictMode.Handle, method);






                                                    share|improve this answer














                                                    share|improve this answer



                                                    share|improve this answer








                                                    edited Sep 26 '18 at 14:48

























                                                    answered Sep 26 '18 at 13:18









                                                    samissamis

                                                    3,51362251




                                                    3,51362251























                                                        -1














                                                        @Pkosta 's answer is one way of doing this.



                                                        Besides using FileProvider, you can also insert the file into MediaStore (especially for image and video files), because files in MediaStore are accessible to every app:




                                                        The MediaStore is primarily aimed at video, audio and image MIME types, however beginning with Android 3.0 (API level 11) it can also store non-media types (see MediaStore.Files for more info). Files can be inserted into the MediaStore using scanFile() after which a content:// style Uri suitable for sharing is passed to the provided onScanCompleted() callback. Note that once added to the system MediaStore the content is accessible to any app on the device.




                                                        For example, you can insert a video file to MediaStore like this:



                                                        ContentValues values = new ContentValues();
                                                        values.put(MediaStore.Video.Media.DATA, videoFilePath);
                                                        Uri contentUri = context.getContentResolver().insert(
                                                        MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);


                                                        contentUri is like content://media/external/video/media/183473, which can be passed directly to Intent.putExtra:



                                                        intent.setType("video/*");
                                                        intent.putExtra(Intent.EXTRA_STREAM, contentUri);
                                                        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                                                        activity.startActivity(intent);


                                                        This works for me, and save the hassles of using FileProvider.






                                                        share|improve this answer




























                                                          -1














                                                          @Pkosta 's answer is one way of doing this.



                                                          Besides using FileProvider, you can also insert the file into MediaStore (especially for image and video files), because files in MediaStore are accessible to every app:




                                                          The MediaStore is primarily aimed at video, audio and image MIME types, however beginning with Android 3.0 (API level 11) it can also store non-media types (see MediaStore.Files for more info). Files can be inserted into the MediaStore using scanFile() after which a content:// style Uri suitable for sharing is passed to the provided onScanCompleted() callback. Note that once added to the system MediaStore the content is accessible to any app on the device.




                                                          For example, you can insert a video file to MediaStore like this:



                                                          ContentValues values = new ContentValues();
                                                          values.put(MediaStore.Video.Media.DATA, videoFilePath);
                                                          Uri contentUri = context.getContentResolver().insert(
                                                          MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);


                                                          contentUri is like content://media/external/video/media/183473, which can be passed directly to Intent.putExtra:



                                                          intent.setType("video/*");
                                                          intent.putExtra(Intent.EXTRA_STREAM, contentUri);
                                                          intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                                                          activity.startActivity(intent);


                                                          This works for me, and save the hassles of using FileProvider.






                                                          share|improve this answer


























                                                            -1












                                                            -1








                                                            -1







                                                            @Pkosta 's answer is one way of doing this.



                                                            Besides using FileProvider, you can also insert the file into MediaStore (especially for image and video files), because files in MediaStore are accessible to every app:




                                                            The MediaStore is primarily aimed at video, audio and image MIME types, however beginning with Android 3.0 (API level 11) it can also store non-media types (see MediaStore.Files for more info). Files can be inserted into the MediaStore using scanFile() after which a content:// style Uri suitable for sharing is passed to the provided onScanCompleted() callback. Note that once added to the system MediaStore the content is accessible to any app on the device.




                                                            For example, you can insert a video file to MediaStore like this:



                                                            ContentValues values = new ContentValues();
                                                            values.put(MediaStore.Video.Media.DATA, videoFilePath);
                                                            Uri contentUri = context.getContentResolver().insert(
                                                            MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);


                                                            contentUri is like content://media/external/video/media/183473, which can be passed directly to Intent.putExtra:



                                                            intent.setType("video/*");
                                                            intent.putExtra(Intent.EXTRA_STREAM, contentUri);
                                                            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                                                            activity.startActivity(intent);


                                                            This works for me, and save the hassles of using FileProvider.






                                                            share|improve this answer













                                                            @Pkosta 's answer is one way of doing this.



                                                            Besides using FileProvider, you can also insert the file into MediaStore (especially for image and video files), because files in MediaStore are accessible to every app:




                                                            The MediaStore is primarily aimed at video, audio and image MIME types, however beginning with Android 3.0 (API level 11) it can also store non-media types (see MediaStore.Files for more info). Files can be inserted into the MediaStore using scanFile() after which a content:// style Uri suitable for sharing is passed to the provided onScanCompleted() callback. Note that once added to the system MediaStore the content is accessible to any app on the device.




                                                            For example, you can insert a video file to MediaStore like this:



                                                            ContentValues values = new ContentValues();
                                                            values.put(MediaStore.Video.Media.DATA, videoFilePath);
                                                            Uri contentUri = context.getContentResolver().insert(
                                                            MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);


                                                            contentUri is like content://media/external/video/media/183473, which can be passed directly to Intent.putExtra:



                                                            intent.setType("video/*");
                                                            intent.putExtra(Intent.EXTRA_STREAM, contentUri);
                                                            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                                                            activity.startActivity(intent);


                                                            This works for me, and save the hassles of using FileProvider.







                                                            share|improve this answer












                                                            share|improve this answer



                                                            share|improve this answer










                                                            answered Jan 25 at 12:02









                                                            NeoWangNeoWang

                                                            5,598114691




                                                            5,598114691























                                                                -2














                                                                In my case I got rid of the exception by replacing SetDataAndType with just SetData.






                                                                share|improve this answer




























                                                                  -2














                                                                  In my case I got rid of the exception by replacing SetDataAndType with just SetData.






                                                                  share|improve this answer


























                                                                    -2












                                                                    -2








                                                                    -2







                                                                    In my case I got rid of the exception by replacing SetDataAndType with just SetData.






                                                                    share|improve this answer













                                                                    In my case I got rid of the exception by replacing SetDataAndType with just SetData.







                                                                    share|improve this answer












                                                                    share|improve this answer



                                                                    share|improve this answer










                                                                    answered Aug 29 '18 at 0:45









                                                                    thomielthomiel

                                                                    1,4031023




                                                                    1,4031023






























                                                                        draft saved

                                                                        draft discarded




















































                                                                        Thanks for contributing an answer to Stack Overflow!


                                                                        • Please be sure to answer the question. Provide details and share your research!

                                                                        But avoid



                                                                        • Asking for help, clarification, or responding to other answers.

                                                                        • Making statements based on opinion; back them up with references or personal experience.


                                                                        To learn more, see our tips on writing great answers.




                                                                        draft saved


                                                                        draft discarded














                                                                        StackExchange.ready(
                                                                        function () {
                                                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f38200282%2fandroid-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed%23new-answer', 'question_page');
                                                                        }
                                                                        );

                                                                        Post as a guest















                                                                        Required, but never shown





















































                                                                        Required, but never shown














                                                                        Required, but never shown












                                                                        Required, but never shown







                                                                        Required, but never shown

































                                                                        Required, but never shown














                                                                        Required, but never shown












                                                                        Required, but never shown







                                                                        Required, but never shown







                                                                        Popular posts from this blog

                                                                        Create new schema in PostgreSQL using DBeaver

                                                                        Deepest pit of an array with Javascript: test on Codility

                                                                        Costa Masnaga