Android Media Storage Service
This article describes how the developer app uses the media Storage service (including Mediascanner, Mediaprovider, and media information parsing) in Android, and includes how to update the app's new or modified files to the media database, How to hide the files generated by the app in the multimedia application, how to monitor the changes of the media database and so on.
Brief introduction:
This article describes how the developer app uses the media Storage service (including Mediascanner, Mediaprovider, and media information parsing) in Android, and includes how to update the app's new or modified files to the media database, How to hide the files generated by the app in the multimedia application, how to monitor the changes of the media database and so on.
Android native has a media storage service, the process name is Android.process.media, the main responsibility is to save the disk file information in the database, for other apps and MTP mode use. So the APP can quickly find out how much music is on the machine at any time, with the duration of the music, the title, the artist, and the album cover available. Here's how the APP we developed deals with this media storage service.
The NOTE:MTP mode was introduced by Android 3.0, and its data came from media storage services.
Hide multimedia files
Application Scenario: The app produces a picture/music/video class file and doesn't want it to appear in the gallery/music player. There are many games on the market, its pictures and sound effects files do not hide, appear in the user's library/music player, causing users to resent. If the user deletes it, it may affect the APP's normal operation.
Method One: Set the file to be hidden. The file in Linux is hidden, for example, "file a" is changed to ". File a". or remove the file extension so that the media Store service does not use it as a multimedia file when it scans.
Method Two: Generate a blank file named ". Nomedia" under the folder. All files under the same folder will not be treated as multimedia files.
1. Add/Modify multimedia files
Application Scenario: The app creates a new multimedia file, or modifies an existing multimedia file. For example, the APP downloads a music file, notifies the media store service, and the user can see the file in the music player. Otherwise, only the next time the media store service starts scanning the entire disk, the new files generated by the APP will be discovered.
Method One
If there is only one file and you do not need to get the result back, send Intent to notify the media Storage service directly.
Copy CodeThe code is as follows:
Import Java.io.File;
Import Android.content.Context;
Import android.content.Intent;
Import Android.net.Uri;
private static void Requestscanfile (context context, file file) {
Intent i = new Intent (intent.action_media_scanner_scan_file);
I.setdata (uri.fromfile (file));
Context.sendbroadcast (i);
}
private static void Requestscanfile (context context, String file) {
Intent i = new Intent (intent.action_media_scanner_scan_file);
I.setdata (Uri.parse ("file://" + uri.encode (file));
Context.sendbroadcast (i);
}
Note: If you use Uri.parse () to generate a Uri from a file name, the file name must first be Uri.encode () to escape the reserved character. For example, if the file name contains "?", it will be treated as a query parameter without Uri.encode escaping, so that the file path obtained by Uri.getpath () will be lost "?" After the part.
Method Two
If there is only one file and the file URI result is required to return, use the callback function.
Copy CodeThe code is as follows:
Import android.media.MediaScannerConnection;
Import Android.net.Uri;
private void Requestscanfile (context context, String file) {
Mediascannerconnection.scanfile (context, new string[] {file},
NULL,//MIME types, unspecified
Mlistener);
}
Mediascannerconnection.onscancompletedlistener Mlistener =
New Mediascannerconnection.onscancompletedlistener () {
public void onscancompleted (String path, Uri Uri) {
TODO: Get the URI to the file in the multimedia database and proceed to the next action
}
};
Note: There is also a way to insert a record that contains a file path to the multimedia database, insert it to get its URI, and then use method one to notify the media Storage service to scan the file and add the file information (such as the album name) to complete. However, this method is not recommended because the file information is not complete when the URI is obtained.
Method Three
If the file is large, Intent notifies the media storage service to scan the entire disk. This is not particularly good, but no other better interface has been found. Third-party file management such as "ES File Manager" is used in this way.
Copy CodeThe code is as follows:
Import Android.content.Context;
Import android.content.Intent;
Import Android.net.Uri;
private static void Requestscandisk (context context) {
Intent i = new Intent (intent.action_media_mounted);
String path = Environment.getexternalstoragedirectory (). GetPath ();
I.setdata (Uri.parse ("file://" + uri.encode (path));
Context.sendbroadcast (i);
}
2. Monitor data changes
Application Scenario: Multimedia database changes, need to refresh the app display interface. Better understand that the multimedia files on the disk have been added, deleted or modified, the APP interface to respond to these changes in real time, refresh the display interface.
Method One
Monitor media storage related Intent. Once the Intent is accepted, the database is queried again. We need to pay attention to Intent mainly have the following several:
1, intent.action_media_scanner_finished: Media storage Services Scan the entire disk will be sent after the Intent. There may be more files added or deleted.
2. Intent.action_media_scanner_scan_file: The media Storage service scans a single file.
Copy CodeThe code is as follows:
Import Android.content.BroadcastReceiver;
Import Android.content.Context;
Import android.content.Intent;
Import Android.content.IntentFilter;
Import Android.net.Uri;
private void Registerreceiver (context context) {
Intentfilter filter = new Intentfilter (intent.action_media_mounted);
Filter.addaction (intent.action_media_scanner_finished);
Filter.addaction (Intent.action_media_scanner_scan_file);
Filter.adddatascheme ("file");
Context.registerreceiver (mreceiver, filter);
}
Private Broadcastreceiver Mreceiver = new Broadcastreceiver () {
@Override
public void OnReceive (context context, Intent Intent) {
String action = Intent.getaction ();
Uri uri = Intent.getdata ();
if (uri! = null && uri.getscheme (). Equals ("file")) {
LOG.V ("Receiver", "broadcastreceiver action =" + action + ", Uri =" + uri ");
if (Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals (ACTION)) {
String FilePath = Uri.getpath ();
Todo:filepath file has changed, APP refresh interface
} else if (Intent.ACTION_MEDIA_SCANNER_FINISHED.equals (ACTION)) {
TODO: Entire disk scan complete, APP refresh interface
}
}
}
};
In addition, in the time between intent.media_scanner_started and intent.action_media_scanner_finished, the media storage service is scanning files, the database will change, so only after receiving The result of the query after intent.action_media_scanner_finished is accurate. If you want to detect whether the media store service is scanning, you can use the following methods:
Copy CodeThe code is as follows:
Import Android.content.ContentResolver;
Import Android.database.Cursor;
Import android.os.Environment;
Import Android.provider.MediaStore;
private static Boolean ismediascannerscanning (Contentresolver cr) {
cursor cursor = NULL;
try {
cursor = Cr.query (Mediastore.getmediascanneruri (), new string[] {
Mediastore.media_scanner_volume}, NULL, NULL, NULL);
if (cursor! = NULL && cursor.getcount () > 0) {
Cursor.movetofirst ();
Return "external". Equals (cursor.getstring (0));
}
} finally {
if (cursor! = NULL) {
Cursor.close ();
}
}
return false;
}
Note:app may also need to monitor changes to the storage device, such as the SD card unplugged, the disk mounted (USB mass storage mode), and so on, in which case you may want to empty the file display interface or exit the program. Each phone may have a slightly different definition for each Intent, but it's basically the following:
1, Intent.action_media_eject: storage device normal removal, such as in the settings to unload memory.
2, intent.action_media_unmounted: storage device normal unloading, usually with EJECT appeared successively.
3, Intent.action_media_bad_removal: Abnormal removal of storage devices, such as hard-pluggable SD card.
Method Two
Listen for database changes. If you need to receive notifications in real time when the database changes, you can use Contentobserver.
Copy CodeThe code is as follows:
Import Android.content.Context;
Import Android.database.ContentObserver;
Import Android.database.Cursor;
Import Android.net.Uri;
Private Contentobserver Mcontentobserver = new Contentobserver (null) {
@Override
public void OnChange (Boolean selfchange) {//Backwards compatible
OnChange (Selfchange, NULL);
}
public void OnChange (Boolean selfchange, Uri Uri) {
TODO: The data has changed, the APP re-queried the database and refreshed the interface
}
};
private void Setupcursor (context context, Cursor c) {
C.unregistercontentobserver (Mcontentobserver); C is the data that needs to be displayed
}
In addition, using CursorAdapter and the displayed ListView bindings can also achieve the same purpose. When the Cursor content is found to be changed, the ListView automatically refreshes accordingly.
Android Media Storage Service (i)