I want to allow the user the ability to download a file to the shared android "Download" directory (preferably) on either the internal storage or the SD card (if it exists). I can download a file to the internal storage but can't seem to get it to work on the SD card and everything I've looked at on here is either deprecated, incomplete, or doesn't work.
Here's my download code:
if(downloadToSdCard) {
File path = new File(browser.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), filename);
Uri downloadsUri = FileProvider.getUriForFile(browser, "my.app.fileprovider", path);
request.setDestinationUri(downloadsUri);
} else {
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
}
downloadManager.enqueue(request);
Related bits in my manifest:
<application
android:requestLegacyExternalStorage="true"
...>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="my.app.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>
And filepaths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Used when sharing images from the internet to create a temp image to download to -->
<cache-path name="shared_images" path="images/"/>
<cache-path name="text_to_speech_gen" path="text_to_speech_gen/"/>
<!-- Used when downloading files to allow external apps to open downloaded files -->
<external-path name="attachment_file" path="."/>
</paths>
I'm really struggling to get my head around how the android file system works so explanations with the answer would be appreciated. I've tried reading the official documentation but I just end up falling down endless rabbit holes of confusion. Thanks!
Related
I have a strange problem. I am developing an android app with Kotlin.
My codes can generate and save the image myImg.png to the following directory
directory: "/storage/emulated/0/Android/data/com.example.MyApp1/files/AutoDDD"
and also it can read the same image from the same directory and show on imageView
Also, the satement;
file.exists()
returns true. However, the problem is that I can not see the image file when I open the folder AutoDDD on my laptop. I removed the application and re-installed, but the problem still occurs. I closed the editor and re-opened, re-run the app, but the problem still occurs.
What is the reason?
This was my problem too, the folder and the file exist but i cannot see it. So
put this in Mainfesx.xml
...
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.mydomain.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/paths" />
</provider>
...
then create xml folder inside (app > src > main > res) , on xml folder add paths.xml finally in paths.xml add this code
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="my_images" path="images/"/>//specify your image path here
</paths>
on Your activity
val imagePath = File(Context.getFilesDir(), "images")//put your path here
val newFile = File(imagePath, "ur_image.png")//put your image here
val contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile)
Warning: make sure you allow storage permission in setting > app > " ur app" > permission > storage & allow it
, in Mainfest add
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
seen this documentation https://developer.android.com/reference/androidx/core/content/FileProvider
it may help you
Thanks!
How can I use
new SharePhoto.Builder()
.setImageUrl(Uri uri)
.build();
to share a file from internal storage to facebook stories? The documentation mentions adding
<provider android:authorities="com.facebook.app.FacebookContentProvider{APP_ID}"
android:name="com.facebook.FacebookContentProvider"
android:exported="true"/>
to the AndroidManifest.xml, but it's not enough.
There is a method FacebookContentProvider.getAttachmentUrl() which gives a path that I tried to use to save my file there, but it doesn't work.
The error that I am getting from the Facebook SDK callback manager is the following.
Failed to copy sticker
There are some probable reasons for not getting the file properly.
The first one is, the Facebook SDK requires to have the file stored in your local storage with a valid Uri to the file. Hence, if the file is not actually stored in your local storage, that might be a problem.
And the other thing is setting up your application correctly so that it can access the files from the internal storage. I would like to recommend checking following things that might be missing in your application.
Check if you have the FileProvider in your AndroidManifest.xml like the following.
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true"
tools:replace="android:authorities">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_provider_paths"
tools:replace="android:resource" />
</provider>
And you should have a file_provider_paths.xml file in your /res/xml folder which should contain the locations of your files like the following.
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="documents"
path="Android/data/bd.com.ipay.android/files/Pictures" />
</paths>
Hope that helps!
I need to create a directory to store user video files in Internal Storage.
In some part of the code I have this:
var path = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos);
System.IO.Directory.CreateDirectory(path);
When I debug, path variable is actually: "/data/data/com.companyname.MyApp/files/Videos"
When I browse device files, the closest target folder is this: "This PC\MyDevice\Internal storage\Android\data"
When I browse that folder, no new folder was created. I was expecting to have com.companyname.MyApp/files/Videos folder structure, but it was not created, even when no exception was thrown.
How can I do it?
Thanks
Jaime
You need to add File provider in the manifest
Define file_paths.xml
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="my_images" path="images/"/>
<files-path name="my_docs" path="docs/"/>
</paths>
and add it into manifest
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
Finally, I had a misconception about Internal and External storage.
What I was seeing in Windows Explorer is in fact, external storage, so I used:
Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryMovies)
That points to the "Movies" directory where I could save the MP4 file in order to view in the Android device.
Regards
Jaime
I have an Image File stored in sd card with an Absolute path as - storage/4469-0C17/DCIM/... and another image stored in internal storage with an absolute path - /storage/emulated/0/
I am using FileProvider to share it with external apps.
Now, I am able to share images stored in internal-storage but for the image stored in external storage, it throws an error as -
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/4469-0C17/DCIM/....
My Manifest -
<manifest>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_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>
</manifest>
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>
Code -
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
File imageFileToShare = new File(filePath);
Uri imageURI = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", imageFileToShare);
share.putExtra(Intent.EXTRA_STREAM, imageURI);
share.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(Intent.createChooser(share, "Share Image"));
and another image stored in internal storage with an absolute path
That is what the Android SDK refers to as external storage.
but for the image stored in external storage, it throws an error as -
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/4469-0C17/DCIM/....
First, that is removable storage, not external storage.
Second, FileProvider does not support removable storage.
Instead of using FileProvider which as you have seen yourself is very limited you better derive your own provider from ContentProvider.
Then you can serve any file you want.
CommonsWare has a nice example how to set up such a file provider.
Add to your provider_paths.xml this:
<root-path path="." name="external_files" />
I have some files in custom folder in the internal storage. I need to open the files using external application like Adobe. I planned to open using FileProvider. But the third party application is stopped when trying to open the the document. I really don't know what mistake I did in the code.
package name = "com.example.doc"
activities are in package = "com.example.doc.activities"
manifest
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.doc.fileprovider"
android:exported="false"
android:grantUriPermissions="true"
android:readPermission="com.example.doc.fileprovider.READ">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepath" />
</provider>
res/xml/filepath.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="files" path="." />
</paths>
activity
//tempfilePath = /data/data/com.example.doc/files/RBC/sample.docx
File file = new File(tempfilePath);
Uri exportUri = FileProvider.getUriForFile (this, "com.example.doc.fileprovider", file);
Intent docViewIntent = new Intent();
docViewIntent.setAction(Intent.ACTION_VIEW);
docViewIntent.setDataAndType(exportUri , extensionType);
docViewIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
docViewIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(docViewIntent);
Do we need to specify any permission in manifest?
Any help would be appreciated..
Thanks
Jomia