Android ExternalStorageDirectory States - android

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.

Related

Saving file under /Download gives name /storage/emulated/0/Download. Sometimes the file is not accessable

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.

How does storage access change on Android 6?

Background
Android had a lot of changes as to how to handle the SD-card and storage in general:
API 3 - you get all access, no permission needed
API 4-15 - you need to use WRITE_EXTERNAL_STORAGE, and you get all access.
API 16-18 - if you wish only to read, use READ_EXTERNAL_STORAGE
API 19-20 - you can't read or write to secondary external storage (SD-card), unless your app is a system app, or you have root.
API 21-22 - in order to access the SD-card, you need to ask the user for permission, and use the DocumentFile API instead of the File API. This raied a lot of questions, as I've written about here, here and here.
Starting with API 23 (Android 6), things seem to change yet again...
The problem
For API 23, there are at least 2 things that are new and are storage-related :
"Adoptable Storage Devices" - The user can optionally make the SD-card as something that's like the primary external storage.
As part of the new permissions mechanism (requesting permissions at runtime), it seems that storage is also a permission the user needs to confirm. This is for both READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE
Since there is no Android 6 device out there that has SD-card, and because the emulator itself doesn't really have the ability to use an SD-card, it's still impossible to know what's going on.
The questions
Will the SD-card get the access using the File-API instead of DocumentFile?
If I want access to all external storage paths (including SD-card), does this mean I need to request this permissions twice: one for the primary external storage and one for the SD-card?
Are files on the SD-card accessible in any way before the manual granting of the permission?
Suppose the user has chosen to use "Adoptable Storage Devices", what does it mean for the various functions that retrieve the paths of the app's files? For example : getFilesDir, getExternalFilesDir,... ? Would the oder of getExternalFilesDirs change because of it?
What happens to the files of the app when the user moves the app from/to the SD-card (using the "Adoptable Storage Devices") ? What about the app's files on the SD-card? Would they stay? Or would they move somewhere?
For example, if the app has "file1.txt" on the SD-card, on path "/storage/extSdCard/Android/data/appPackageName", and it has a file "file2.txt" (or even the same name) on the primary external storage on path "/storage/emulated/0/Android/data/appPackageName". After switching, what would happen for those files? How would they merge into a single folder, if at all?
When moving the app to the SD-card (using "Adoptable Storage Devices"), does it mean no internal storage will be used?
Let me answer Adoptable Storage Devices related questions:
Suppose the user has chosen to use "Adoptable Storage Devices", what does it mean for the various functions that retrieve the paths of
the app's files? For example : getFilesDir, getExternalFilesDir,... ?
Would the oder of getExternalFilesDirs change because of it?
When user choose to use SD card as "Adoptable Storage Device" (Format as internal), it means now that SD card is available only as Internal Storage i.e. no SD card available to store downloaded files. There will be no order change in paths returned by the related methods. For example: getExternalFilesDir() will list only external storage path if user formatted his SD card as "Adoptable Storage Devices". SD card path will not be available.
What happens to the files of the app when the user moves the app from/to the SD-card (using the "Adoptable Storage Devices") ? What
about the app's files on the SD-card? Would they stay? Or would they
move somewhere? For example, if the app has "file1.txt" on the
SD-card, on path "/storage/extSdCard/Android/data/appPackageName", and
it has a file "file2.txt" (or even the same name) on the primary
external storage on path
"/storage/emulated/0/Android/data/appPackageName". After switching,
what would happen for those files? How would they merge into a single
folder, if at all?
When ever user will choose his SD card as "Adoptable Storage Devices" then user need to format his SD card as internal storage using "Format as internal" option. Format means all the data/files stored on SD card will be erased. Similarly when user want to remove his SD card from "Adoptable Storage Devices" then user again have to format his SD card as portable storage using "Format as portable" option.
When moving the app to the SD-card (using "Adoptable Storage Devices"), does it mean no internal storage will be used?
Yes, original internal storage will not be used. Only SD card storage will be used because after choosing SD card as "Adoptable Storage Devices". All the data/cache will be stored to SD card
To answer your question 5: under Android 7, all files in the "public data" area, /storage/emulated/0/ (or a manufacturer-specific location; it's the directory containing DCIM Downloads, etc.), are stored either entirely in the internal memory or entirely on the adopted SD card. After the initial format of an adopted SD card the user will be presented with an opportunity to "Migrate data" which will move all of /storage/emulated/0 to the SD card. At any time the user can also go to Settings / Storage, pick the storage area that does not currently hold the public data area, and the and clicking the ⋮ (three vertical dots) icon at the upper right to bring up a menu with the "Migrate data" option.
It appears that there's no way for a user or application to force a particular public file to the SD card if an adopted card is in use; it's all or nothing. (The app's private storage will be in the internal storage or on the SD card based on whether or not the app has been moved to the SD card; there too it appears that the app will only ever be using one or the other, not both.)

How to find whether the SD card is present or not via code/API in Android?

How to get the status whether a SD card is mounted/inserted in Android device or not.
The following is always returning TRUE:
android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)
There are several post related to this, but I couldn't find a manufacturer-independent solution.
Android API: Iterate through all external storages obtainable with getExternalStoragePublicDirectory, calling isExternalStorageRemovable on each of them. When you find one, ask if it is mounted with getExternalStorageState. However, it may happen that the SD card is not used for any external storage directory and so you would not find it.
fstab: Parse /etc/vold.fstab, find mount points, ask if they are removeable with isExternalStorageRemovable and check their state with getExternalStorageState. Because it does not use public API, it may not work correctly in some versions of Android, including future ones. It may not work when the SD card is not used for any external storage either.
mounts: Parse /proc/mounts and do the same as for fstab but that may not work if the SD card is not used for any external storage. Or search for any partition using vfat but that may return false positives. /proc/mounts is a public Linux API so it is present in the same format everywhere. If no SD card can be found there, it is impossible to distinguish whether the SD card is unmounted or not supported at all.
However, there's really no reason to need that (and that's why there is no simple API for it). When you want to put some content in an external storage, you should use the appropriate directory provided by getExternalStoragePublicDirectory, disregarding whether it is an SD card or not.

