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.
Related
Internal Storage Path
Consider the above picture. It shows the folders and file in internal storage. My problem is i am not able to get the absolute path of the internal storage. I Have tried using
String path = getFilesDir().getAbsolutePath();
but it is giving me the path of my app storage. My objective is to backup a file from the private storage of my app to the top of internal storage. And i am unable to find a solution on web and neither on stack overflow. Suggest a solution to this problem!
Environment.getExternalStorageDirectory();
Return the primary shared/external storage directory.
Note: don't be confused by the word "external" here. This directory can better be thought as media/shared storage. It is a filesystem that can hold a relatively large amount of data and that is shared across all applications (does not enforce permissions). Traditionally this is an SD card, but it may also be implemented as built-in storage in a device that is distinct from the protected internal storage and can be mounted as a filesystem on a computer.
File dir = Environment.getExternalStorageDirectory();
String path = dir.getAbsolutePath();
It is only possible with root access. You should write you backup to external storage to make it world-readable. Android docs says that if you want to share file with other apps or store this file even after app will be deleted you should save it to external storage. Android docs
Try this,
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
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.
I have spent literally hours now looking for (and trying) many different ways to write some files to my 4.4 Android KitKat's removable SD card after getting countless "eacces permission denied" errors. Seems now that Google has limited access to the filesystem on SD cards you are forced to only be able to write to directories owned by the application (eg: /Android/data/com.mycompany.myapp/files/).
Finally I was able to get something working that creates a directory on the removable SD card that can be written to. However I am curious why in order to gain access to this owned directory on the removable SD card I first had to create a new file object using a path to the external directory?
My implementation:
First I create two globals to house the strings of both the external and removable paths.
MainActivity
public class MainActivity extends ActionBarActivity {
String externalStorageDirectory;//path to owned external storage files
String secondaryStorageDirectory ;//path to owned removable storage files
Then I ask the system what the manufacturer specific directories are called and start concatenating absolute paths for both the externalStorage and removableStorage variables. I also create a new File object initialized with the path to the external app owned directory.
onCreate()
externalStorageDirectory = this.getExternalFilesDir(null).toString();//build absolute path to the app owned external directory
File folder = new File(externalStorageDirectory ); //THIS LINE IS CRUCIAL!!
Log.d("DEBUG", " - External Path" + externalStorageDirectory );// "/storage/emulated/0/Android/data/com.mycompany.myapp/files"
String ownedDirectory = "/Android/data/" + this.getPackageName() + "/files/";
secondaryStorageDirectory = System.getenv("SECONDARY_STORAGE").toString() + ownedDirectory;//build absolute path to the app owned removable directory
Log.d("DEBUG", " - Removable Path"+secondaryStorageDirectory );// "/storage/external/Android/data/com.mycompany.myapp/files/"
Finally I was able to write a file to my application's owned removable SD card directory. And more specifically I was using an AsyncTask to download my files and save them, method #1 of this post.
doInBackground()
output = new FileOutputStream(secondaryStorageDirectory + "myawesomefile.mp4");
Then I was able to navigate to the removable SD card directory via adb shell and I could see my file.
Adb shell output:
//internal storage
shell#QTAQZ3:/storage/emulated/0/Android/data/com.mycompany.myapp/files $ ls
s <
//removable SD card
shell#QTAQZ3:/storage/external/Android/data/com.mycompany.myapp/files $ ls
ls
myawesomefile.mp4
<
And just to reiterate a little:
File folder = new File(externalStorageDirectory); //THIS LINE IS CRUCIAL!!
File folder = new File(secondaryStorageDirectory ); //THIS LINE DOES NOTHING?
So my questions are:
When I create that File object instance, what is happening that makes those directories available?
Why is having to call mkdir() or mkdirs() seem to unnecessary in this case as the dirs magically appear when the file object was created?
And why am I able to see my app's secondary(removable) directory only after I set
the file to the external(non-removable) path?
Admittedly I am relatively new to Android programming, so I'm not even sure if this approach is correct or just a lucky hack? But it seems to work in my app for now.
General Problem:
People are complaining about data loss after app update of data that is stored on 'external storage directory'
What I'm doing:
I'm using Environment.getExternalStorageDirectory() to get the external storage directory to store files outside the internal memory to get the chance to be able to store those on the SD card.
I'm running into the problem that after each app update a very low amount of users is complaining that the files stored in the app are not visible any more.
There is a paragraph in the official documentation of this method saying:
This path may change between platform versions, so applications should
only persist relative paths.
in my app I'm getting my directory with the following code:
File root = Environment.getExternalStorageDirectory();
File dir = new File(root.getAbsolutePath() + "/" + DIRECTORY_NAME + "/");
Depending on the Android version this will be a different dir. e.g. /mnt/sdcard/dir_name, /storage/sdcard0/dir_name
In case dir does not exist, I create the directory. This is the same behavior that happens on a new install.
Question:
What happens when the OS is updated. Is there a guarantee that the old location will exist as a symlink to the new location?
How can people complain about data loss after an app update?
I'm using Environment.getExternalStorageDirectory() to get the external storage directory to store files outside the internal memory to get the chance to be able to store those on the SD card.
External storage on Android does not have anything necessarily to do with "the SD card". In particular, on modern devices, Environment.getExternalStorageDirectory() is highly unlikely to be a removable medium.
in my app I'm getting my directory with the following code:
Please consider switching to just about anything else, so you do not clutter up the root of the user's external storage with random directories. Use getExternalFilesDir(), getExternalCacheDir() (both on Context), or Environment.getExternalStoragePublicDir() instead.
Depending on the Android version this will be a different dir. e.g. /mnt/sdcard/dir_name, /storage/sdcard0/dir_name
This will not be a problem, so long as you are not trying to save these absolute paths somewhere (e.g., in a database).
Is there a guarantee that the old location will exist as a symlink to the new location?
No. This is why the documentation recommends that you do not persist absolute paths to locations on external storage.
In my app I want to record a 2-second long sound and play it back to the user. All examples I've found so far require that the audio data for playback either comes from a file or from a URL.
Both MediaPlayer and SoundPool classes accept only files, file descriptors, resource id's or URLs as input and not just, say, a byte array.
Since one can only write files to the SD card and NOT internal storage (is this so?), the app would require that an SD card is mounted and writable. But my app should also work if no SD card is present.
Is there a way to achieve this?
Thanks
Yes, an App can write to internal storage (where it is installed). Every Installed app is provided a Data folder to write its internal files. Also there is a cache storage provided.
These methods of Context can get you these directories:
getCacheDir() : Returns the absolute path to the application specific cache directory on the filesystem (Note: System may delete cache if its low on storage)
getDir(String name, int mode) : Retrieve, creating if needed, a new directory in which the application can place its own custom data files.
Also there is a method for External storage: getExternalCacheDir() but is unreliable since external storage might not be always there.
Also, if you just need to write files in App's internal data directory, there is a very simple method:
openFileOutput (String name, int mode)
You can use
'getApplicationContext().getFilesDir().getAbsolutePath()'
to get the path of the directory where the app is installed.
One limitation is, 'getFilesDir()' gives you the path to the directory on the file system where files created with openFileOutput(String, int) are stored.