對Android稍有熟悉的人都知道,Android Media Scanner只對SD卡上的媒體檔案進行掃描。其掃描的策略,請參考《Android Media Scanner Process
》。假如我們的硬體平台上面沒有提供SD卡槽,難道Android就不能進行對媒體檔案播放了嗎?當然不是的,否則Android系統將不會成為一個完善的Framework。本文結合本人的經驗介紹一下,怎樣修改多媒體檔案的掃描路徑。
根據《Android Media Scanner Process
》的介紹我們可以知道,Android scanner掃描媒體完成之後,會把媒體檔案存放在資料庫中,由MediaProvider為上層的應用程式提供服務。
經過研究Media scanner的代碼發現,他的掃描路徑為android.os.Environment.EXTERNAL_STORAGE_DIRECTORY。定義該變數檔案位於:
frameworks/base/core/java/android/os/Environment.java
預設情況下,Android將會搜尋/sddisk目錄:
private static final File EXTERNAL_STORAGE_DIRECTORY = getDirectory("EXTERNAL_STORAGE", "/sddisk");
為了讓其進行搜尋我們自訂的路徑,可以修改該變數的定義,加入我們希望掃描/external目錄。代碼修改如下:
private static final File EXTERNAL_STORAGE_DIRECTORY = getDirectory("EXTERNAL_STORAGE", "/external");
這樣Android Media Scanner將會搜尋/external目錄來尋找媒體檔案。
下一步我們需要保證這個檔案一定要存在,我們需要修改init.rc檔案。增加如下的定義:
mkdir /external 0777 system system
這樣在開機的時候,如果/external目錄不存在,則會建立一個。如果已經存在,則不會有任何動作。
另外怎樣觸發Media Scanner?根據《Android Media Scanner Process
》
的介紹,當收到
ACTION_BOOT_COMPLETED,ACTION_MEDIA_MOUNTED,ACTION_MEDIA_SCANNER_SCAN_FILE
訊息的時候才會進行掃描。以前是掃描SD卡,當SD卡mount的時候Android系統會有ACTION_MEDIA_MOUNTED訊息通
知,Media Scanner開始掃描媒體檔案。但是我們的/external目錄修改之後,怎樣通知Android media
scanner掃描呢?一個辦法是重啟,沒有人樂意這樣做。另外一個辦法是運行menu->dev tools->Media
Scan,這樣將會進行掃描。目前我還沒有讓目錄修改之後,自動掃描的辦法。如果你有好的點子,請你給我留言。
通過以上的步驟,可以在Android的/external目錄存放媒體檔案,並且被music應用程式播放了。當然還有不完善的地方歡迎各位朋友指正。
補充(於2010-9-20)
研究為什麼Android系統會自動調用MediaScaner掃描檔案呢?研究MediaScannerReceiver的源碼發現:
@Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Uri uri = intent.getData(); String externalStoragePath = Environment.getExternalStorageDirectory().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) && 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); } } } }
我們發現在收到ACTION_BOOT_COMPLETED訊息時,Android系統會掃描記憶體中的媒體檔案。當系統收到ACTION_MEDIA_MOUNTED才會去掃描系統中的擴充記憶體(一般是SD卡)。
假如系統中有SD卡的話,系統啟動的時候是可以收到ACTION_MEDIA_MOUNTED訊息和ACTION_BOOT_COMPLETED訊息的,
這樣開機的時候系統會對系統進行媒體檔案掃描。當SD卡檔案修改了(比如用資料線,串連PC),一般也是有ACTION_MEDIA_MOUNTED訊息
上報的。這樣也可以即時更新媒體資料。
但是我們上面沒有真正的SD卡,而是把一個記憶體中的目錄設定為擴充記憶體。那麼我們將永遠不會受到ACTION_MEDIA_MOUNTED訊息,所以也不
會自動掃描外儲存記憶體中的媒體檔案。那麼你可能會問:為什麼運行menu->dev tools->Media
Scan就可以掃描外儲存記憶體中的資料呢?這段代碼的實現,在檔案Development/src/com/android/development
/MediaScannerActivity.java中:
@Override public void onResume() { super.onResume(); ........ sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()))); ........ }
可以看出這裡面廣播了一個ACTION_MEDIA_MOUNTED訊息,這樣MediaScannerReceiver將會掃描外儲存記憶體中的媒體檔案。