Android Media Scanner Mechanism Analyze
来源:互联网 发布:不会聊天 知乎 编辑:程序博客网 时间:2024/05/22 07:59
转载自:http://blog.csdn.net/qikaibinglan/article/details/6126449
Architecture
Figure 2-1
As Figure 2-1. MediaScannerReciver start up at anytime where receive intent ACTION_BOOT_COMPLETED, ACTION_MEDIA_MOUNTED or ACTION_MEDIA_SCANNER_SCAN_FILE. Cause on that spend long time to process the media metadata, so that MediaScannerReceiver will call up MediaScannerService.
MediaScannerService invoke a public class which named MediaScanner to do the scan work, MediaScanner handle the media database with a public class which named MediaProvider
MediaScannerReciver support two types of the folder:
1.internal volume, point to $(ANDROID_ROOT)/media.
2.External volume, point $(EXTERNAL_STORAGE).
Scanner Action
ACTION_BOOT_COMPLETED
public static final String ACTION_BOOT_COMPLETED
Broadcast Action: This is broadcast once, after the system has finished booting. It can be used to perform application-specific initialization, such as installing alarms. You must hold theRECEIVE_BOOT_COMPLETED permission in order to receive this broadcast.
This is a protected intent that can only be sent by the system.
Constant Value: "android.intent.action.BOOT_COMPLETED"
ACTION_MEDIA_MOUNTED
public static final String ACTION_MEDIA_MOUNTED
Broadcast Action: External media is present and mounted at its mount point. The path to the mount point for the removed media is contained in the Intent.mData field. The Intent contains an extra with name "read-only" and Boolean value to indicate if the media was mounted read only.
Constant Value: "android.intent.action.MEDIA_MOUNTED"
ACTION_MEDIA_SCANNER_SCAN_FILE.
public static final String ACTION_MEDIA_SCANNER_SCAN_FILE
Broadcast Action: Request the media scanner to scan a file and add it to the media database. The path to the file is contained in the Intent.mData field.
Constant Value: "android.intent.action.MEDIA_SCANNER_SCAN_FILE"
Android Media Scanner Receiver
We can find the source file with path anydroid/packages/providers/MediaProvider/src/com/android/providers/media/MediaScannerReceiver.java
public class MediaScannerReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent) {
......
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) &&
externalStoragePath.equals(path)) {
scan(context, MediaProvider.EXTERNAL_VOLUME);
} else if (action.equals(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE) &&
path != null && path.startsWith(externalStoragePath + "/")) {
scanFile(context, path);
}
}
}
}
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();
args.putString("filepath", path);
context.startService(
new Intent(context, MediaScannerService.class).putExtras(args));
}
}
Figure 4-1
As the source codes, and Figure 4-1, there are two different media database in the system, one is the internal storage , the other is the external storage. Finally, they call the method startService() to start the MediaScannerService.
Android Media Scanner Service
We can find the source file with path /android/packages/providers/MediaProvider/src/com/android/providers/media/MediaScannerService.java .
public void onCreate()
{
......
Thread thr = new Thread(null, this, "MediaScannerService");
thr.start();
}
public int onStartCommand(Intent intent, int flags, int startId)
{
......
Message msg = mServiceHandler.obtainMessage();
......
mServiceHandler.sendMessage(msg); return Service.START_REDELIVER_INTENT;
}
public void run()
{
......
mServiceHandler = new ServiceHandler();
......
}
private final class ServiceHandler extends Handler
{
......
@Override
public void handleMessage(Message msg)
{
......
if (filePath != null) {
......
Uri uri = scanFile(filePath, arguments.getString("mimetype"));
......
}
else {
......
scan(directories, volume);
......
}
}
}
private void scan(String[] directories, String volumeName) {
......
MediaScanner scanner = createMediaScanner();
scanner.scanDirectories(directories, volumeName);
......
}
private Uri scanFile(String path, String mimeType) {
......
MediaScanner scanner = createMediaScanner();
return scanner.scanSingleFile(path, volumeName, mimeType);
}
Figure 5-1
Android application maybe block with invoking service, generic create a thread to run at the backend. First, media service call onCreate() to start the service if it is not exist, then create a thread and run thread.start() to call the runnable method which has implemented with the run(). In the run(), invoke a internal class named ServiceHandler to scan file. In the method scan() and scanFile(), they all invoke a public class named MediaScanner whom has method named createMediaScanner() to process metadata and media dabase.
Android Media Scanner
We can find the relate files with path android/frameworks/base/media/java/android/media,
Figure 6-1
java codes
file://android/frameworks/base/media/java/android/media/MediaScanner.java
public void scanDirectories(String[] directories, String volumeName) {
......
for (int i = 0; i < directories.length; i++) {
processDirectory(directories[i], MediaFile.sFileExtensions, mClient);
}
......
}
}
public void scanFile(String path, long lastModified, long fileSize) {
// This is the callback funtion from native codes.
// Log.v(TAG, "scanFile: "+path);
doScanFile(path, null, lastModified, fileSize, false);
}
public void scanFile(String path, String mimeType, long lastModified, long fileSize) {
doScanFile(path, mimeType, lastModified, fileSize, false);
}
public Uri doScanFile(String path, String mimeType, long lastModified, long fileSize, boolean scanAlways) {
......
if( isMetadataSupported(mFileType) ) {
processFile(path, mimeType, this);
} else if (MediaFile.isImageFileType(mFileType)) {
// we used to compute the width and height but it's not worth it
}
result = endFile(entry, ringtones, notifications, alarms, music, podcasts);
......
}
private Uri endFile(FileCacheEntry entry, boolean ringtones, boolean notifications,
boolean alarms, boolean music, boolean podcasts)
throws RemoteException {
......
mMediaProvider.insert(...) // mMediaProvider.update(...)
......
}
private native void processDirectory(String path, String extensions, MediaScannerClient client);
private native void processFile(String path, String mimeType, MediaScannerClient client);
c++ codes
file://android/frameworks/base/media/jni/android_media_MediaScanner.cpp
static void
android_media_MediaScanner_processDirectory(JNIEnv *env, jobject thiz, jstring path, jstring extensions, jobject client)
{
MediaScanner *mp = (MediaScanner *)env->GetIntField(thiz, fields.context);
......
MyMediaScannerClient myClient(env, client);
mp->processDirectory(pathStr, extensionsStr, myClient, ExceptionCheck, env);
......
}
static void
android_media_MediaScanner_processFile(JNIEnv *env, jobject thiz, jstring path, jstring mimeType, jobject client)
{
MediaScanner *mp = (MediaScanner *)env->GetIntField(thiz, fields.context); ......
MyMediaScannerClient myClient(env, client);
mp->processFile(pathStr, mimeTypeStr, myClient);
......
}
file://android/external/opencore/android/mediascanner.cpp
status_t MediaScanner::processDirectory(const char *path, const char* extensions,
MediaScannerClient& client, ExceptionCheck exceptionCheck, void* exceptionEnv)
{
......
result = doProcessDirectory(pathBuffer, pathRemaining, extensions, client, exceptionCheck, exceptionEnv);
......
}
status_t MediaScanner::doProcessDirectory(char *path, int pathRemaining, const char* extensions,
MediaScannerClient& client, ExceptionCheck exceptionCheck, void* exceptionEnv)
{
......
client.scanFile(path, statbuf.st_mtime, statbuf.st_size);
......
}
status_t MediaScanner::processFile(const char *path, const char* mimeType, MediaScannerClient& client)
{
status_t result = PVMFSuccess;
int error = 0;
InitializeForThread();
OSCL_TRY(error,
client.setLocale(mLocale);
client.beginFile();
//LOGD("processFile %s mimeType: %s/n", path, mimeType);
const char* extension = strrchr(path, '.');
if (extension &&
(strcasecmp(extension, ".mp3") == 0 || strcasecmp(extension, ".aac") == 0)) {
// Both mp3 and aac files use ID3 tags to hold metadata
result = parseID3Tag(path, client);
} else if (extension &&
(strcasecmp(extension, ".mp4") == 0 || strcasecmp(extension, ".m4a") == 0 ||
strcasecmp(extension, ".3gp") == 0 || strcasecmp(extension, ".3gpp") == 0 ||
strcasecmp(extension, ".3g2") == 0 || strcasecmp(extension, ".m4b") == 0 ||
strcasecmp(extension, ".3gpp2") == 0)) {
result = parseMP4(path, client);
} else if (extension && strcasecmp(extension, ".ogg") == 0) {
result = parseOgg(path, client);
} else if (extension &&
(strcasecmp(extension, ".mid") == 0 || strcasecmp(extension, ".smf") == 0 ||
strcasecmp(extension, ".imy") == 0)) {
result = parseMidi(path, client);
} else if (extension &&
(strcasecmp(extension, ".wma") == 0 || strcasecmp(extension, ".wmv") == 0 ||
strcasecmp(extension, ".asf") == 0 || strcasecmp(extension, ".amr") == 0 ||
strcasecmp(extension, ".wav") == 0 || strcasecmp(extension, ".awb") == 0)) {
result = parseASF(path, client);
} else {
result = PVMFFailure;
}
client.endFile();
);
OSCL_FIRST_CATCH_ANY( error,LOGV("OSCL_LEAVE happened in processFile Exit with failure");return PVMFFailure);
return result;
}
As Figure 6-1, If scanDirectory() has called by MediaScannerService, it will invoke c++ llibrary libmedia_jni method processDiretorys() by JNI mechanism, then processDiretorys() invoke JAVA class MyMediaScannerClient by JNI, Finaly, endFile() use to insert or update the database.
- Android Media Scanner Mechanism Analyze
- Android Media Scanner Mechanism Analyze
- Android Media Scanner Mechanism Analyze
- Android Media Scanner Process
- 修改Android Media Scanner的扫描路径
- 修改Android Media Scanner的扫描路径
- 修改Android Media Scanner的扫描路径
- 修改Android Media Scanner的扫描路径
- Android Media Scanner工作流程及原理
- Android Media Scanner工作流程及原理
- 修改Android Media Scanner的扫描路径
- Android Media Scanner工作流程及原理
- Android Media Scanner工作流程及原理
- 基于Bluetooth AVRCP Input Device分析Android Media Button Mechanism
- Android 多媒体扫描过程(Android Media Scanner Process)
- Android 多媒体扫描过程(Android Media Scanner Process)
- Android多媒体扫描过程(Android Media Scanner Prosess)
- android 多媒体扫描过程(Android Media Scanner Process)
- 传微信300元/年今日全面开放接口,企业能用它们来做啥?
- 深入探讨在集群环境中使用 EhCache 缓存系统
- 从EXCEL导出数据到XML
- 如何对PNG进行压缩?PNG24压缩方法
- Cocos2d-x+Plugin-X插件集成指南 cocos2d-x 2.13
- Android Media Scanner Mechanism Analyze
- 计算机视觉、机器学习相关领域论文和源代码
- 想要做好职业规划,先认清自我
- AllJoyn的优势
- 如何将普通jar报转为osgi
- Java实现链表
- Java 技术,IBM 风格: 类共享
- string 中find_last_of的索引是字符串最后的字符,不是开始的字符的位置,记录一下
- vs开发工具常见错误总结