Android app says folder exists but I cant see it

I have an app I made on my old phone. It creates a folder called LocationTracker. When Im stepping through the code it says the folder exists. But I cant seem to browse to it when I connect my phone to the computer. I just checked my file explorer on my phone and i can browse to the folder there as well. According to that it is under the sd card, but i just cant see it on my PC.
Im rooting around in my file explorer on my phone. There appears to be 2 sd card folders. One is called sdcard1, and that seems to be my actual sd card. The other is called sd card. I think its an emulated one. I use Environment.getExternalStorageDirectory(), i thought that returned the sd card if one was available. If that is the case why is it using the emulated folder instead of the actual sd card folder? How do I fix this?
From Android documentation:
In devices with multiple "external" storage directories, this directory represents the "primary" external storage that the user will interact with. Access to secondary storage is available through
The rest of the sentence is sadly missing. However the methods are Context.getExternalFilesDirs() and Context.getExternalMediaDirs().

Saving data to /externalsdcard/Android/data/<app package name> in KITKAT

I read alot about KITKAT and the prevention of writing to the secondary external sdcard.
It seems to be a new policy from google. I also read about storing the app's data under /externalsdcard/Android/data/.
Now my question, because I can't reproduce or test:
If the app is not allowed to write data directly under
< secundary external sdcard >, Will it then be possible to store the app's data under < secundary external sdcard >/Android/data/< app package name > ?
If possible. Could someone share a codesample ?
Never assume the removable secondary storage is larger than primar internal. On most modern devices internal storage can be up to 64 GB, but SD Card can be as small as 1 MB large (if user inserted small old card).
There is no way to distinguish which one is "external" using current APIs.
So the right way is using Context.getExternalFilesDirs() which returns all external storages to which you can store application-specific files without any permissions.
Use StatFs to find the largest storage available, and write data into it.
final File[] dirs = context.getExternalFilesDirs(null); //null means default type
//find a dir that has most of the space and save using StatFs
As the documentation says,
Returns absolute paths to application-specific directories on all 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.
This is like getFilesDir() in that these files will be deleted when the application is uninstalled, however there are some important differences:
External files are not always available: they will disappear if the user mounts the external storage on a computer or removes it.
There is no security enforced with these files.
External storage devices returned here are considered a permanent part of the device, including both emulated external storage and physical media slots, such as SD cards in a battery compartment. The returned paths do not include transient devices, such as USB flash drives.
An application may store data on any or all of the returned devices. For example, an app may choose to store large files on the device with the most available space, as measured by StatFs.
No permissions are required to read or write to the returned paths; they are always accessible to the calling app. Write access outside of these paths on secondary external storage devices is not available.
The first path returned is the same as getExternalFilesDir(String). Returned paths may be null if a storage device is unavailable.

Categories

Resources