Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android開發——MediaProvider源碼分析(1)

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

編輯:Android開發實例

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中有個廣播接收者,代碼如下:

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

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

   1: private void detachVolume(Uri uri) {
   2:        //判斷是否是同一個進程
   3:        if (Process.supportsProcesses() && Binder.getCallingPid() != Process.myPid()) {
   4:            throw new SecurityException(
   5:                    "Opening and closing databases not allowed.");
   6:        }
   7:         //此方法只是操作Sdcard的媒體數據庫,不支持手機內存的媒體數據庫
   8:        String volume = uri.getPathSegments().get(0);
   9:        if (INTERNAL_VOLUME.equals(volume)) {
  10:            throw new UnsupportedOperationException(
  11:                    "Deleting the internal volume is not allowed");
  12:        } else if (!EXTERNAL_VOLUME.equals(volume)) {
  13:            throw new IllegalArgumentException(
  14:                    "There is no volume named " + volume);
  15:        }
  16:  
  17:        synchronized (mDatabases) {
  18:            DatabaseHelper database = mDatabases.get(volume);
  19:            if (database == null) return;
  20:  
  21:            try {
  22:                // touch the database file to show it is most recently used
  23:                File file = new File(database.getReadableDatabase().getPath());
  24:                file.setLastModified(System.currentTimeMillis());
  25:            } catch (SQLException e) {
  26:                Log.e(TAG, "Can't touch database file", e);
  27:            }
  28:             //移除數據庫
  29:            mDatabases.remove(volume);
  30:            database.close();
  31:        }
  32:  
  33:        getContext().getContentResolver().notifyChange(uri, null);
  34:        if (LOCAL_LOGV) Log.v(TAG, "Detached volume: " + volume);
  35:    }

注意移除數據庫並非刪除數據庫文件(*.db),mDatabases是一個HashMap<String,DatabaseHelper>,移除的含義是暫時無法操作,也可以說說是查詢返回的數據都是空的。

2.MediaScannerCursor

一個自定義游標,用來查詢媒體文件的掃描狀態。主要有一個volume字段,用來區分是內置媒體數據庫還是Sdcard的媒體數據庫。

3.MediaScannerReceiver

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

   1: public class MediaScannerReceiver extends BroadcastReceiver
   2: {
   3:     private final static String TAG = "MediaScannerReceiver";
   4:  
   5:     @Override
   6:     public void onReceive(Context context, Intent intent) {
   7:         String action = intent.getAction();
   8:         Uri uri = intent.getData();
   9:         String externalStoragePath = Environment.getExternalStorageDirectory().getPath();
  10:         //系統啟動完畢
  11:         if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
  12:             // scan internal storage
  13:             scan(context, MediaProvider.INTERNAL_VOLUME);
  14:         } else {
  15:             if (uri.getScheme().equals("file")) {
  16:                 // handle intents related to external storage
  17:                 String path = uri.getPath();
  18:                 if (action.equals(Intent.ACTION_MEDIA_MOUNTED/*Sdcard掛載廣播*/) && 
  19:                         externalStoragePath.equals(path)) {
  20:                     scan(context, MediaProvider.EXTERNAL_VOLUME);
  21:                 } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE/*單個文件掃描廣播*/) &&
  22:                         path != null && path.startsWith(externalStoragePath + "/")) {
  23:                     scanFile(context, path);
  24:                 }
  25:             }
  26:         }
  27:     }

掃描分為兩種三種情況:

a,啟動完畢掃面手機內存中的媒體文件

b.sdcard掛載完畢掃描擴展卡的媒體文件

c,掃描單個文件

應用實例:我們可以發送不同的廣播讓系統去掃描媒體文件。當需要掃描單個文件的時候需要設置一些參數,如下:

   1: /**
   2:      * 掃描文件
   3:      * 
   4:      * @param filePath 文件路徑
   5:      * @author http://t.sina.com.cn/halzhang
   6:      */
   7:     public void scanOneFile(final String filePath) {
   8:         Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
   9:         Uri uri = Uri.parse("file://" + filePath);
  10:         intent.setData(uri);
  11:         sendBroadcast(intent);
  12:     }

接著看一下scanscenFile兩個方法:

   1: private void scan(Context context, String volume/*內置卡或者外置卡*/) {
   2:        Bundle args = new Bundle();
   3:        args.putString("volume", volume);
   4:        context.startService(
   5:                new Intent(context, MediaScannerService.class).putExtras(args));
   6:    }    
   7:  
   8:    private void scanFile(Context context, String path/*文件路徑*/) {
   9:        Bundle args = new Bundle();
  10:        args.putString("filepath", path);
  11:        context.startService(
  12:                new Intent(context, MediaScannerService.class).putExtras(args));
  13:    }  

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

關於MediaScannerSerive且聽下回分解。

轉自:http://www.cnblogs.com/halzhang/archive/2011/03/07/1976178.html

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved