According to my application, I'm downloading the pictures and some data and I need to save them somewhere in the phone memory or sd card. Since the pictures can be quite big, I decided to save it into sd card. I'm using the code below to determine whether the sd card is available or not. If it is I'm using SD card if not I'm using phone memory. But the Issue is, If I eject the SD card, my application crashes on start up and I get File Not Found exception. As far as I understand, since the phone has internal SD card,
android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)
is always returning "mounted". How can I understand the external SD card is really ejected ?
EDIT: I tried to check whether the SD card is available or not , since I'm using the code below and since I have internal SD card in my phone
android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)
always returns true and It creates the directory without having and SD card. So checking directory for null is not working to understand whether the file is exist or not. Here is my code below.
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
cacheDir=new File(context.getExternalFilesDir(null), applicationDirectory + folderName);
}
else {
cacheDir = new File(context.getCacheDir(), applicationDirectory + folderName);
}
if(!cacheDir.isDirectory())
cacheDir.mkdirs();
So according to my solution, I try to read the required file and If I get FileNotFoundException I copy all the content from assets folder to the directory(SD card or phone memory) when application starts up and I control it with a boolean value in shared preferences. In that way if the user ejects the SD card, the content will be copied to phone memory and will be working from that directory.
I need around 10MB of cache space to save some of my files, and with this solution (I'm not sure if it's that effective) I will have my content both in SD card and phone memory if the user runs the application when there is no SD card. Any other solution to find out where to keep files, external or internal memory ? Thanks for the answers. Any Idea will be appreciated.
You could using these methods to check if your Folder on the external sd exists:
if(myFolder != null && myFolder.exists()) { /* work here */ }
myFolder would be a file targeting at the external sd (you should check the vendor mappings in the internal memory because they differ vor each vendor).
Sadly two sds is not the real Android way and this results in Android thinking the internal sd is the external one.
There is a discussion and a code example for finding the external sd here.
Check this thread:
How android application detects two SD CARDS in a device
Maybe you could then check if the folders for the sdcards exist and handle the cases where the card does not exist differently?
So something like:
sdcardloc = /mnt/sdcard/sdcard1;
if(sdcardloc != null && myFolder.exists()) { /*case where card is mounted*/ }
else { /*handle case where no card is mounted*/}
External SD card, the concept is specific for device vendor. In android only External Storage concept. And also Environment.getExternalStorageDirectory() refers to whatever the device manufacturer considered to be "external storage".
Related
I want to give the user the option to save images on their sd card and I want to be able to calculate the sizes of folders of such images. I find that Environment.getExternalStorageDirectory() returns internal storage. The only way I can find the sd card is by using an ACTION_OPEN_DOCUMENT_TREE request. But this means I have to use DocumentFiles rather than regular Files. I can only get a content uri, not a direct path to the sd card itself.
So, File.length() works well with internal storage but DocumentFile.length() is extremely slow with external storage. Is there any way to get the size of a folder based on its content uri without it taking forever? Or can I somehow find an actual path to the sd card and use Files instead? I found a folder like /storage/3857-3732 but I don't seem to have permission to write to it (yes I have WRITE_EXTERNAL_STORAGE permission).
Android check for SD Card mounted always returns true
My question has been asked earlier also & as there were no satisfactory answers, I am stuck. My requirement is very simple. I am working on an app where I need to ask the user to select a storage to save in app downloads. I need a method that confirms that external SDcard is present. Have already tried following methods:
This is always returning true probably owing to this reason: https://stackoverflow.com/a/7790228/3475715
final Boolean isSDPresent = Environment.getExternalStorageState().
equals(android.os.Environment.MEDIA_MOUNTED);
Following is also not working coz maybe the hard coded path is different for different mobiles
File file = new File("/mnt/extSdCard");
try {
File list[] = file.listFiles();
Toast.makeText(getApplicationContext(),
"Yes sdcard is mounted,file count " + list.length,
Toast.LENGTH_LONG).show();
} catch (NullPointerException o) {
Toast.makeText(getApplicationContext(),
"Sorry no sdcard is mounted:", Toast.LENGTH_LONG).show();
}
Any suggestions are appreciated!
You should use getExternalFilesDirs method. This method returns path(s) to both internal memory & Micro SD card (if present). The second returned path would be path of Micro SD card. But that path may not be root directory of Micro SD card.
getExternalFilesDirs introduced in API level 19 is the only official method that can be used to get SD card path. All others methods will return either public or private storage locations(paths) of internal memory.
I have tested this method on my phone & emulator. Kindly, note that I have passed null as parameter for getExternalFilesDirs during testing. But You could also pass parameter(s) like Environment.DIRECTORY_PICTURES, Environment.DIRECTORY_MOVIES etc.
TEST RESULTS:-
When my phone has memory card inserted, getExternalFilesDirs returned :
1st path (internal memory): /storage/emulated/0/Android/data/my_package.appname/files
2nd path (Micro SD): /storage/sdcard1/Android/data/my_package.appname/files
Note: root directory of my SD card is: /storage/sdcard1
On my emulator, getExternalFilesDirs returned :
1st path (internal memory): /storage/emulated/0/Android/data/my_package.appname/files
2nd path (Micro SD): /storage/11E9-4214/Android/data/my_package.appname/files
Note: On emulator, SD card is emulated(not real one).
If Micro SD card is ejected (either on phone or emulator) getExternalFilesDirs returns null
1st path (internal memory): path to internal memory - It varies depending on device
2nd path (Micro SD): null
BUT ;
On some devices, you may not get the Micro SD card path. It means getExternalFilesDirs will return only one path(internal memory). Second path would be empty i.e. it will not return any second path.
Reason: OEM of that particular device may not have set the path (i.e. SECONDARY_STORAGE environment variable) in the device.
This answer for this question says,
the OEM must have set the SECONDARY_STORAGE environment variable in
the device specific init.rc file as mentioned here:
https://source.android.com/devices/storage/config-example.html
Also the comment made by somesh on the above mentioned answer says,
If that environment variable is not set, you can't write to the sdcard
by making use of getExternalFilesDirs since its not going to return
the sdcard path.
In those kind of cases, assume that memory card is not present and save whatever you want to save in internal memory.
To Summarize, If getExternalFilesDirs doesn't return second path or returned second path is null, don't store in SD card (store in internal storage); else store in second path returned by getExternalFilesDirs
Suggestion:
To understand about different storage locations in Android, please go through my answer on stackoverflow
Android does not expose any API that allows you to get the path of the sdcard root path. You can use reflection and obtain the sdcard root path from StorageManager.java -> getVolumePaths() - http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/os/storage/StorageManager.java#590
You cannot arbitrarily save to any location on the SD Card. You can either use one of the paths returned from getExternalFilesDirs or use SAF(Storage Access Framework) to explicitly request for user permission to write to SD Card. How to use the new SD card access API presented for Android 5.0 (Lollipop)?
The moment store files in SDCard, it's taking a long time but if I store files in internal storage its taking less time.
My code:
public File getTileViewImageDirectory() {
// check SDCard if available or not, if available store in SDCard
// else store in internal storage
if(android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED) && !android.os.Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
File[] dirs = ContextCompat.getExternalFilesDirs(context, null);
File directory = new File(dirs[dirs.length > 1 ? 1 : 0].getParentFile().getAbsolutePath() + AppConstants.TILEVIEW_IMAGE_LOCATION);
return directory;
} else {
return new File(context.getFilesDir().getAbsolutePath() + AppConstants.TILEVIEW_IMAGE_LOCATION);
}
}
Note: If SDCard not available than default it will store in internal storage.
When using the internal storage it be fast (under 30 sec), but in external storage it is taking longer time (over 1 min).
How can I decrease the time when using external storage?
To save directly to the SD card will be always slower. The only way to improve the speed is to use/buy a high speed SD card.
Also looking at your code I should warn you that starting in Android 4.4 and above the SD card is no longer accessible with the common File API. You will need to use instead the new Storage Access Frameork.
Also take into account that in Android Q and above, SAF has been enforced to be the only way to access the SD card, so there are no workarounds or hacks for such versions.
I got the both the external and internal(phone memory ) SD card in listing in my application
but along with that i got some more folder and i don't want them so how can i limit to external and internal SD card only in listing...
i provided the root directory which is /storage and it displays whole the folder...
or can some one tell me how to get external sd card programmaticaly
i have tried the usual way File file = Environment.getExternalStorageDirectory();
given by android but it returned only internal path .
Environment.getExternalStorageDirectory() it returns sd card path but depends on the device
for better under standing check Find an external SD card location
I am working on email application. My application will create some files in the Sd card.
I am using
Environment.getExternalStorageDirectory()
to store the files in SD card. But I have observed that some times when my device connected to my computer I am unable to access my files.
Please suggest what's the path I need to use so that my files must always accessible.
I want to store my files only in Sd card.
I think when the SD card is mounted you cannot access it.