Android scanning multimedia file operation detailed _android

Source: Internet
Author: User
Tags locale

This article from the System source code analysis, describes how to add the multimedia files created by the program to the system's media Library, how to remove from the Media Library, as well as most of the program developers often encounter problems can not be added to the Media Library. I will explain these problems through the analysis of the source code.

Multimedia file scanning mechanism in Android

Android provides a great program to handle media libraries that add multimedia files. This program is Mediaprovider, now we simply look at the following program. First look at its receiver.

Copy Code code as follows:

<receiver android:name= "Mediascannerreceiver" >
<intent-filter>
<action android:name= "Android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
<intent-filter>
<action android:name= "Android.intent.action.MEDIA_MOUNTED"/>
<data android:scheme= "File"/>
</intent-filter>
<intent-filter>
<action android:name= "Android.intent.action.MEDIA_UNMOUNTED"/>
<data android:scheme= "File"/>
</intent-filter>
<intent-filter>
<action android:name= "Android.intent.action.MEDIA_SCANNER_SCAN_FILE"/>
<data android:scheme= "File"/>
</intent-filter>
</receiver>

Mediascannerreceiver only receives the correct intent with action and data rules.

Mediascannerreciever how to deal with intent

1. Scan for internal storage (not built-in and external sdcard) when and only when action Android.intent.action.BOOT_COMPLETED is received
2. Intent must have data transfer, except for action-Android.intent.action.BOOT_COMPLETED.
3. When received intent.action_media_mounted Intent, scan sdcard
4. When received Intent.action_media_scanner_scan_file Intent, detection is not a problem, will scan a single file.

How Mediascannerservice Works

In fact, Mediascannerreceiver does not really handle scanning work, it starts a service called Mediascannerservice. We continue to look at the part of Mediaprovider's manifest about service.

Copy Code code as follows:

<service android:name= "Mediascannerservice" android:exported= "true" >
<intent-filter>
<action android:name= "Android.media.IMediaScannerService"/>
</intent-filter>
</service>

The Scanfile method in Mediascannerservice

Copy Code code as follows:

Private Uri Scanfile (string path, String mimetype) {
String volumename = Mediaprovider.external_volume;
OpenDatabase (VolumeName);
Mediascanner scanner = Createmediascanner ();
return Scanner.scansinglefile (Path, VolumeName, mimetype);
}

The scan method in Mediascannerservice

Copy Code code as follows:

