音乐播放器是从MediaProvider中获取音乐和音乐信息的,在插入SD卡后,MediaProvider启动扫描服务,文件解析通过opencore操作,扫描到的媒体文件由MediaProvider来保存到数据库,数据库位于
/data/data/com.android.providers.media/databases/external-*.db
在扫描时,扫描到的专辑图片存放于
Android/data/com.android.providers.media/albumthumbs/
专辑图片选用优先选择音乐内嵌专辑图片
如果音乐没有内嵌专辑图片,则在音乐目录下搜索(忽略根目录和下载目录)
0 AlbumArt.jpg
1 AlbumArt*Large.jpg
2 Any other jpg image with 'albumart' anywhere in the name
3 Any other jpg image
4 any other png image
对于扫描的过程,详细可分析文件:
/android-2.2/packages/providers/MediaProvider/src/com/android/providers/media/MediaProvider.java
private ParcelFileDescriptor makeThumbInternal(ThumbData d) ---> getCompressedAlbumArt(getContext(), d.path);
如果音频文件中有专辑图片,用音频里的图片,如果没有,则按如下策略选择图片。
// Extract compressed image data from the audio file itself or, if that fails,
// look for a file "AlbumArt.jpg" in the containing directory.
private static byte[] getCompressedAlbumArt(Context context, String path) {
byte[] compressed = null;
try {
File f = new File(path);
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(f,
ParcelFileDescriptor.MODE_READ_ONLY);
MediaScanner scanner = new MediaScanner(context);
compressed = scanner.extractAlbumArt(pfd.getFileDescriptor());
pfd.close();
// If no embedded art exists, look for a suitable image file in the
// same directory as the media file, except if that directory is
// is the root directory of the sd card or the download directory.
// We look for, in order of preference:
// 0 AlbumArt.jpg
// 1 AlbumArt*Large.jpg
// 2 Any other jpg image with 'albumart' anywhere in the name
// 3 Any other jpg image
// 4 any other png image
if (compressed == null && path != null) {
int lastSlash = path.lastIndexOf('/');
if (lastSlash > 0) {
String artPath = path.substring(0, lastSlash);
String sdroot = Environment.getExternalStorageDirectory().getAbsolutePath();
String dwndir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
String bestmatch = null;
synchronized (sFolderArtMap) {
if (sFolderArtMap.containsKey(artPath)) {
bestmatch = sFolderArtMap.get(artPath);
} else if (!artPath.equalsIgnoreCase(sdroot) &&
!artPath.equalsIgnoreCase(dwndir)) {
File dir = new File(artPath);
String [] entrynames = dir.list();
if (entrynames == null) {
return null;
}
bestmatch = null;
int matchlevel = 1000;
for (int i = entrynames.length - 1; i >=0; i--) {
String entry = entrynames[i].toLowerCase();
if (entry.equals("albumart.jpg")) {
bestmatch = entrynames[i];
break;
} else if (entry.startsWith("albumart")
&& entry.endsWith("large.jpg")
&& matchlevel > 1) {
bestmatch = entrynames[i];
matchlevel = 1;
} else if (entry.contains("albumart")
&& entry.endsWith(".jpg")
&& matchlevel > 2) {
bestmatch = entrynames[i];
matchlevel = 2;
} else if (entry.endsWith(".jpg") && matchlevel > 3) {
bestmatch = entrynames[i];
matchlevel = 3;
} else if (entry.endsWith(".png") && matchlevel > 4) {
bestmatch = entrynames[i];
matchlevel = 4;
}
}
// note that this may insert null if no album art was found
sFolderArtMap.put(artPath, bestmatch);
}
}
if (bestmatch != null) {
File file = new File(artPath, bestmatch);
if (file.exists()) {
compressed = new byte[(int)file.length()];
FileInputStream stream = null;
try {
stream = new FileInputStream(file);
stream.read(compressed);
} catch (IOException ex) {
compressed = null;
} finally {
if (stream != null) {
stream.close();
}
}
}
}
}
}
} catch (IOException e) {
}
return compressed;
}