In the Android Media app (Audio, Image, Video) need to do a detailed analysis of the Android media provider (Mediaprovider), the following record my harvest:
First, obtain Mediaprovider:
The project in the system source code Packages\providers directory, put forward and import eclipse, easy to read;
There are a lot of errors in the figure, it is drip, because we need some interface outside the System Standard SDK, but do not affect our reading code.
II. Engineering Structure and internal relations:
You can see that there are 4 files included:
Mediascannerservice.java: Media Services, with broadcast to achieve the media scanning class instantiation, the initialization of the database and other work, but also to provide interfaces;
Mediascannerreceiver.java: A broadcast receiver used to accept broadcasts from the system to media services and to activate media services;
Mediaprovider.java: Media Database Encapsulation class, the code is relatively large (more than 4,000 lines), the function is more complex, but in general is to create a database, to provide a URI to the database to achieve the deletion and modification of the function;
Mediathumbrequest.java: Media file thumbnail request class, used in conjunction with Mediaprovider;
The previous diagram is more intuitive:
It's not a standard class diagram, it's just a schematic diagram of a logical relationship drawing.
The position and function of Mediaprovider is shown in the red box in the picture;
Additional content is included:
1, the app layer: audio, image, video How to interact with the media Library;
2, the framework layer (Android.media package): How to achieve media scanning;
3, native layer: How to achieve the media file parsing;
4, the Resource storage layer: SD card, U disk and other media, DTCM storage thumbnail image;
Third, the type of detailed
1, Mediascannerreceiver:
public void OnReceive (context context, Intent Intent) {
String action = Intent.getaction ();
Uri uri = Intent.getdata ();
String Externalstoragepath =
Environment.getexternalstoragedirectory (). GetPath ();
String Externalsdstoragepath = Environment
. Getexternalsdstoragedirectory (). GetPath ();
String Externaludiskstoragepath = Environment
. Getexternaludiskstoragedirectory (). GetPath ();
String Externalextsdstoragepath = Environment
. Getexternalextsdstoragedirectory (). GetPath ();
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 ();
if (Action.equals (intent.action_media_mounted)) {
if (externalsdstoragepath.equals (path))
Scan (context, MEDIAPROVIDER.EXTERNAL_VOLUME_SD);
else if (externaludiskstoragepath.equals (path))
Scan (context, mediaprovider.external_volume_udisk);
else if (externalextsdstoragepath.equals (path))
Scan (context, MEDIAPROVIDER.EXTERNAL_VOLUME_EXTSD);
Else
SLOG.W (TAG, "Unknown volume path" + path);
} else if (Action.equals (intent.action_media_scanner_scan_file)
&& path! = NULL
&& (Path.startswith (Externalsdstoragepath + "/")
|| Path.startswith (Externalextsdstoragepath
+ "/") || Path
. StartsWith (Externaludiskstoragepath + "/"))) {
Scanfile (context, path);
}
}
}
}
There are three types of situations that need to start scanning services:
A, the system started to complete;
b, Media mounts (EXTERNAL_VOLUME_SD, External_volume_udisk, EXTERNAL_VOLUME_EXTSD);
C, media file scanning broadcast (action_media_scanner_scan_file);
The Scanfile and Scan methods are simple, just start media services:
private void scan (context context, String volume) {
Bundle args = new bundle ();
Args.putstring ("Volume", volume);
Context.startservice (New Intent (context, Mediascannerservice.class)
. Putextras (args));
}
private void Scanfile (context context, String path) {
Bundle args = new bundle ();
SLOG.I (TAG, "Start scanfile.");
Args.putstring ("filepath", path);
Context.startservice (New Intent (context, Mediascannerservice.class)
. Putextras (args));
}
2, Mediascannerservice:
First step: Start a thread
public void Run () {
Reduce priority below other background threads to avoid interfering
With other services at boot time.
Process.setthreadpriority (Process.thread_priority_background
+ process.thread_priority_less_favorable);
Looper.prepare ();
Mservicelooper = Looper.mylooper ();
Mservicehandler = new Servicehandler ();
Looper.loop ();
}
Get the current message queue in the thread and process the message using handler;
Part II: Start Servicehandler processing messages
Servicehandler in the processing of two kinds, one is scanning, the second is the resolution of specific media files;
Take a look at how the second one is implemented:
IBinder Binder = Arguments.getibinder ("Listener");
Imediascannerlistener listener = (Binder = = null? null
: IMediaScannerListener.Stub.asInterface (binder));
Uri uri = Scanfile (FilePath,
Arguments.getstring ("MimeType"));
if (listener! = null) {
Listener.scancompleted (FilePath, URI);
}
Code
Private final Imediascannerservice.stub Mbinder = new Imediascannerservice.stub () {
public void Requestscanfile (string path, String MimeType,
Imediascannerlistener listener) {
if (CONFIG.LOGD) {
LOG.D (TAG, "imediascannerservice.scanfile:" + path
+ "MimeType:" + mimeType);
}
Bundle args = new bundle ();
Args.putstring ("filepath", path);
Args.putstring ("MimeType", mimetype);
if (listener! = null) {
Args.putibinder ("Listener", Listener.asbinder ());
}
StartService (New Intent (Mediascannerservice.this,
Mediascannerservice.class). Putextras (args));
}
public void Scanfile (string path, string mimeType) {
Requestscanfile (path, mimeType, NULL);
}
};
So the question is: what should we do if we want the system Media Library to parse a specific file in the app?
As can be seen from the above code, Mediascannerservice gives us a binding interface, we only need to pass filepath and a Imediascannerlistener listener, The Media Library will call back the Scancompleted method after parsing to tell us the result of parsing;
The third step: Create Mediascanner object, complete scanning and parsing;
Visible specific scanning, parsing work is not mediascannerservice do, Mediascannerservice is only in the call SACN, Acanfile method when the Mediascanner object was created and handed over to him;
Mediascanner in the Android.media.MediaScanner system framework, there is no discussion here;
Mediascannerservice basically on these content;
3, Mediaprovider:
Mediaprovider is to create a database, to provide a URI to the database to achieve additions and deletions to change the function;
4, Mediathumbrequest:
Audio, image, video files are thumbnails, the thumbnail path is stored in the DB, the real files are stored in the SD card DICM folder, Mediathumbrequest is only provided to Mediaprovider class operations database use.
The main two methods, a new thumbnail method: Execute, an update thumbnail method: Updatedatabase
New skill get: Get thumbnails in app and look forward to the next article;
At this point, mediaprovider structure analysis Clearly, follow-up plan to fill two pieces of article:
Use the System Media Library in the app;
How to realize the scanning and parsing of media files;
See:
- Http://www.linuxidc.com/Linux/2015-03/114754.htm
- Http://www.linuxidc.com/Linux/2015-03/114756.htm
For more information about Android, see the Android feature page http://www.linuxidc.com/topicnews.aspx?tid=11
This article permanently updates the link address : http://www.linuxidc.com/Linux/2015-03/114755.htm
Android Media Library Analysis: Mediaprovider