My Phonegap application deals with some large files, so I want to store them on the user's external SD card if possible. The org.apache.cordova.file plugin says that you can call
window.resolveLocalFileSystemURL(
cordova.file.externalDataDirectory, ...)
which it describes as "where to put app-specific data files on external storage."
This resolves to file:///mnt/sdcard/Android/data/my.app.id and that's where my files get saved. Unfortunately, that's not "external" storage; a number of phones I have tested appear to have an "internal" SD card (built into the phone, limited capacity) and an external SD card (the pluggable slot).
With the Sony Xperia st23i, for example, the external SD card gets mounted at /mnt/ext_sdcard. Judging by pages like this one it's very device-specific where the physical external SD card appears on the system.
In this JIRA issue it was suggested that the file-system-roots plugin should provide a way to get at file:/storage/extSdCard, but the file-system-roots plugin is now supposed to be folded into org.apache.cordova.file; however, its documentation does not appear to have an option for the actual external SD card. ("External storage (SD card) " just means "not the phone's internal storage" rather than the pluggable slot.)
Is there a sensible, portable way to address the user-supplied microSD (if there is one) card from phonegap?
Related
I've been looking for a way to get the SD card directory for a majority of the day. I've recently found out that the function call getExternalStorageDirectory under some circumstances returns a path that is on-board memory. I am supporting API 19 and above.
The common answer stackOverflow gives to get the SD card path is
Environment.getExternalStorageDirectory().getAbsolutePath();
which is not working for my devices because the external storage returned is non-removable memory (Samsung Tab S2).
I've been able to use getExternalFilesDirs to return the list of directories, and in my testing it will return two directories, the on-board memory location for the application and the SD card that I've mounted. However the function call
isExternalStorageRemovable was not introduced until API 21. This was the clearest candidate that I could find that would have satisfied what I am trying to do, which is make sure that I am actually writing to the external SD Card.
1) Is there a way to verify if the directory returned by getExternalFilesDirs is removable or external in API 19?
2) Can it be assumed that if the only storage use cases are "Internal Memory" and "Internal Memory and SD Card" that the SD card location will always be returned second from getExternalFilesDirs as has happened in my brief testing?
I've recently found out that the function call getExternalStorageDirectory under some circumstances returns a path that is on-board memory
External storage is not removable storage. On the vast majority of Android devices, getExternalStorageDirectory() returns a location that is part of the on-board flash. That has been the case for ~7 years, since the introduction of Android 3.0.
Is there a way to verify if the directory returned by getExternalFilesDirs is removable or external in API 19?
If getExternalFilesDirs() returns 2+ items, the second and subsequent ones are on removable storage.
Can it be assumed that if the only storage use cases are "Internal Memory" and "Internal Memory and SD Card"
That is not a safe assumption.
that the SD card location will always be returned second from getExternalFilesDirs as has happened in my brief testing?
The first entry returned by getExternalFilesDirs() is the same as what is returned by getExternalFilesDir() (the older, singular form). While the vast majority of Android devices have fixed external storage, there may be some devices where external storage is actually removable. In this case, the Android SDK and framework still consider this to be external storage — after all, that is what the device manufacturer told the firmware to do. And, in this case, the location returned first from getExternalFilesDirs() would be physically removable, even if it is not what Android developers typically think of as removable storage. This is a fringe scenario; I cannot name any current device models that have external storage implemented on a removable card.
Also, bear in mind that not all removable storage is in the form of a card. USB OTG thumb drives are also removable storage, as are more traditional thumb drives for those devices that have a USB Type A port (e.g., Android TV, Samsung Galaxy S8 in a DeX dock).
which is make sure that I am actually writing to the external SD Card.
I strongly recommend that you stop thinking in terms of media. Use things like the Storage Access Framework (e.g., ACTION_OPEN_DOCUMENT, ACTION_CREATE_DOCUMENT) to allow the user to choose places to store content from all possibilities at their disposal: external storage, removable storage, Google drive, Windows file servers, etc.
I'm using CyanogenMod 10.2.1 on an Xperia ZR. This device has an emulated SD card and a removable SD card. The stock camera app has an option to store images in the emulated or the removable SD card (see screenshots below).
I'm writing a camera app and I want to do the same thing, so I looked at the code of the camera app in Android's source and in CyanogenMod's source. The first uses Environment.getExternalStoragePublicDirectory() and the second Environment.getExternalStorageDirectory(). Neither of those seem to be dynamic, so where does the setting item come from?
Here are some screenshots showing the storage option:
All in all, I want to find out whether those apps use the techniques in Find an external SD card location to access secondary storage.
This link here describes about the non removable external storage.
does all the android devices have non removable external storage ?
No, this depends completely on the manufacturer. Devices like the Nexus S, Galaxy Nexus and Nexus 4 have non removable external storage, while some devices like the Optimus One have only removable external storage. Some devices may even have two external storages, one a partition on the on board memory chip and another as an SD Card.
EDIT
As CommonsWare pointed out in the comments, as far as the standard Android SDK is concerned, you only have one external storage on the device (which you can get via Environment.getExternalStorageDirectory()). As the documentation states, this will return the primary external storage in the event of the presence of more than one external storage:
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.
From that link
Because the external storage may be unavailable—such as when the user has mounted the storage to a PC or has removed the SD card that provides the external storage—you should always verify that the volume is available before accessing it.
I am developing a program that need read/write some files from sdcard or internal storage at runtime. When I mount the sdcard in my phone it run correctly but if i unmount sdcard my application raises some error.
What I have to do for phones that have not card slot like Htc one x or phones that have not any sdcard inserted? how i can write on those phones storage? I don't want write this file into /data/data/my.app.package folder. I want write somewhere that files can be read from another apps.
first I check storage status with this code and if sdcard be inserted and writable i have not any problem. but if sdcard does not exists i realy don't know what i have to do.
string _location;
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
_location=Environment.getExternalStorageDirectory()+"/myfolder/";
Toast.makeText(context, _location, 1000).show();
}
else
{
_location="/myfolder/"
Toast.makeText(context, Environment.getExternalStorageDirectory().toString(), 1000).show();
}
mysync mys=new mysync(); // Asynctasc that writes some file on _location path
mys.execute(_location);
i am so confused and undortunately i haven't any phone with big internal storage. please help me.
I am developing a program that need read/write some files from sdcard or internal storage at runtime.
Here, and in your question title, you say you want to write to internal storage. Later, you say that you do not want to write to internal storage.
Which is it?
What I have to do for phones that have not card slot like Htc one x or phones that have not any sdcard inserted?
External storage != "sdcard". External storage can be whatever the device manufacturer wants, so long as it meets the terms of the Compatibility Definition Document. Hence, external storage can be removable (e.g., SD card) or not (e.g.,. dedicated portion of on-board flash). And, on Android 3.0+, external storage is merely a special subdirectory on the same partition that contains internal storage.
You only care about whether external storage is presently available or not. It should be available pretty much all of the time on Android 3.0+ devices. It will be unavailable on Android 1.x and 2.x devices if the device is plugged into a host computer and the host computer has mounted the device's external storage (e.g., as a drive letter on Windows).
if sdcard does not exists i realy don't know what i have to do.
You ask the user to please unmount their device from their host computer. Or, you decide to write to internal storage in those cases.
What exactly does Environment.ExternalStorageDirectory return? I read from the developer docs:
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.
Am I correct in understanding that if my device has a large (16GB) internal memory and no SD Card, this will return the path to the internal memory?
Or, do I have to check to see if the SD card is mounted and if not, use the ApplicationContext.FilesDir?
I suppose what I am asking is, if my app needs to download 250MB of data, how do I know where to store it? - As I want to use the "correct" location.
Am I correct in understanding that if my device has a large (16GB) internal memory and no SD Card, this will return the path to the internal memory?
It will return a path to external storage. On a device with the characteristics you describe, external storage will either be:
a separate data partition of that 16GB of on-board flash (Android 2.x), or
a directory within the main data partition of that 16GB of on-board flash (Android 3.0+)
Or, do I have to check to see if the SD card is mounted
External storage may be mounted on a host PC, regardless of whether external storage is represented by an SD card, a portion of on-board flash, or pixie dust.
On Android 2.x, if external storage is mounted on a host PC, it is unavailable to your application. Hence, if you are supporting Android 2.x, you need to check whether external storage is available, regardless of how that external storage is implemented.
I suppose what I am asking is, if my app needs to download 250MB of data, how do I know where to store it?
Put it on external storage. If external storage is not available, do not download the data and tell the user to unmount their phone from their host PC. There are many Android 2.x devices which do not even have 250MB of internal storage for all apps combined, let alone for just your use.
Here is another stackoverflow thread. Hope it will work for you.