Android開發——MediaProvider源碼分析(一)

來源:互聯網
上載者:User

MediaProvider包括五個類:

* com.android.providers.media.MediaProvider
* com.android.providers.media.MediaScannerCursor
* com.android.providers.media.MediaScannerReceiver
* com.android.providers.media.MediaScannerService
* com.android.providers.media.MediaThumbRequest

1.MediaProvider

此類繼承ContentProvider,實現一個內容提供者。主要用於建立媒體庫的資料庫表。有自己建立過ContentProvider的同學相信都比較清楚的。

特別說明一下在MediaProvider中有個廣播接收者,代碼如下:

   
 private BroadcastReceiver mUnmountReceiver = new BroadcastReceiver() {          @Override          public void onReceive(Context context, Intent intent) {              if (intent.getAction().equals(Intent.ACTION_MEDIA_EJECT)) {                  // Remove the external volume and then notify all cursors backed by                  // data on that volume                  detachVolume(Uri.parse("content://media/external"));                  sFolderArtMap.clear();                  MiniThumbFile.reset();              }          }      };

此接收者是用來接收Sdcard卸載的廣播。當Sdcard從手機中分離出來的時候,Sdcard中的媒體檔案相對應的資料庫將無法操作。

private void detachVolume(Uri uri) {         //判斷是否是同一個進程         if (Process.supportsProcesses() && Binder.getCallingPid() != Process.myPid()) {             throw new SecurityException(                     "Opening and closing databases not allowed.");         }          //此方法只是操作Sdcard的媒體資料庫,不支援手機記憶體的媒體資料庫         String volume = uri.getPathSegments().get(0);         if (INTERNAL_VOLUME.equals(volume)) {             throw new UnsupportedOperationException(                     "Deleting the internal volume is not allowed");         } else if (!EXTERNAL_VOLUME.equals(volume)) {             throw new IllegalArgumentException(                     "There is no volume named " + volume);         }           synchronized (mDatabases) {             DatabaseHelper database = mDatabases.get(volume);             if (database == null) return;               try {                 // touch the database file to show it is most recently used                 File file = new File(database.getReadableDatabase().getPath());                 file.setLastModified(System.currentTimeMillis());             } catch (SQLException e) {                 Log.e(TAG, "Can't touch database file", e);             }              //移除資料庫             mDatabases.remove(volume);             database.close();         }           getContext().getContentResolver().notifyChange(uri, null);         if (LOCAL_LOGV) Log.v(TAG, "Detached volume: " + volume);     }

注意移除資料庫並非刪除資料庫檔案(*.db),mDatabases是一個HashMap,移除的含義是暫時無法操作,也可以說說是查詢返回的資料都是空的。

2.MediaScannerCursor

一個自訂遊標,用來查詢媒體檔案的掃描狀態。主要有一個volume欄位,用來區分是內建媒體資料庫還是Sdcard的媒體資料庫。

3.MediaScannerReceiver

此類實現廣播接收者。接收到廣播的時候對手機的媒體檔案進行掃描。

 public class MediaScannerReceiver extends BroadcastReceiver  {      private final static String TAG = "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/*Sdcard掛載廣播*/) &&                           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);                  }              }          }      }

掃描分為兩種三種情況:

a,啟動完畢掃面手機記憶體中的媒體檔案

b.sdcard掛載完畢掃描擴充卡的媒體檔案

c,掃描單個檔案

應用執行個體:我們可以發送不同的廣播讓系統去掃描媒體檔案。當需要掃描單個檔案的時候需要設定一些參數,如下:

/**       * 掃描檔案       *        * @param filePath 檔案路徑       * @author http://t.sina.com.cn/halzhang       */      public void scanOneFile(final String filePath) {          Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);          Uri uri = Uri.parse("file://" + filePath);          intent.setData(uri);          sendBroadcast(intent);      }
/**                     * update by Peng on 2011-10-18                     */                    //send a broadcast to mediascanner so that the music player can get the latest playlist                    if(mContext!=null){                    Intent intent=new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);                    Uri uri=Uri.parse("file:///mnt"+destFile.getAbsolutePath());                    intent.setData(uri);                    mContext.sendBroadcast(intent);                    }//或者 context.sendBroadcast(new Intent(                            Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + path)));//其中的path為絕對路徑,如:/mnt/sdcard/filename。

接著看一下scan和scenFile兩個方法:

   
 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));     }

兩個方法都是啟動MediaScannerService去掃描媒體檔案的。

關於MediaScannerSerive且聽下回分解。

相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。