實現手機來電鈴聲,通知鈴聲、警告鈴聲等音頻定製化功能(一,添加掃描分區myimage)

來源:互聯網
上載者:User

標籤:android   style   io   ar   color   sp   java   檔案   on   

需求功能說明:    該定製需求在各個國家民族差異化為背景下產生的,要求在系統中增加一個新的分區如myimage,用以實現存放定製資源,以符合不同國家民族的使用者的體驗。例如在myimage下建立media檔案夾用於存放定製的音頻資源,如果系統myimage分區下,media目錄下存在相關目錄或檔案,則系統摒棄系統重名預設資源,優先選擇該分區下的定製資源。
注!
    本篇博文結合從系統啟動完成之後系統對多媒體檔案的掃描流程進行分析和修改。修改思路為:優先掃描定製分區西下定製音頻資源並將掃描結果插入相對應的資料庫中。若定製分區下不存在資來源目錄或檔案,則將系統預設資源的掃描結果插入相對應的資料庫,若定製資源檔名與系統資源檔名相同,則優先插入定製資源。
參考代碼:Android4.1.2_r21.當系統啟動完成,MediaScannerReceiver接收到系統啟動完成的廣播,並調用scan()方法對內建存放裝置進行掃描。相關類:MediaScannerReceiver.java是一個BroadcastReceiver,接收廣播,進行媒體掃描,是MediaScanner提供的介面,主要負責接收廣播並啟動MediaScannerService具體執行掃描工作。方法調用流程:onReceiver()-->scan()-->scanDirectories()具體代碼如下:public voidonReceive(Context context, Intent intent) {......   if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {//接收到系統啟動完成的廣播
        // 掃描內部存放裝置,INTERNAL_VOLUME的值為"internal"
        scan(context, MediaProvider.INTERNAL_VOLUME);
    }......}private voidscan(Context context, String volume) {
         Bundle args = new Bundle();
         args.putString("volume", volume);        //通過startService()啟動服務開始內部Media檔案掃描,這裡的參數volume的值為”internal”。
         context.startService(new Intent(context, MediaScannerService.class).putExtras(args));
}2.MediaScannerService服務被啟動,主要負責媒體掃描。詳細來說MediaScannerService用於接收系統重啟後、插拔SD卡、檔案複製與拷貝等訊息,收到訊息後會啟動一個handler去處理訊息並掃描,最後會將掃描結果放到MediaProvider提供的資料庫中去。這裡我們先從onCreate生命週期函數開始分析。主要方法如下:handleMessage()-->scan()
public voidonCreate(){     PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);    //掃描期間保持螢幕常亮
    mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
    ......    //啟動一個背景工作執行緒來處理大量的計算任務,由於MediaScannerService實現了Runnable,因此大量計算的任務都是在Runnable的run()方法中來執行的。
    Thread thr = new Thread(null, this, "MediaScannerService");
     thr.start();    ......}//在Runnable.run()中執行訊息迴圈,把通過Handler發送過來的訊息在背景工作執行緒中執行。public voidrun(){         Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND + Process.THREAD_PRIORITY_LESS_FAVORABLE);
         Looper.prepare();
         mServiceLooper = Looper.myLooper();
         mServiceHandler = new ServiceHandler();
         Looper.loop();
     }//Service對象在被啟動的時候,onStartCommand()會被調用。public intonStartCommand(Intent intent, int flags, int startId){
        ....
         Message msg = mServiceHandler.obtainMessage();
         msg.arg1 = startId;
         msg.obj = intent.getExtras();
         mServiceHandler.sendMessage(msg);
         return Service.START_REDELIVER_INTENT;
}private final classServiceHandlerextends Handler
     {
         @Override
         public void handleMessage(Message msg){            ......
             Bundle arguments = (Bundle) msg.obj;
             String filePath = arguments.getString("filepath");
                     String volume = arguments.getString("volume");
                     String[] directories = null;                    //根據前文我們知道這裡的形參volume的值是“internal”,因此這裡會預設掃描"system/media"路徑。
                    if (MediaProvider.INTERNAL_VOLUME.equals(volume)) {
                         directories = new String[] {
                                 Environment.getRootDirectory() + "/media",                                 //註:根據需求這裡我們新增加了一個新的分區如myimage用來存放我們需要定製的資源,因此在這裡我們在對內部進行掃描的時候增加一個掃描路徑,也就是“myimage/media”。
                                 "myimage/media"
                        };
                     }                    if (directories != null) {
                        ......
                         scan(directories, volume);
                         ......
                     }
        ......}//從 getContentResolver獲得一個ContentResover,然後直接插入根據AIDL,這個ContentResover的另一端是MediaProvider。這裡主要獲得了一個掃描URI。private voidscan(String[] directories, String volumeName) {
         ContentValues values = new ContentValues();
         values.put(MediaStore.MEDIA_SCANNER_VOLUME, volumeName);
         Uri scanUri = getContentResolver().insert(MediaStore.getMediaScannerUri(), values);        //這裡不做任何修改以保持原有的資料庫結構不發生變化。
         Uri uri = Uri.parse("file://" + directories[0]);        //發送開始掃描的通知
         sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_STARTED, uri));
         try {
             if (volumeName.equals(MediaProvider.EXTERNAL_VOLUME)) {
                 openDatabase(volumeName);
             }
             MediaScanner scanner = createMediaScanner();            //掃描目錄
             scanner.scanDirectories(directories, volumeName);
         } catch (Exception e) {
             Log.e(TAG, "exception in MediaScanner.scan()", e);
         }         //刪除掃描路徑,以示掃描結束(這裡由於時間問題不做驗證,大概也就是會有地方捕捉該刪除動作,並發出廣播,以通知掃描結束)
         getContentResolver().delete(scanUri, null, null);
         sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_FINISHED, uri));
         mWakeLock.release();}

實現手機來電鈴聲,通知鈴聲、警告鈴聲等音頻定製化功能(一,添加掃描分區myimage)

聯繫我們

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

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

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.