The interaction between Android app and media Storage service _android

Source: Internet
Author: User

Brief introduction:
This article describes how developers ' apps use media storage services (including Mediascanner, Mediaprovider, and media information parsing) in Android, and 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 has an original set of media storage services, the process name is Android.process.media, mainly responsible for the disk file information stored in the database for other APP use and MTP mode use. So APP can quickly find out how much music is on the machine at any time, and the length, title, artist, and album cover of the music can be obtained. Here's a description of 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: APP produces a picture/music/video class file that does not want it to be displayed in the gallery/music player. There are many games on the market, its pictures and audio files do not hide, appearing in the user's gallery/music player, causing users to resent. If the user deletes it, it may affect the APP's normal operation.

Method One: Set the file as hidden. A dot in Linux is hidden, for example, "file a" is changed to ". File a". or remove the file name extension so that the media Store service does not use it as a multimedia file when it is scanned.
Method Two: Create a blank file named ". Nomedia" under the folder. This way all files under the same folder are not treated as multimedia files.

Add/Modify multimedia files
Application Scenario: APP creates a new multimedia file, or modifies an existing multimedia file. For example, the APP downloads a music file and needs to notify the media Store service so that 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 file created 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 the Intent to the media storage service directly.

Copy Code code 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 the filename, the filename must be Uri.encode () to escape the reserved character. For example, if the filename contains "?", it is considered a query parameter without Uri.encode escaping, so that the path of the file Uri.getpath () is lost "?" After the part.

Method Two
If there is only one file, and the file URI result is required to return, the callback function is used.

Copy Code code 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, not specified
Mlistener);
}

Mediascannerconnection.onscancompletedlistener Mlistener =
New Mediascannerconnection.onscancompletedlistener () {
public void onscancompleted (String path, Uri Uri) {
TODO: Get the URI of the file in the multimedia database and take the next action
}
};


Note: There is another way to insert a record into a multimedia database that contains a file path, and then you can get its URI after inserting it, and then use the method one to notify the media Store service to scan the file and to complete the file information (such as album name). However, this method is not recommended because the file information is incomplete when the URI is obtained.

Method Three
If there are more files, the Intent notifies the media store service to scan the entire disk. This was not particularly good, but no other better interface was found. Third-party file management such as "ES File Manager" is the use of this method.

Copy Code code 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);
}

Monitor data changes
Application Scenario: Multimedia database changes, need to refresh the APP display interface. It is better to understand that the multimedia files on the disk have new, deleted or modified, the APP interface to real-time response to these changes, refresh the display interface.

Method One
Listen for media storage related Intent. Once the Intent is accepted, requery the database. The main Intent we need to pay attention to are as follows:
1, intent.action_media_scanner_finished: Media storage Services Scan the entire disk will be sent after the Intent. More files may be added or deleted.
2, Intent.action_media_scanner_scan_file: Media storage Services Scan a single file.

Copy Code code 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 changed, APP Refresh interface
else if (Intent.ACTION_MEDIA_SCANNER_FINISHED.equals (ACTION)) {
TODO: Full 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 and the database changes, so only when you receive The result of the query after intent.action_media_scanner_finished is accurate. If you want to detect if the media storage service is scanning, you can use the following methods:
Copy Code code 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 storage devices, such as SD card pull-out, disk mount (USB bulk storage mode), and so on, in which case the file display interface may be emptied, or the program can be exited. Each cell phone may have a slightly different definition for each Intent, but basically the following:
1, Intent.action_media_eject: storage devices To remove the normal, such as in the settings uninstall memory.
2, intent.action_media_unmounted: storage equipment normal unloading, usually with EJECT successively appear.
3, Intent.action_media_bad_removal: Abnormal removal of storage devices, such as hard plug SD card.

Method Two
Monitor database changes. If you need to receive notifications in real time when a database changes, you can use Contentobserver.

Copy Code code 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) {//Backward compatible
OnChange (Selfchange, NULL);
}

public void OnChange (Boolean selfchange, Uri Uri) {
TODO: The data has changed, the APP requery the database and refreshes the interface
}
};

private void Setupcursor (context context, Cursor c) {
C.unregistercontentobserver (Mcontentobserver); C for data that needs to be displayed
}


In addition, the same purpose can be achieved by using CursorAdapter and display ListView bindings. When Cursor content is found to change, ListView will automatically refresh accordingly.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.