android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()
up vote
515
down vote
favorite
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?
add a comment |
up vote
515
down vote
favorite
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?
3
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 at 11:36
try this , small and perfect code stackoverflow.com/a/52695444/4997704
– Binesh Kumar
Oct 8 at 4:38
add a comment |
up vote
515
down vote
favorite
up vote
515
down vote
favorite
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?
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?
edited Feb 2 at 17:32
asked Jul 5 '16 at 9:51
Thomas Vos
4,05041748
4,05041748
3
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 at 11:36
try this , small and perfect code stackoverflow.com/a/52695444/4997704
– Binesh Kumar
Oct 8 at 4:38
add a comment |
3
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 at 11:36
try this , small and perfect code stackoverflow.com/a/52695444/4997704
– Binesh Kumar
Oct 8 at 4:38
3
3
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 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 at 11:36
try this , small and perfect code stackoverflow.com/a/52695444/4997704
– Binesh Kumar
Oct 8 at 4:38
try this , small and perfect code stackoverflow.com/a/52695444/4997704
– Binesh Kumar
Oct 8 at 4:38
add a comment |
17 Answers
17
active
oldest
votes
up vote
956
down vote
accepted
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
FileProviderpublic class GenericFileProvider extends FileProviderAdd a FileProvider
<provider>tag inAndroidManifest.xmlunder<application>tag. Specify a unique authority for theandroid:authoritiesattribute to avoid conflicts, imported dependencies might specify$applicationId.providerand 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.xmlfile inres/xmlfolder. 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.
44
I just needed to add intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
– alorma
Nov 22 '16 at 15:11
19
Will it work for all Android versions, or just from API 24?
– android developer
Nov 24 '16 at 17:43
3
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
30
FileProvidershould be extended only if you want to override any of the default behavior, otherwise useandroid:name="android.support.v4.content.FileProvider". See developer.android.com/reference/android/support/v4/content/…
– JP Ventura
Jan 15 at 21:56
|
show 14 more comments
up vote
249
down vote
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.
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 newVmPolicy.
– 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 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 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 at 19:08
|
show 5 more comments
up vote
125
down vote
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?).
3
"while files served over content scheme can't be (can they?)." -- sure, if you have write access to the content.ContentResolverhas bothopenInputStream()andopenOutputStream(). A less-hacky way of doing this is to just configure the VM rules yourself, and do not enable thefileUrirule.
– CommonsWare
Feb 25 '17 at 17:13
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
1
Android 7.0 (S8+) and Emulator 8.0 is worked. Thanks
– hungtdo
Oct 31 '17 at 4:23
2
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 at 12:26
|
show 18 more comments
up vote
87
down vote
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);
and you are good to go. Hope it helps.
did not helped me
– Maksim Kniazev
Nov 16 '17 at 6:30
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 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 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 at 13:07
|
show 7 more comments
up vote
78
down vote
If your targetSdkVersion is 24 or higher, you can not use file: Uri values in Intents on Android 7.0+ devices.
Your choices are:
Drop your
targetSdkVersionto 23 or lower, orPut your content on internal storage, then use
FileProviderto 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)
Thanks for the answer. What happens when I use this with files on the/systempartition? 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/systembeing 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,FileProviderwill not help you, as you cannot teach it to serve from/system. You could create a custom strategy for myStreamProvider, or roll your ownContentProvider, 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
|
show 12 more comments
up vote
43
down vote
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.
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
add a comment |
up vote
24
down vote
@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
:)
1
Where did you find about<root-pathplease ? 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 meantAndroid/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 at 15:25
|
show 1 more comment
up vote
17
down vote
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"));
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 at 6:25
this work for me. Thanks
– Sujeet Kumar
Aug 10 at 11:19
add a comment |
up vote
16
down vote
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
It works perfectly fine
– Sushant Garg
Jan 24 at 9:49
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 at 10:16
worked for me,thanks
– Meerz
Sep 2 at 19:48
1
Simple yet perfect.
– Nikita Vishwakarma
Oct 15 at 8:32
1
Simply a genius.... Thanks!!! Less code more solutions!! :D
– Blasco73
Oct 17 at 10:13
add a comment |
up vote
11
down vote
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
else
uri = Uri.fromFile(new File(path));
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
add a comment |
up vote
5
down vote
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.
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 at 16:52
add a comment |
up vote
2
down vote
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 ProcessRecordredacted (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.
add a comment |
up vote
1
down vote
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>
add a comment |
up vote
0
down vote
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 :-)
add a comment |
up vote
-1
down vote
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.
- For android N, we generate new Content:// uri based url pointing to
file. - 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.
1
You are referencing a answer already posted here, if you need to complete it, comment in the answer plz.
– IgniteCoders
May 9 at 18:12
1
@IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.
– Aram
May 10 at 6:46
add a comment |
up vote
-1
down vote
In my case I got rid of the exception by replacing SetDataAndType with just SetData.
add a comment |
up vote
-1
down vote
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);
add a comment |
17 Answers
17
active
oldest
votes
17 Answers
17
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
956
down vote
accepted
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
FileProviderpublic class GenericFileProvider extends FileProviderAdd a FileProvider
<provider>tag inAndroidManifest.xmlunder<application>tag. Specify a unique authority for theandroid:authoritiesattribute to avoid conflicts, imported dependencies might specify$applicationId.providerand 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.xmlfile inres/xmlfolder. 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.
44
I just needed to add intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
– alorma
Nov 22 '16 at 15:11
19
Will it work for all Android versions, or just from API 24?
– android developer
Nov 24 '16 at 17:43
3
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
30
FileProvidershould be extended only if you want to override any of the default behavior, otherwise useandroid:name="android.support.v4.content.FileProvider". See developer.android.com/reference/android/support/v4/content/…
– JP Ventura
Jan 15 at 21:56
|
show 14 more comments
up vote
956
down vote
accepted
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
FileProviderpublic class GenericFileProvider extends FileProviderAdd a FileProvider
<provider>tag inAndroidManifest.xmlunder<application>tag. Specify a unique authority for theandroid:authoritiesattribute to avoid conflicts, imported dependencies might specify$applicationId.providerand 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.xmlfile inres/xmlfolder. 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.
44
I just needed to add intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
– alorma
Nov 22 '16 at 15:11
19
Will it work for all Android versions, or just from API 24?
– android developer
Nov 24 '16 at 17:43
3
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
30
FileProvidershould be extended only if you want to override any of the default behavior, otherwise useandroid:name="android.support.v4.content.FileProvider". See developer.android.com/reference/android/support/v4/content/…
– JP Ventura
Jan 15 at 21:56
|
show 14 more comments
up vote
956
down vote
accepted
up vote
956
down vote
accepted
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
FileProviderpublic class GenericFileProvider extends FileProviderAdd a FileProvider
<provider>tag inAndroidManifest.xmlunder<application>tag. Specify a unique authority for theandroid:authoritiesattribute to avoid conflicts, imported dependencies might specify$applicationId.providerand 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.xmlfile inres/xmlfolder. 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.
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
FileProviderpublic class GenericFileProvider extends FileProviderAdd a FileProvider
<provider>tag inAndroidManifest.xmlunder<application>tag. Specify a unique authority for theandroid:authoritiesattribute to avoid conflicts, imported dependencies might specify$applicationId.providerand 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.xmlfile inres/xmlfolder. 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.
edited Oct 30 at 1:38
jachguate
15.4k14383
15.4k14383
answered Aug 9 '16 at 18:33
Pkosta
9,750157
9,750157
44
I just needed to add intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
– alorma
Nov 22 '16 at 15:11
19
Will it work for all Android versions, or just from API 24?
– android developer
Nov 24 '16 at 17:43
3
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
30
FileProvidershould be extended only if you want to override any of the default behavior, otherwise useandroid:name="android.support.v4.content.FileProvider". See developer.android.com/reference/android/support/v4/content/…
– JP Ventura
Jan 15 at 21:56
|
show 14 more comments
44
I just needed to add intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
– alorma
Nov 22 '16 at 15:11
19
Will it work for all Android versions, or just from API 24?
– android developer
Nov 24 '16 at 17:43
3
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
30
FileProvidershould be extended only if you want to override any of the default behavior, otherwise useandroid:name="android.support.v4.content.FileProvider". See developer.android.com/reference/android/support/v4/content/…
– JP Ventura
Jan 15 at 21:56
44
44
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
19
19
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
3
3
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
30
30
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 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 at 21:56
|
show 14 more comments
up vote
249
down vote
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.
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 newVmPolicy.
– 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 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 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 at 19:08
|
show 5 more comments
up vote
249
down vote
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.
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 newVmPolicy.
– 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 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 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 at 19:08
|
show 5 more comments
up vote
249
down vote
up vote
249
down vote
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.
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.
edited Jan 6 at 10:56
answered Nov 18 '16 at 10:31
hqzxzwb
2,5471512
2,5471512
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 newVmPolicy.
– 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 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 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 at 19:08
|
show 5 more comments
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 newVmPolicy.
– 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 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 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 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 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 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 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 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 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 at 19:08
|
show 5 more comments
up vote
125
down vote
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?).
3
"while files served over content scheme can't be (can they?)." -- sure, if you have write access to the content.ContentResolverhas bothopenInputStream()andopenOutputStream(). A less-hacky way of doing this is to just configure the VM rules yourself, and do not enable thefileUrirule.
– CommonsWare
Feb 25 '17 at 17:13
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
1
Android 7.0 (S8+) and Emulator 8.0 is worked. Thanks
– hungtdo
Oct 31 '17 at 4:23
2
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 at 12:26
|
show 18 more comments
up vote
125
down vote
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?).
3
"while files served over content scheme can't be (can they?)." -- sure, if you have write access to the content.ContentResolverhas bothopenInputStream()andopenOutputStream(). A less-hacky way of doing this is to just configure the VM rules yourself, and do not enable thefileUrirule.
– CommonsWare
Feb 25 '17 at 17:13
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
1
Android 7.0 (S8+) and Emulator 8.0 is worked. Thanks
– hungtdo
Oct 31 '17 at 4:23
2
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 at 12:26
|
show 18 more comments
up vote
125
down vote
up vote
125
down vote
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?).
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?).
edited Feb 24 '17 at 11:29
answered Feb 24 '17 at 11:21
Pointer Null
28.3k126995
28.3k126995
3
"while files served over content scheme can't be (can they?)." -- sure, if you have write access to the content.ContentResolverhas bothopenInputStream()andopenOutputStream(). A less-hacky way of doing this is to just configure the VM rules yourself, and do not enable thefileUrirule.
– CommonsWare
Feb 25 '17 at 17:13
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
1
Android 7.0 (S8+) and Emulator 8.0 is worked. Thanks
– hungtdo
Oct 31 '17 at 4:23
2
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 at 12:26
|
show 18 more comments
3
"while files served over content scheme can't be (can they?)." -- sure, if you have write access to the content.ContentResolverhas bothopenInputStream()andopenOutputStream(). A less-hacky way of doing this is to just configure the VM rules yourself, and do not enable thefileUrirule.
– CommonsWare
Feb 25 '17 at 17:13
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
1
Android 7.0 (S8+) and Emulator 8.0 is worked. Thanks
– hungtdo
Oct 31 '17 at 4:23
2
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 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
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
1
1
Android 7.0 (S8+) and Emulator 8.0 is worked. Thanks
– hungtdo
Oct 31 '17 at 4:23
Android 7.0 (S8+) and Emulator 8.0 is worked. Thanks
– hungtdo
Oct 31 '17 at 4:23
2
2
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 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 at 12:26
|
show 18 more comments
up vote
87
down vote
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);
and you are good to go. Hope it helps.
did not helped me
– Maksim Kniazev
Nov 16 '17 at 6:30
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 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 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 at 13:07
|
show 7 more comments
up vote
87
down vote
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);
and you are good to go. Hope it helps.
did not helped me
– Maksim Kniazev
Nov 16 '17 at 6:30
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 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 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 at 13:07
|
show 7 more comments
up vote
87
down vote
up vote
87
down vote
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);
and you are good to go. Hope it helps.
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);
and you are good to go. Hope it helps.
edited Nov 1 '17 at 5:13
answered Aug 18 '17 at 7:58
Pankaj Lilan
1,9311331
1,9311331
did not helped me
– Maksim Kniazev
Nov 16 '17 at 6:30
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 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 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 at 13:07
|
show 7 more comments
did not helped me
– Maksim Kniazev
Nov 16 '17 at 6:30
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 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 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 at 13:07
did not helped me
– Maksim Kniazev
Nov 16 '17 at 6:30
did not helped me
– Maksim Kniazev
Nov 16 '17 at 6:30
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 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 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 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 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 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 at 13:07
|
show 7 more comments
up vote
78
down vote
If your targetSdkVersion is 24 or higher, you can not use file: Uri values in Intents on Android 7.0+ devices.
Your choices are:
Drop your
targetSdkVersionto 23 or lower, orPut your content on internal storage, then use
FileProviderto 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)
Thanks for the answer. What happens when I use this with files on the/systempartition? 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/systembeing 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,FileProviderwill not help you, as you cannot teach it to serve from/system. You could create a custom strategy for myStreamProvider, or roll your ownContentProvider, 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
|
show 12 more comments
up vote
78
down vote
If your targetSdkVersion is 24 or higher, you can not use file: Uri values in Intents on Android 7.0+ devices.
Your choices are:
Drop your
targetSdkVersionto 23 or lower, orPut your content on internal storage, then use
FileProviderto 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)
Thanks for the answer. What happens when I use this with files on the/systempartition? 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/systembeing 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,FileProviderwill not help you, as you cannot teach it to serve from/system. You could create a custom strategy for myStreamProvider, or roll your ownContentProvider, 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
|
show 12 more comments
up vote
78
down vote
up vote
78
down vote
If your targetSdkVersion is 24 or higher, you can not use file: Uri values in Intents on Android 7.0+ devices.
Your choices are:
Drop your
targetSdkVersionto 23 or lower, orPut your content on internal storage, then use
FileProviderto 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)
If your targetSdkVersion is 24 or higher, you can not use file: Uri values in Intents on Android 7.0+ devices.
Your choices are:
Drop your
targetSdkVersionto 23 or lower, orPut your content on internal storage, then use
FileProviderto 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)
answered Jul 5 '16 at 12:42
CommonsWare
758k13718471901
758k13718471901
Thanks for the answer. What happens when I use this with files on the/systempartition? 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/systembeing 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,FileProviderwill not help you, as you cannot teach it to serve from/system. You could create a custom strategy for myStreamProvider, or roll your ownContentProvider, 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
|
show 12 more comments
Thanks for the answer. What happens when I use this with files on the/systempartition? 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/systembeing 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,FileProviderwill not help you, as you cannot teach it to serve from/system. You could create a custom strategy for myStreamProvider, or roll your ownContentProvider, 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
|
show 12 more comments
up vote
43
down vote
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.
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
add a comment |
up vote
43
down vote
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.
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
add a comment |
up vote
43
down vote
up vote
43
down vote
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.
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.
edited Aug 12 '16 at 19:59
answered Aug 12 '16 at 19:45
Karn Patel
431310
431310
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
add a comment |
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
add a comment |
up vote
24
down vote
@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
:)
1
Where did you find about<root-pathplease ? 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 meantAndroid/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 at 15:25
|
show 1 more comment
up vote
24
down vote
@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
:)
1
Where did you find about<root-pathplease ? 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 meantAndroid/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 at 15:25
|
show 1 more comment
up vote
24
down vote
up vote
24
down vote
@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
:)
@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
:)
edited Feb 20 '17 at 21:24
Vini.g.fer
4,82883357
4,82883357
answered Jan 15 '17 at 11:59
Ramz
5,23654882
5,23654882
1
Where did you find about<root-pathplease ? 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 meantAndroid/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 at 15:25
|
show 1 more comment
1
Where did you find about<root-pathplease ? 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 meantAndroid/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 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 at 15:25
Need to add this to the intent: intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
– s-hunter
Feb 17 at 15:25
|
show 1 more comment
up vote
17
down vote
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"));
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 at 6:25
this work for me. Thanks
– Sujeet Kumar
Aug 10 at 11:19
add a comment |
up vote
17
down vote
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"));
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 at 6:25
this work for me. Thanks
– Sujeet Kumar
Aug 10 at 11:19
add a comment |
up vote
17
down vote
up vote
17
down vote
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"));
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"));
edited Apr 14 '17 at 7:59
Maksim Ostrovidov
5,57022751
5,57022751
answered Feb 8 '17 at 3:02
Simon
518618
518618
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 at 6:25
this work for me. Thanks
– Sujeet Kumar
Aug 10 at 11:19
add a comment |
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 at 6:25
this work for me. Thanks
– Sujeet Kumar
Aug 10 at 11:19
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 at 6:25
this dont work on android 8 and upper
– ArMo 372
Apr 9 at 6:25
this work for me. Thanks
– Sujeet Kumar
Aug 10 at 11:19
this work for me. Thanks
– Sujeet Kumar
Aug 10 at 11:19
add a comment |
up vote
16
down vote
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
It works perfectly fine
– Sushant Garg
Jan 24 at 9:49
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 at 10:16
worked for me,thanks
– Meerz
Sep 2 at 19:48
1
Simple yet perfect.
– Nikita Vishwakarma
Oct 15 at 8:32
1
Simply a genius.... Thanks!!! Less code more solutions!! :D
– Blasco73
Oct 17 at 10:13
add a comment |
up vote
16
down vote
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
It works perfectly fine
– Sushant Garg
Jan 24 at 9:49
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 at 10:16
worked for me,thanks
– Meerz
Sep 2 at 19:48
1
Simple yet perfect.
– Nikita Vishwakarma
Oct 15 at 8:32
1
Simply a genius.... Thanks!!! Less code more solutions!! :D
– Blasco73
Oct 17 at 10:13
add a comment |
up vote
16
down vote
up vote
16
down vote
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
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
answered Jan 16 at 6:50
Kaushal Sachan
20713
20713
It works perfectly fine
– Sushant Garg
Jan 24 at 9:49
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 at 10:16
worked for me,thanks
– Meerz
Sep 2 at 19:48
1
Simple yet perfect.
– Nikita Vishwakarma
Oct 15 at 8:32
1
Simply a genius.... Thanks!!! Less code more solutions!! :D
– Blasco73
Oct 17 at 10:13
add a comment |
It works perfectly fine
– Sushant Garg
Jan 24 at 9:49
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 at 10:16
worked for me,thanks
– Meerz
Sep 2 at 19:48
1
Simple yet perfect.
– Nikita Vishwakarma
Oct 15 at 8:32
1
Simply a genius.... Thanks!!! Less code more solutions!! :D
– Blasco73
Oct 17 at 10:13
It works perfectly fine
– Sushant Garg
Jan 24 at 9:49
It works perfectly fine
– Sushant Garg
Jan 24 at 9:49
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 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 at 10:16
worked for me,thanks
– Meerz
Sep 2 at 19:48
worked for me,thanks
– Meerz
Sep 2 at 19:48
1
1
Simple yet perfect.
– Nikita Vishwakarma
Oct 15 at 8:32
Simple yet perfect.
– Nikita Vishwakarma
Oct 15 at 8:32
1
1
Simply a genius.... Thanks!!! Less code more solutions!! :D
– Blasco73
Oct 17 at 10:13
Simply a genius.... Thanks!!! Less code more solutions!! :D
– Blasco73
Oct 17 at 10:13
add a comment |
up vote
11
down vote
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
else
uri = Uri.fromFile(new File(path));
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
add a comment |
up vote
11
down vote
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
else
uri = Uri.fromFile(new File(path));
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
add a comment |
up vote
11
down vote
up vote
11
down vote
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
else
uri = Uri.fromFile(new File(path));
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
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
else
uri = Uri.fromFile(new File(path));
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
answered Dec 11 '16 at 16:05
Max
6,59233250
6,59233250
add a comment |
add a comment |
up vote
5
down vote
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.
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 at 16:52
add a comment |
up vote
5
down vote
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.
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 at 16:52
add a comment |
up vote
5
down vote
up vote
5
down vote
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.
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.
edited Nov 21 at 18:24
answered Oct 22 at 9:15
CrazyJ36
5912
5912
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 at 16:52
add a comment |
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 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 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 at 16:52
add a comment |
up vote
2
down vote
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 ProcessRecordredacted (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.
add a comment |
up vote
2
down vote
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 ProcessRecordredacted (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.
add a comment |
up vote
2
down vote
up vote
2
down vote
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 ProcessRecordredacted (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.
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 ProcessRecordredacted (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.
answered Sep 17 at 12:59
jimbo1qaz
701824
701824
add a comment |
add a comment |
up vote
1
down vote
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>
add a comment |
up vote
1
down vote
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>
add a comment |
up vote
1
down vote
up vote
1
down vote
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>
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>
edited Jul 28 at 12:23
answered Jul 28 at 11:57
Bhoomika Chauhan
313
313
add a comment |
add a comment |
up vote
0
down vote
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 :-)
add a comment |
up vote
0
down vote
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 :-)
add a comment |
up vote
0
down vote
up vote
0
down vote
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 :-)
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 :-)
answered Sep 20 at 9:15
Ripdaman Singh
693
693
add a comment |
add a comment |
up vote
-1
down vote
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.
- For android N, we generate new Content:// uri based url pointing to
file. - 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.
1
You are referencing a answer already posted here, if you need to complete it, comment in the answer plz.
– IgniteCoders
May 9 at 18:12
1
@IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.
– Aram
May 10 at 6:46
add a comment |
up vote
-1
down vote
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.
- For android N, we generate new Content:// uri based url pointing to
file. - 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.
1
You are referencing a answer already posted here, if you need to complete it, comment in the answer plz.
– IgniteCoders
May 9 at 18:12
1
@IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.
– Aram
May 10 at 6:46
add a comment |
up vote
-1
down vote
up vote
-1
down vote
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.
- For android N, we generate new Content:// uri based url pointing to
file. - 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.
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.
- For android N, we generate new Content:// uri based url pointing to
file. - 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.
answered Apr 30 at 7:20
Aram
222116
222116
1
You are referencing a answer already posted here, if you need to complete it, comment in the answer plz.
– IgniteCoders
May 9 at 18:12
1
@IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.
– Aram
May 10 at 6:46
add a comment |
1
You are referencing a answer already posted here, if you need to complete it, comment in the answer plz.
– IgniteCoders
May 9 at 18:12
1
@IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.
– Aram
May 10 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 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 at 18:12
1
1
@IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.
– Aram
May 10 at 6:46
@IgniteCoders As I clearly mentioned in the message, my answer covers the related use case.
– Aram
May 10 at 6:46
add a comment |
up vote
-1
down vote
In my case I got rid of the exception by replacing SetDataAndType with just SetData.
add a comment |
up vote
-1
down vote
In my case I got rid of the exception by replacing SetDataAndType with just SetData.
add a comment |
up vote
-1
down vote
up vote
-1
down vote
In my case I got rid of the exception by replacing SetDataAndType with just SetData.
In my case I got rid of the exception by replacing SetDataAndType with just SetData.
answered Aug 29 at 0:45
thomiel
1,3481023
1,3481023
add a comment |
add a comment |
up vote
-1
down vote
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);
add a comment |
up vote
-1
down vote
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);
add a comment |
up vote
-1
down vote
up vote
-1
down vote
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);
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);
edited Sep 26 at 14:48
answered Sep 26 at 13:18
samis
3,37562051
3,37562051
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
3
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 at 11:36
try this , small and perfect code stackoverflow.com/a/52695444/4997704
– Binesh Kumar
Oct 8 at 4:38