private void Scan (string[] directories, String volumename) {
Don ' t sleep while scanning
Mwakelock.acquire ();

Contentvalues values = new Contentvalues ();
Values.put (Mediastore.media_scanner_volume, volumename);
Uri Scanuri = Getcontentresolver (). Insert (Mediastore.getmediascanneruri (), values);

Uri uri = uri.parse ("file://" + directories[0]);
Sendbroadcast (New Intent (intent.action_media_scanner_started, Uri));

try {
if (Volumename.equals (Mediaprovider.external_volume)) {
OpenDatabase (VolumeName);
}

Mediascanner scanner = Createmediascanner ();
Scanner.scandirectories (directories, volumename);
catch (Exception e) {
LOG.E (TAG, "exception in Mediascanner.scan ()", e);
}

Getcontentresolver (). Delete (Scanuri, NULL, NULL);

Sendbroadcast (New Intent (intent.action_media_scanner_finished, Uri));
Mwakelock.release ();
}

The Createmediascanner method in Mediascannerservice

Copy Code code as follows:

Private Mediascanner Createmediascanner () {
Mediascanner scanner = new Mediascanner (this);
Locale Locale = Getresources (). GetConfiguration (). Locale;
if (locale!= null) {
String language = Locale.getlanguage ();
String country = locale.getcountry ();
String localestring = null;
if (language!= null) {
if (country!= null) {
Scanner.setlocale (Language + "_" + country);
} else {
Scanner.setlocale (language);
}
}
}

return scanner;
}

From the above can be found that the real work is actually android.media.MediaScanner.java specific scanning process, please click on the left link to view.

How to scan a file that you just created

Here are two ways to implement adding a newly created file to a media library.

The simplest way

Only need to send a correct intent broadcast to Mediascannerreceiver.

Copy Code code as follows:

String saveAs = "Your_created_file_path"
Uri Contenturi = uri.fromfile (new File (SaveAs));
Intent mediascanintent = new Intent (Intent.action_media_scanner_scan_file,contenturi);
GetContext (). Sendbroadcast (mediascanintent);

The above minimalist approach works most of the time, but in some cases it will not work, as will be described later in this section. Even if you have succeeded in using the above method, it is advisable to continue reading later on why the broadcast was unsuccessful.

Using Mediascannerconnection

Copy Code code as follows:

public void Mediascan (file file) {
Mediascannerconnection.scanfile (Getactivity (),
New string[] {File.getabsolutepath ()}, NULL,
New Onscancompletedlistener () {
@Override
public void onscancompleted (String path, Uri Uri) {
LOG.V ("Mediascanwork", "File" + Path
+ "was scanned seccessfully:" + uri);
}
});
}

The Mediascannerconnection Scanfile method is introduced from the 2.2 (API 8).

Create a Mediascannerconnection object and then call the Scanfile method

Very simple, reference http://developer.android.com/reference/android/media/MediaScannerConnection.html

How to scan multiple files

1. Send multiple Intent.action_media_scanner_scan_file broadcasts
2. Using Mediascannerconnection, pass in the array of paths to join.

Why sending Media_scanner_scan_file broadcasts does not take effect

As for why some devices are not effective, many people think it is the API, in fact, it is not, this is actually related to the file path you passed in. Look at the OnReceive code of the recipient receiver.

Copy Code code as follows:

public void OnReceive (context context, Intent Intent) {
String action = Intent.getaction ();
Uri uri = Intent.getdata ();
if (Action.equals (intent.action_boot_completed)) {
Scan internal Storage
Scan (context, mediaprovider.internal_volume);
} else {
if (Uri.getscheme (). Equals ("file")) {
Handle intents related to external storage
String path = Uri.getpath ();
String Externalstoragepath = Environment.getexternalstoragedirectory (). GetPath ();

LOG.D (TAG, "action:" + Action + "path:" + path);
if (Action.equals (intent.action_media_mounted)) {
Scan whenever any volume is mounted
Scan (context, mediaprovider.external_volume);
else if (action.equals (intent.action_media_scanner_scan_file) &&
Path!= null && path.startswith (Externalstoragepath + "/")) {
Scanfile (context, path);
}
}
}
}

All the parts are correct except for the incoming path. Because you may have hard-coded the file path. Because there is one such judgment Path.startswith (Externalstoragepath + "/"), here I give a simple example.

Copy Code code as follows:

Final String saveAs = "/sdcard/" + system.currenttimemillis () + "_add.png";
Uri Contenturi = uri.fromfile (new File (SaveAs));
Intent mediascanintent = new Intent (Intent.action_media_scanner_scan_file,contenturi);
GetContext (). Sendbroadcast (mediascanintent);
Uri uri = Mediascanintent.getdata ();
String path = Uri.getpath ();
String Externalstoragepath = Environment.getexternalstoragedirectory (). GetPath ();
LOG.I ("LogTag", "Androidyue onreceive intent=" + mediascanintent
+ ";p ath=" + path + "externalstoragepath=" +
Externalstoragepath);

Let's look at the output log and analyze the reason.

Copy Code code as follows:

LogTag Androidyue onreceive intent= Intent {act=android.intent.action.media_scanner_scan_file dat=file:///sdcard/ 1390136305831_add.png};p Ath=/sdcard/1390136305831_add.png;externalstoragepath=/mnt/sdcard

The above output analysis, you send the broadcast, the action is correct, the data rule is also correct, and your file path also exists, however, the file path/sdcard/1390136305831_add.png not with the external storage root path/mnt/sdcard/ Beginning. So the scan did not start, causing the file to not be added to the Media Library. So, check the path to the file.

How to remove from a multimedia library

If we delete a multimedia file, it means we also need to remove the file from the Media Library.

Can you just send the radio?

Does just sending a broadcast solve the problem? I wish I could, but actually it's not working, so see the code below.

Copy Code code as follows:

This function is used to scan a single file
Public Uri Scansinglefile (string path, String volumename, String mimetype) {
try {
Initialize (volumename);
Prescan (path, true);

File File = new file (path);
if (!file.exists ()) {
return null;
}

LastModified is in milliseconds on Files.
Long lastmodifiedseconds = file.lastmodified ()/1000;

Always scan the file, so we can return the Content://media Uri for existing files
return Mclient.doscanfile (Path, MimeType, Lastmodifiedseconds, File.length (),
False, True, Mediascanner.isnomediapath (path));
catch (RemoteException e) {
LOG.E (TAG, "remoteexception in Mediascanner.scanfile ()", e);
return null;
}
}

As the code above, the file is checked for existence, and if the file does not exist, stop down execution directly. So that's not going to work. What about it?

Copy Code code as follows:

public void Testdeletefile () {
String Existingfilepath = "/mnt/sdcard/1390116362913_add.png";
File Existingfile = new file (Existingfilepath);
Existingfile.delete ();
Contentresolver resolver = getactivity (). Getcontentresolver ();
Resolver.delete (Images.Media.EXTERNAL_CONTENT_URI, Images.Media.DATA + "=?", new String[]{existingfilepath});

}

The above code can work, directly removed from the Mediaprovider. For specific deletion code, refer to code snippet for Media on Android

One more Thing

You can get more information by looking at/data/data/com.android.providers.media/databases/external.db (slightly different systems) files.

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.