MediaProvider相當於一個數據中心,SD卡上所有的數據在這裏都有記錄,而Gallery的什用就是展示和操作這個數據中心,每次用戶啓動Gallery時,Gallery只是讀取MediaProvider裏面的記錄並顯示用戶。如果用戶在Gallery裏刪除一個媒體時,Gallery通過調用MediaProvider開放的接口來實現。
MediaProvider和Gallery的大致關係就是這樣的了。我現在碰到的問題要解決的話,必須要搞清楚一件事才能繼續往下走:
因爲Gallery啓動時是不會給MediaProvider發送命令讓它掃描全盤的。那麼,當SD卡上的數據有更新時(比如通過藍牙接收一個媒體、從網上下載一個媒體、刪除一個媒體等操作),MediaProvider如何知道這些變化然後更新自己的數據庫的呢?
在這裏不考慮用戶通過PC上的USB傳輸到SD卡上的問題。因爲SD卡重新掛載時,MediaProvider會自動掃描SD卡上的媒體來更新媒體數據庫的。
那麼只有一個答案了,誰更新了SD卡上的媒體,誰通知MediaProvider把更新了的媒體同步到MediaProvider的媒體數據庫中。有兩種方式,恰好藍牙和下載器分別使用了這兩種方式,這裏就以它們兩個程序來說明一下。
1、MediaScannerConnection,藍牙傳輸文件時就是用的這種方式,每當接收到新的媒體文件,都會通過這種方式告訴MediaProvider同步媒體數據庫。
建立連接
mConnection = new MediaScannerConnection(mContext, this);
因爲建立連接是一個異步過程,所以,在建立連接時需要加入一個監聽器。這樣,連接建立後就可以得到通知,並進行下一步。
更新媒體數據庫
mConnection.scanFile(mInfo.mFilename, mInfo.mMimetype);
這也是一個異步過程,更新完畢後,監聽器中得到通知,並斷開連接。
斷開連接
mConnection.disconnect();
詳細代碼參考/packages/apps/Bluetooth下面BluetoothOppService.java中的MediaScannerNotifier這個類。
2、MediaScannerService,下載器DownloadProvider就是用的這種方式,當一個媒體文件下載完成後,直接綁定到MediaScannerService上,並調用mMediaScannerService.scanFile(info.mFileName, info.mMimeType);
這種方式比起上面的方式來,有兩個缺點:
1、無法設置監聽器。
2、scanFile本身是同步方法,掃描完成後纔會返回,因此需要自己開一個新的線程來調用。
詳細代碼可以參考/packages/providers/DownloadProvider中DownloadService.java
任何一個應用程序,如果會更新SD卡上的媒體的話,都要記得使用上面兩種方式中的一種來通知MediaProvider更新數據庫。否則的話,用戶打開Gallery是看不到我們的更新的。