A sure shot method to find if SDCard is present - android

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

Related

How to get path of directory which is in SD Card?

I want to create directory in SD card same as in the internal storage.
My internal storage path is "sdcard/<my_directory_name>/"
I want to create the same directory in root of SD card.
I have try the following ways to find the path of directory.
sdcard1/<my_directory_name>/
Environment.getExternalStorageDirectory() +"/<my_directory_name>/"
Please suggest the way to find SD card path.
You do not have arbitrary access to removable storage on Android 4.4+. Hence, there is no useful path, from a filesystem standpoint. You are welcome to use getExternalFilesDirs() and kin -- if they return 2+ locations, the second and subsequent ones are on removable storage, and you can read and write to those locations.
Although as CommonsWare answered, you cannot read or write in Secondary External Storage, here's a way to generate it's path.
System.getenv("SECONDARY_STORAGE"); //returns /storage/extSdCard
You can also use String path = "/storage/extSdCard"; but again you cannot write files there.
Edit: As #CommonsWare commented, there is no guarantee of this method. Though when I tested it, it worked, but again, if he says there's no guarantee, you can take his word.

SD Card Location on Android

I'm using Bluestacks for testing my app, because I don't have Androids lying around. I'm tring to write a file to the SDCard but can't seem to figure out the path for it. I've tried the following: /mnt/sdcard/ext_sd & /mnt/extSdCard but neither of those worked.
I've tried the following: /mnt/sdcard/ext_sd & /mnt/extSdCard but
neither of those worked.
You should not hardcode paths. Because SD card storage location or path varies from phone to phone. SD card storage location in my phone is /storage/sdcard1
Now coming to your question,
Before API level 19, there was no official API method to store in SD card. But, many could do it using unofficial libraries or APIs.
Officially, one method (getExternalFilesDirs) was introduced in Context class in API level 19 (Android version 4.4 - Kitkat).
File[] getExternalFilesDirs (String type)
It returns absolute paths to application-specific directories on all
shared/external storage devices where the application can place
persistent files it owns. These files are internal to the application,
and not typically visible to the user as media.
That means, it will return paths to both types Storage - Internal memory and Micro SD card. Generally, second returned path would be storage path of micro SD card(but not always). So you need to check it out by executing the code with this method.
Instead of hardcoding paths, you should use this method in your app source code to get the SD card location. Then, write files to that location.
If you want to know more about storage location or paths in Android, please go through my other answer

Android ExternalStorageDirectory States

I have an Android application which needs some data from the SD and I check on entry that the files are there with File.exists() method and checking the SD card isnt either UNMOUNTED or SHARED. This works fine on my device, but have gotten feedback that on other device its showing the Toast that indicates that no data is present.
My questions are:
1 - Is there a way this checks can indicate that the SD is not mounted or shared even after it has been unplugged from the PC?.
2 - Is it possible that getExternalStorageDirectory() resolves to internal storage? I know how this sounds, but people have told me that the app works on some devices when copying the data to internal storage instead of external one, even though i keep telling them that shouldn't happen.
On many devices getExternalStorageDirectory() does not give you the SdCard but resolves to internal storage often called /sdcard or /storage/sdcard0. It does not matter if you
put a microSD in the device. Those paths stay the same and are valid.
If you put in a microSD than that can be mounted under many names e.g:
, "/mnt/sd-ext
, "/mnt/sdcard-ext
, "/mnt/external_sd
, "/mnt/extsd
, "/mnt/extSdCard
, "/mnt/sdcard2
There is no function to determine the sdcard.
You have to give your users the opportunity to select the storage directory.

Directory to save files in android?

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

storing android application data on SD Card

Is there a way to store android application data on the SD card instead of in the internal memory?
I know how to transfer the application sqlite database from the internal memory to the SDCard, but what if the internal memory gets full in the first place? How does everyone handle this?
It's better practice to use Environment.getExternalStorageDirectory() than to hard code "/sdcard"
It's not always certain that the folder name will be called that. Also, the Environment class offers a getExternalStorageState() method to check on if the external storage is even available.
To begin:
Depending on the model/os, you can access the sd card root directory with:
File externalStorage = Environment.getExternalStorageDirectory();
This will refer to the internal sd storage or internal sd memory.
externalStorage.getAbsolutePath()
will return one of the following values
"/sdcard/" or "/mnt/sdcard/"
To access the external sd memory or micro SD, that you usually plug from the outside of the phone/tablet, you must use one of the following folders that android creates to point to the external memory:
"/mnt/sdcard/sd"
"/mnt/sdcard/external_sd"
"/sdcard/external_sd"
"/sdcard/sd"
"/mnt/sdcard/"
ps: you can notice an empty folder external_sd or sd on the internal sdcard
memory, this folder is empty and its used to point to external micro sd card.
at the end make sure that you have read/write access to the sd card android.permission.WRITE_EXTERNAL_STORAGE in the android manifest xml.
finally you must specify the file name and your ready
private SQLiteDatabase DB = null;
private static final String DATABASE_NAME = "MyDb.db";
////////////
File sdcard = Environment.getExternalStorageDirectory();
String dbfile = sdcard.getAbsolutePath() + File.separator+ "external_sd" + File.separator + DATABASE_NAME;
DB = SQLiteDatabase.openDatabase(dbfile, null,SQLiteDatabase.NO_LOCALIZED_COLLATORS);
///////////
and your ready to go ...
Here is another neat little trick.
The Application has a number of methods which are called to acquire paths.
In particular the application has the method getDatabasePath with is used by SQLiteOpenHelper to construct the path.
A custom application class can override these methods to provide different paths including paths in the getExternalStorageDirectory.
The external storage is either application specific or public.
There are methods, replacing the getExternalStorageDirectory mechanism,
getExternalFilesDir() and getExternalStoragePublicDirectory() respectively.
Warning: This answer is out-dated. You should use Environment.getExternalStorageDirectory() to get the root path of the SD card as mentioned in the answers below.
Old Answer so the comments on this make sense:
Adding /sdcard/ to the root your path should direct your Android application to use the SD card (at least it works that way with the G1). Android's file system objects give you the ability to check file sizes... so it should be possible (if tricky) to write some fail-over code. This code would adjust your root path if the internal memory filled up.
some device use /mnt/sdcard as root point to SD Card.
The problem with using the SDCard is that you cannot reliably assume that it will be present always when your application needs it. This is not the case with internal memory. As long as your application does not rely on this data to run it should be fine.

Categories

Resources