Android's external vs internal storage is something that developers working on media applications have to deal with. This is even more confusing as some devices without an external SD card slot would return valid data set for MediaStore.Images.Media.EXTERNAL_CONTENT_URI. Official documentation too doesn't help.
So how are developers supposed to frame the query, given that the real world external/internal terminology (understood by app users) is interpreted differently by Android APIs? So lets take a look at the source path used by the content provider serving media dataset (audio, images, video etc).
Android's media scanner service kicks off upon boot completion and scans the physical storage and populates the media provider. In this process, the meta data along with the file path is stored as database entries. From here on, the applications can use a content resolver to query and fetch data set.
if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
// Scan both internal and external storage
scan(context, MediaProvider.INTERNAL_VOLUME);
scan(context, MediaProvider.EXTERNAL_VOLUME);
}
Media scanner service considers /system/media and /oem/media as internal storage. The root directory and oem directory can be controlled by device manufactures via environment variables, ENV_ANDROID_ROOT and ENV_OEM_ROOT respectively. Applications wanting to process media contents stored in this path could query media provider for INTERNAL_CONTENT_URI.
Paths for external volume is queried from Mount service (via StorageManager). Mount service basically keeps track of a list of volumes (including emulated volumes) that are mounted at run time. These external mount points are specified via an xml and processed during boot up. Querying EXTERNAL_CONTENT_URI basically translates to these mount volumes including sdcard.
int id = com.android.internal.R.xml.storage_list;
XmlResourceParser parser = resources.getXml(id);
AttributeSet attrs = Xml.asAttributeSet(parser);
try {
XmlUtils.beginDocument(parser, TAG_STORAGE_LIST);
while (true) {
XmlUtils.nextElement(parser);
String element = parser.getName();
if (element == null) break;
if (TAG_STORAGE.equals(element)) {
TypedArray a = resources.obtainAttributes(attrs,
com.android.internal.R.styleable.Storage);
String path = a.getString(
com.android.internal.R.styleable.Storage_mountPoint);
int descriptionId = a.getResourceId(
com.android.internal.R.styleable.Storage_storageDescription, -1);
CharSequence description = a.getText(
com.android.internal.R.styleable.Storage_storageDescription);
boolean primary = a.getBoolean(
com.android.internal.R.styleable.Storage_primary, false);
boolean removable = a.getBoolean(
com.android.internal.R.styleable.Storage_removable, false);
boolean emulated = a.getBoolean(
com.android.internal.R.styleable.Storage_emulated, false);
int mtpReserve = a.getInt(
com.android.internal.R.styleable.Storage_mtpReserve, 0);
boolean allowMassStorage = a.getBoolean(
com.android.internal.R.styleable.Storage_allowMassStorage, false);
OnePlus one (Kitkat 4.4.4) and Nexus 4 (CM 11) has ringtones, notification music etc in /system/media and doesn't use environment variables.
So how are developers supposed to frame the query, given that the real world external/internal terminology (understood by app users) is interpreted differently by Android APIs? So lets take a look at the source path used by the content provider serving media dataset (audio, images, video etc).
Android's media scanner service kicks off upon boot completion and scans the physical storage and populates the media provider. In this process, the meta data along with the file path is stored as database entries. From here on, the applications can use a content resolver to query and fetch data set.
if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
// Scan both internal and external storage
scan(context, MediaProvider.INTERNAL_VOLUME);
scan(context, MediaProvider.EXTERNAL_VOLUME);
}
Media scanner service considers /system/media and /oem/media as internal storage. The root directory and oem directory can be controlled by device manufactures via environment variables, ENV_ANDROID_ROOT and ENV_OEM_ROOT respectively. Applications wanting to process media contents stored in this path could query media provider for INTERNAL_CONTENT_URI.
Paths for external volume is queried from Mount service (via StorageManager). Mount service basically keeps track of a list of volumes (including emulated volumes) that are mounted at run time. These external mount points are specified via an xml and processed during boot up. Querying EXTERNAL_CONTENT_URI basically translates to these mount volumes including sdcard.
int id = com.android.internal.R.xml.storage_list;
XmlResourceParser parser = resources.getXml(id);
AttributeSet attrs = Xml.asAttributeSet(parser);
try {
XmlUtils.beginDocument(parser, TAG_STORAGE_LIST);
while (true) {
XmlUtils.nextElement(parser);
String element = parser.getName();
if (element == null) break;
if (TAG_STORAGE.equals(element)) {
TypedArray a = resources.obtainAttributes(attrs,
com.android.internal.R.styleable.Storage);
String path = a.getString(
com.android.internal.R.styleable.Storage_mountPoint);
int descriptionId = a.getResourceId(
com.android.internal.R.styleable.Storage_storageDescription, -1);
CharSequence description = a.getText(
com.android.internal.R.styleable.Storage_storageDescription);
boolean primary = a.getBoolean(
com.android.internal.R.styleable.Storage_primary, false);
boolean removable = a.getBoolean(
com.android.internal.R.styleable.Storage_removable, false);
boolean emulated = a.getBoolean(
com.android.internal.R.styleable.Storage_emulated, false);
int mtpReserve = a.getInt(
com.android.internal.R.styleable.Storage_mtpReserve, 0);
boolean allowMassStorage = a.getBoolean(
com.android.internal.R.styleable.Storage_allowMassStorage, false);
OnePlus one (Kitkat 4.4.4) and Nexus 4 (CM 11) has ringtones, notification music etc in /system/media and doesn't use environment variables.
shell@A0001:/ $ echo $ENV_ANDROID_ROOT
shell@A0001:/ $ echo $ENV_OEM_ROOT
shell@A0001:/ $ ls /system/media
LMprec_508.emd
PFFprec_600.emd
audio
bootanimation.zip
Nexus 4 (Lollipop 5.0.1) has something similar,
shell@mako:/ $ echo $ENV_ANDROID_ROOT
shell@mako:/ $ echo $ENV_OEM_ROOT
shell@mako:/ $ ls /system/media
audio
bootanimation.zip
shell@mako:/ $ ls /system/media/audio
alarms
notifications
ringtones
ui
2 comments:
Infycle Technologies is the best software training center in Chennai and is widely known for its excellence in giving the best software training in Chennai. Providing quality software programming training with 100% assured placement & to build a strong career for every individual and young professionals in the software industry is the ultimate aim of Infycle Technologies. Apart from all, the students love the 100% practical training, which is the specialty of Infycle Technologies. To proceed with your career with a solid base, reach Infycle Technologies through 7502633633.Best Software Training Center in Chennai | Infycle Technologies
Post a Comment