It'd be convenient if an application I'm writing stored some files to external storage permanently (so they persist after the application has been exited[destroyed]), but on an uninstall I'd like to do the decent thing and have these files removed to free up the storage.
Is there any way I can have these files removed on an uninstall?
If there isn't (and I'm skeptical), then I'll have to create these files each time. I'm trying to save start-up time and also occupy required space by having them exist permanently.
Note: I need to use external storage, so both internal storage or a DB would be inappropriate.
actually it is possible .
android will automatically remove files of the app in the external storage , but the files must be inside a specific path of the app :
"...../Android/data/APP_PACKAGE_NAME/"
where APP_PACKAGE_NAME is the application's package name.
another path that is automatically being emptied is :
"...../Android/obb/APP_PACKAGE_NAME/"
where APP_PACKAGE_NAME is the application's package name.
the data is for anything you wish.
the obb folder is for huge files that are downloaded using the play-store and the apk extension library . you are not supposed to create files there .
No, I don't believe so. Only files that you write to internal storage will be removed when your application is uninstalled (or if the user presses the 'clear data' button in the Application settings app).
Your app can't receive its own PACKAGE_REMOVED broadcast intent either, so you essentially have no notification that you're being uninstalled.
Yes, this is possible. Simply write your files to the external files directory:
File dir = getExternalFilesDir(null);
This will create a folder at /Android/data/your.package/. Note that this is not External as in sdcard, but it is publicly accessible. If a user uninstalls your app, this directory will also be removed, along with all of its contents.
Quoting from the blog post of CommonsWare
Internal storage: your file is deleted
External storage: if you wrote your file to a location rooted at getExternalFilesDir() or getExternalCacheDir(), your file is deleted. If you wrote your file elsewhere (e.g., Environment.getExternalStoragePublicDirectory()), your file is not deleted
Removable storage, prior to Android 4.4: removable storage is not officially accessible; if your file winds up out there, it should not be deleted when your app is uninstalled
Removable storage, Android 4.4+: AFAIK, if you write to a supported location (getExternalFilesDirs() or getExternalCacheDirs()), your file is deleted if that particular bit of removable storage is in the device at the time of uninstall
Related
On my Samsung devices I put a file in the /Download folder. When I select the file within my app (via a file browser), the file is called /storage/emulated/0/Download/myfile.db. This name is stored in my app settings.
At the start of the app the file should be opened. First the app checks if the file exists. In some cases, say once every 2 weeks, the file is said to be not existing! This happens also at my friends mobile since half a year.
Why is that happening? For years everything ran smoothly.
This code runs for 6 years. Of course I added the permissions stuff.
Your help is much appreciated!
You can't use the Download as an guaranteed storage place for your files. You should use the Internal storage for the app. This is what Google has written about the download folder:
This space is called external because it's not guaranteed to be accessible—it is a storage space that users can mount to a computer as an external storage device, and it might even be physically removable.
Here you can read more about the Internal storage and the External storage in Android.
Here is some more information about the Download folder from Google.
Caution: The external storage might become unavailable if the user removes the SD card or connects the device to a computer. And the files are still visible to the user and other apps that have the READ_EXTERNAL_STORAGE permission. So if your app's functionality depends on these files or you need to completely restrict access, you should instead write your files to the internal storage.
A rare but reoccurring problem reported with one of my apps is that "all my files were deleted" (files referring to project files generated from said app, save files essentially).
The culprit ends up being those "optimizer" apps that clean "unwanted" files from your Android device. Because my app generates custom-file-extension files, maybe they're not recognized and deleted?
Regardless, I know of the .nomedia file, a file used to tell media players to ignore a directory when scanning for media. Is there a similar file to "protect" directories from automated modification/deletion? Maybe even something placed in the Android Manifest?
Save the files in the internal storage that your app is assigned to by the system. No other apps can access it as it is private to your app. If you save files in a public directory, any app can access that.
File dir = context.getFilesDir()
To get your app's storage 'partition'
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.
As the question states:
My application has created some files in
Environment.getExternalStorageDirectory()
I have to delete all the files of my application in that
Environment.getExternalStorageDirectory() location
How to do this
Note: It must not delete other files created by other application
Use the delete() method on the File object for each file to be deleted.
You will need to determine for yourself what files are to be deleted. Nobody else will know, including Android. There is no app-specific ownership information on files on external storage, even if such data would necessarily be reliable for your use case.
Also, bear in mind that each account on Android gets its own part of external storage, and you can only delete files that are in the external storage for whatever account it is that is presently running. Other accounts (on Android 4.2+ tablets and Android 5.0+ phones) are not accessible to you.
I want to track everything that apps store in phone memory/on sd card, so I can delete it if the app is uninstalled. Is this possible? If not, how can I get all the files from phone memory/sd card?
there is no way to "track" what your application creates, i think..
generally, the app stores data in the Cache directory, which is :
"<storage directory>/data/<your package name>/"
on a device which supports external storage, the "storage directory" is generally "/mnt/sdcard"
you can read the documentation to learn how to use the External storage to save files you create through your application.
I'd also like to point out that there is no way for you to know when your app is being uninstalled, so you can't delete the files before uninstall manually anyway,if that's what you intend to do. The android system itself removes the files stored in your cache directory, though.