how can I get the path for the folder where my app can save large JPG files?. getExternalStorageDirectory() works fine only when SD Card is present, but what happens when SD is removed or the harware don't have SD Card slot.
thanks
You can use the getFilesDir() method of a Context. From a context you can also use methods to get the cache directory, external cache directory, and the external files directory. An Activity is also a context, so you can use these methods from inside one.
The getFilesDir() method gives you the folder where your files will be accessible only from your application and will be always available. However, you should use the cache directory instead, when possible. This way you will avoid making the system run out of space.
EDIT:
My answer: Almost always a device will either have an SD card or built-in external storage. When it's built-in, it's still called external storage. To check whether the external storage is removable (SD card) or built-in you can use isExternalStorageRemovable() in Environment.
Basically, you shouldn't place large files on the internal memory. There is no public folder in the internal memory. If a device doesn't have external storage, it's simply not capable of doing certain things. Simple as that. So one option you have when there is no external storage is to inform the user about it and ask them to insert a card. You don't have to handle this case, let the user handle it.
The answer you asked for: Try using getDir(String name, int mode) and/or openFileOutput(String name, int mode) of a Context object, and for mode use MODE_WORLD_READABLE or MODE_WORLD_WRITEABLE. Also check Using the Internal Storage.
You are facing intended limitations of the platform that are there for the good of everyone.
You could either require external directory to exist, or you can store to the internal directory. If you choose to permit both, I suggest you store a flag in internal space to indicate that you've stored something externally, so that if external storage is not present you can take appropriate action.
As you are Saving Large JPG files, its is better to save it in external storage because Phone has very small internal memory and its all effect the performance of phone.
Related
I have some downloadable content (e.g.:game character image) in a app, in iOS they are saved to path NSCachesDirectory, which I follows the guidelines of iOS that downloadable content should be saved in NSCachesDirectory, which is a cache directory. I am struggling if I should save the files to getCacheDir() in android side.
At first I think the cache folder in iOS should be equivalent (or similar) to the one in android, but after looking at some doc I doubt if they are functionally identical:
1.iOS suggest some downloadable content to save in cache folder, such content is more persist temporary file in tmp. But in android, the doc says getCacheDir() should store cache files rather than persist files, it makes me suspect android cache folder works more like the tmp folder in iOS
2.I cannot find any size limit guideline on iOS cache file, but android side says it should have reasonable size limit, say 1 MB (and I think my content would be far more than 1 MB, say 50 to 100 MB).
So my question is, are iOS cache folder works functionally equivalent to cache folder in android? Is it correct to use getCacheDir() at android side at the place that I use NSCachesDirectory in iOS side? if not,which path should I use at android side when I use NSCachesDirectory at iOS side?
No, iOS cache folder doesn't works functionally equivalent to cache
folder in android.
For more details of all the data-storage options of Android have a look at official docs here.
In Android for storing large amount of data you can go with either Internal or external data-storage options, Also you can make your data private on Internal or external data-storage options if you need so.
Internal storage
Each application has its own private internal storage to save files. This is the kind of storage to use if the user shouldn’t be able to modify the file from outside your application, and if other application shouldn’t be able to access those files. Since the internal storage is private to your application, the files will be deleted if your application is uninstalled. The internal storage is also where your application is installed by default, so your files will always be available. On some older or cheaper devices the internal storage is quite limited, so you need to be careful about the size of the data you save if you need to support those devices.
You should never hardcode the path to the storage directories, since the directory may changes depending on the version of the Android OS used. Also, Android 4.4 introduces the concept of multiple users : in that case, the internal and external storage depend on the user logged in and the files of the other users will be invisible. Here are some of the methods used to get the paths to the internal storage:
android.content.Context.getFilesDir(): returns a java.io.File object representing the root directory of the internal storage for your application from the current context.
android.content.Context.getDir(String name, Context.MODE_PRIVATE): returns a java.io.File object representing the directory name in the internal storage, creating the directory if it does not exists. The second parameter can also be used to set the directory to MODE_WORLD_READABLE or MODE_WORLD_WRITABLE so it is visible by all the other applications, but this is is risky security-wise and was deprecated in API level 17 (Android 4.2).
android.content.Context.getCacheDir(): returns a java.io.File object representing the internal cache directory for the application. This is mean for small files (the documentation suggests no more that 1MB total) that can be deleted at any time when the system needs more storage. There is no guarantee that the cache will be cleared, so you must also clear those files manually when they are not needed anymore.
As you can see, the files are represented by the File object from the java.io namepace: there is no file object specific to the Android SDK and the standard Java APIs for reading and writing files are used. Also, there is no specific application permission to set in the Android manifest to use the internal storage since it is already private to the application.
External storage
In addition of the internal storage, there is an external storage space shared by all the applications that is kept when your application is uninstalled. This is the storage that is shown when using a file explorer application and when the device is plugged in your computer. It may be implemented as a SD card that can be removed or as a partition of the built-in storage in the device, so your application should be able to work even if the card is removed or changed. To check the current state of the external storage, you can call the getExternalStorageState() method.
On device with many users (starting with Android 4.4), the external storage is specific to the current user and files for other users can’t be accessed. Also, there may be more than one external storage if the device has a built-in external storage which is a partition on the internal memory and a SD card: in that case, the built-in storage is the primary external storage. Reading files from the external storage requires the READ_EXTERNAL_STORAGE permission and writing or reading files requires the WRITE_EXTERNAL_STORAGE permission.
Here are the methods you should use to call to get the directories of the primary external storage:
android.os.Environment.getExternalStorageDirectory(): returns a java.io.File object representing the root directory of the primary external storage of the device that is shared by all applications.
android.os.Environment.getExternalStoragePublicDirectory(): returns a java.io.File object representing a public directory for files of a particular type on the primary external storage of the device. For example, you can get the path to the public music directory by calling Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) or the public pictures directory by calling Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).
android.content.Context.getExternalFilesDir(): returns a java.io.File representing the root directory of the primary external storage specific to your application, which is under the directory returned by getExternalStorageDirectory(). Unlike the other directories of the external storage, the files you store in that folder will be deleted when your application is uninstalled. So, if you need to store files that are only needed by your application you should use this folder. Also, there is no specific permission needed for the application to read or write to its own external storage starting with Android 4.4, but with older versions your application needs the READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE permission.
android.content.Context.getExternalFilesDirs(): returns an array of java.io.File representing the root directories of all the external storage directories that can be used by your application with the primary external storage as the first directory in the array. All those directories works the same as the primary storage returned by the getExternalFilesDir() method. If the device has a built-in storage as the primary external storage and a SD card as a secondary external storage, this is the only way to get the path to the SD card. This method was introduced in Android 4.4, before that it was impossible to get the path to the secondary storage.
android.content.Context.getExternalCacheDir(): returns a java.io.File object representing the cache of the application on the primary external storage. This cache is not visible to the user and is deleted when the application is uninstalled. There is no mechanism in the Android SDK to delete files in the cache directory, so you need to manage your cache to keep it to a reasonable maximum size. Starting with Android 4.4, the application does not need permission to access its own cache, but with older versions your application needs the READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE permission.
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.
I currently use Environment.getExternalStorageDirectory() to obtain a location where I can store some data temporarily and then after being used gets deleted. This data can range from 1-100MB.
This works fine but on some cases the state of the external storage is removed or unmounted etc... and I can't access to store my data...
My question is what could be a good fallback solution when this storage is not available?
I'm targeting Android 1.6 and greater.
Note that you should not use the path returned by Environment.getExternalStorageDirectory() directly:
Applications should not directly use this top-level directory, in
order to avoid polluting the user's root namespace. Any files that are
private to the application should be placed in a directory returned by
Context.getExternalFilesDir, which the system will take care of
deleting if the application is uninstalled. Other shared files should
be placed in one of the directories returned by
getExternalStoragePublicDirectory(String).
Use the path returned by getFilesDir() to store files private to your app on the internal storage, or getExternalFilesDir() to store on the external storage.
If you're storing data temporarily, consider using the cache directories.
These files will be ones that get deleted first when the device runs
low on storage.
Use the methods: getCacheDir() or getExternalCacheDir() on the external filesystem. Read the documentation for important differences between them.
If the size of the data to be stored is not large, you'd be better off using the internal storage. Otherwise, you'll have to managing the complexity of detecting if external storage is available, falling backing to internal storage if not.
I want to make a folder on the external memory (could be on SD card) private or protected so that only my application/process can have access to that folder.
Can I do this? if so please let me know?
my requirement:
I can use android's internal memory to store my app's files/data, but that may decrease the phone's internal memory (that can cause problems like not having enough space for other apps to install, etc)
Data on external storage cannot be private. It is world-readable and can be changed by the user if they enable USB mass storage.
Quoted from developer.android.com:
Every Android-compatible device supports a shared "external storage" that you can use to save files. This can be a removable storage media (such as an SD card) or an internal (non-removable) storage. Files saved to the external storage are world-readable and can be modified by the user when they enable USB mass storage to transfer files on a computer.
you cannot.You can zip the folder and store in as pass-worded zip file.
Since API 9 you have for this purpose the
File.setWritable(boolean, boolean)
and also for the read/exec operation. take a look to the link
quote from android docs:
public abstract File getExternalFilesDir (String type)
Since: API Level 8 Returns the absolute path to the directory on the
external filesystem (that is somewhere on
Environment.getExternalStorageDirectory()) where the application can
place persistent files it owns.
These files are private to the
applications, and not typically visible to the user as media. This is
like getFilesDir() in that these files will be deleted when the
application is uninstalled[...]
Source: http://developer.android.com/reference/android/content/Context.html#getExternalFilesDir(java.lang.String)
So basically you will get a private (sorta) folder in your SD card.
Use this in combination with Blackbelt's answer for better effects.
In my application , downloading lot of files from server. I want to cache them in sdcard.
for that am using fallowing api..
context.getExternalCacheDir();
But problem is that, not able to save them in internal sdcard(i.e; non removable external storage).They are saving in to "/mnt/sdcard/external_sd/Android/data/".
Please gimme a way to save may files in to non removable android cache.
Regards,
Srinivas
From intellisense for Environment.getExternalStorageDirectory:
"Gets the Android external storage directory. This directory may not currently be accessible if it has been mounted by the user on their computer, has been removed from the device, or some other problem has happened. You can determine its current state with getExternalStorageState().
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.
In devices with multiple "external" storage directories (such as both secure app storage and mountable shared storage), this directory represents the "primary" external storage that the user will interact with.
Applications should not directly use this top-level directory, in order to avoid polluting the user's root namespace. Any files that are private to the application should be placed in a directory returned by Context.getExternalFilesDir, which the system will take care of deleting if the application is uninstalled. Other shared files should be placed in one of the directories returned by getExternalStoragePublicDirectory(String)."