I'm using react-native-document-picker in order to pick files and send them to the server. After picking the file, I use RNFetchBlob.fs.stat(uri) from rn-fetch-blob package to get the real path from the URI that the picker gives me. It works fine with internal storage files but when I choose an image from "SD card" section the stat function throws an exception which says something like this:
failed to stat path null for it doesn't exist or it's not a folder
Surprisingly, when I choose "Images" section and go to the SD card folder and choose the very same image it works just fine!!
I have the same problem with "Downloads" section, too.
The URI that the picker returns is this when I choose the image from "Images" section:
content://com.android.providers.media.documents/document/image%3A76431
and when I choose from "SD card" section:
content://com.android.externalstorage.documents/document/F673-1818%3Abbb.png
Right now I'm using this code but it's not the right solution because it's somehow dirty and it doesn't work on all devices.
if(uri.substr(0,57) === "content://com.android.externalstorage.documents/document/"){
let filePath = decodeURIComponent(uri.substr(57));
let subUri = filePath.replace(/:\s*/g, "/");
filePath = "/storage/" + subUri;
return `file://${filePath}`
}
Is there a nicer way to get the real path of a file in SD card from it's URI?
I appreciate any idea.
OS: Android
Related
I have a big problem. I want to save some files that I download from internet with my application, into my SD card fallowing this path:
/storage/9016-4EF8/Android/data/com.my.application/files
But I don't want to hardcode this string inside my code. So how can I do it programmatically?
I have already ask permission to write on external storage.
Currently inside my code there is this piece of code below:
File sdcard = new File(context.getExternalFilesDir(null).getAbsolutePath() + "/Video scaricati/");
But with it, my application saves the files inside:
/storage/emulated/0/Android/data/com.my.application/files/Video scaricati
that it isn't in my SD card.
How can I do it?
Take the second item returned by
File dirs[] =getExternalFilesDirs();
Check if the array contains more then one element before use. Not everybody puts a micro SD card in.
Try changing to Environment.getExternalStorageDirectory() like this
new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Video scaricati/");
I am working on a chat application where I am sending/receiving Images/ Media. I am writing those files in a directory both sent and received.
Now the problem is if I send an image from gallery in chat I am copying it into Sdcardpath + AppName/Images/Sent/.
I this case the images in sent folder are duplicate.
And gallery app is Showing Sent folder with images. I need a way so that gallery cannot read the SentFolder. Below is my code for creating directory.
public static File getImageSentDirectory() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
File dir = new File(Environment.getExternalStorageDirectory() + DOCUMENT_FILE_SENT_PATH);
if (!dir.exists())
dir.mkdirs();
return dir;
} else {
File dir = new File(getAppContext().getFilesDir() + DOCUMENT_FILE_SENT_PATH);
if (!dir.exists())
dir.mkdirs();
return dir;
}
}
I also tried .
dir.setWritable(true,true);
dir.setReadable(true,true);
But on restart device gallery app is showing the sent folder with images .
Add a .nomedia file in your "Sent" directory.
This will make the "Gallery" app skip your folder and thus it won't be listed.
The .nomedia file is like this inside WhatsApp media directory. It is a zero byte file.
I need a way so that galery can not read the SentFolder.
Do not put SentFolder on external storage. Put it on internal storage.
The .nomedia suggestion may help, but it is a convention, not a rule. Any app that has read access to external storage can get to any files you put on external storage. If you do not want that, do not put the files on external storage.
Since android 6.0, the sdcard path is no longer "/storage/sdcard1/", "/storage/sdcard-ext/" or something.
The path depends on the phone instead. If I use Nexus 5x AVD, the path is "/storage/1D15-3A1B/". When I use Nexus 6p AVD, the path is "/storage/4679-1802/". So how can I dynamically write the sdcard path in program to locate the file in external sdcard?
Thank you!
Have a look at getExternalFilesDirs().
It seems that I found the solution.
I'm using the access storage framework. I get it by handling the string of uri and get the "1D15-3A1B" part and then combine it to the sdcard path. Here is the solution.
When I click the file Welcome to Word.docx in the sdcard root path, I get the intent by onActivityResult().
Get the DocumentId by String docId = DocumentsContract.getDocumentId(intent.getData()), thus the string docId is "1D15-3A1B:Welcome to Word.docx".
Split the string and get a string array by String[] split = docId.split(":"), so we can get "1D15-3A1B" which is split[0], and the path in sdcard "Welcome to Word.docx" is split[1].
If we want to get the uri of the file we clicked before, just need to build a new string String newPath = "/storage/" + split[0] + "/" + split[1].
update:
Actually getExternalFilesDirs() is much easier to do this...Thank you #greenapps!
I was trying many approaches, including:
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
Environment.getExternalStorageDirectory()
Still my picture files in DCIM/Camera were not visible to my app. I could see the directory names, but listFiles() on any of these directories returned null.
Finally, and sheepishly, I found that my Manifest did not contain the magic line android.permission.WRITE_EXTERNAL_STORAGE.
Once I added the permission, it worked like a charm.
Moral of the story: Android does not warn/break/throw exception under this condition. When it fails, it fails silently!
I hope to export my data as a text file and save it to disk in Android, so I need to choose which folder I will save the file to.
I hope that a normal user can find the folder easily and the app does not need special permission to create the folder.
I have read some document, it seems that there are 3 ways: Context.getFilesDir().getAbsolutePath(), Environment.getExternalStorageDirectory().getAbsolutePath() and Context.getExternalFilesDir(null).
You know some android users don't install SD card, so it seems that Environment.getExternalStorageDirectory().getAbsolutePath() and Context.getExternalFilesDir(null) are be excluded.
Am I only to choose Context.getFilesDir().getAbsolutePath()? or is there a better way? Thanks!
BTW, From the document Android - Where to save text files to?
Save it in internal phone storage, here no users and applications can access these files(unless if phone is rooted). But these files will be deleted one's the user selectes clear data from Settings -> Apps -> .
It seems that normal users can't access the saved text files if I use Context.getFilesDir().getAbsolutePath(), is it right?
Use this if you want a path that the user can modify and can have access
getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();
More documentation here.
EDIT:
This is how use in case error in some devices:
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
String fname = "TEXT.txt";
File file = new File(path, fname);
if (!path.exists()) {
//noinspection ResultOfMethodCallIgnored
path.mkdir();
}
// YOUR CODE FOR COPY OR CREATE THE FILE TXT in PATH WITH THE VARIABLE file ABOVE
I am trying to read an image file from /mnt/sdcard/image.jpg into my ImageView. Here is my code:
Bitmap bmp = BitmapFactory.decodeFile("/mnt/sdcard/image.jpg");
webImage.setImageBitmap(bmp);
I have write external storage permission.
My code says bmp is null, even though the image resides in the root directory (I go to I Drive and image.jpg is there.)
What am I doing incorrectly?
There could be two cases:
1) If you image is in the root folder of sdcard then it is possible to to access it through
Environment.getExternalStorageDirectory().toString + File.separator + "yourimage.jpg"
2) But i guess in your case it is in the /mnt/sdcard/external_sd which your memory card of the device in that case try this:
Environment.getExternalStorageDirectory().toString + File.separator + "external_sd" + File.separator + "yourimage.jpg"
Replace the above two paths with yours in BitmapFactory.decodeFile("Replace Here...")
I suspect the card with the image isn't mounted under /mnt/sdcard/.
Since you are using a Motorola device, chances are that you have two mass storage devices (see this list, if your device is in there, this is the case). In this situation you have to use the Motorola "External" Storage API to get the path to your second mass storage.
Also in general: You can't rely on hardcoding paths to the SD-Card like this. The mountpoint differs across devices. Or might be named differently, some devices might have a flash storage instead of a card, and so on. In short: What works on your phone breaks on others. You can read a reliable path to the primary external storage by calling Environment.getExternalStorageDirectory() instead.
Thanks, I managed to resolve it. Here is what I found:
I went to project > clean
I disconnected the phone from the computer. When it is connected, the SD is mounted and you can't view data.
The image name can't start with numbers. I am using SDK 7.
I viewed LogCat and I didn't get any errors, however, saving to other system areas (like /Android/Data/) caused a FileNotFoundException - permissions error.
File destination = new File(Environment.getExternalStorageDirectory(), "image" +
DateHelper.getTodaysDate() + "_" + DateHelper.getCurrentTime() + ".jpg");
private View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Add extra to save full-image somewhere
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(destination));
startActivityForResult(intent, REQUEST_IMAGE);
}
};
Please check you LogCat for more information.
My guess is you have a Samsung device. Samsung tends to have an external_sd folder, so you might have added it to the wrong sdcard because Samsung often has an internal and an external one.
Your code is perfectly okay. Just check whether you are writing proper sd card path or not. May be for that reason you are getting null bitmap.
And "write external storage permission" is for writing to your sd card not for reading from sd card. Make this concept clear.