天天看點

Android 流媒體系列(一)Android   設定鈴聲分析  

代碼其實沒有幾行,這裡簡單記錄下學習的過程.

Android系統啟動時會掃描系統與SD卡中的對媒體檔案,分别存入資料庫sqlite中,以contentProvider的形式對外提供服務

路徑:/data/data/com.android.providers.media/databases/XXX...

Android 流媒體系列(一)Android   設定鈴聲分析  

可以看到有2個db檔案, 一個是系統的,一個是sd卡裡的

用SQLite Expert打開internal.db,部分截圖如下:

Android 流媒體系列(一)Android   設定鈴聲分析  

這裡面記錄了音頻audio、視訊video、圖檔images的相關資料資訊,我們以音頻audio為例,藍色部分audio_meta就是audio資料表,打開之後就可以看到詳細資訊了,裡面列出了系統内部的所有音頻檔案,各個字段在android.provider.MediaStore中都定義有相應的常量,如id --- MediaStore.Audio.Media._ID.

而這裡面有想說下這四個字段

Android 流媒體系列(一)Android   設定鈴聲分析  

含義在源碼裡都有說明,看了一遍資料,發現這四個字段同時有且僅有一個字段為1,也就是對于一個多媒體檔案隻能是這四種中的一種,預設為0,如果是某種類型,則android系統預設置為1,是以也就明白了為什麼很多掃描系統通知或者來電鈴聲的示例代碼中,都會有一個類似的條件語句:is_notification = 1.

如:

Android 流媒體系列(一)Android   設定鈴聲分析  
Android 流媒體系列(一)Android   設定鈴聲分析  

這裡 is_notification != 0,效果是一樣的,除非哪天google再定義個2, 3 ......

上面扯了些其他的,關于設定鈴聲的方法,系統提供了一個鈴聲管理器android.provider.RingtoneManager,其中提供了擷取與設定鈴聲的API

如:Uri uri = RingtoneManager.getActualDefaultRingtoneUri(MediaActivity.this, RingtoneManager.TYPE_NOTIFICATION);可以擷取到目前系統的通知鈴聲uri

第二個參數可以指定擷取的鈴聲類型,還有其他的TYPE_RINGTONE,TYPE_ALARM, TYPE_ALL

設定鈴聲的API:

第二個參數同上,最後一個是指定一個新的Uri, 這裡的data.get(position)就是在上面的掃描代碼掃描出的所有通知鈴聲path路徑中選澤一個,然後在解析成一個URI對象傳入即可

那麼android是如何擷取指定類型的系統鈴聲呢?

這涉及到另一個類android.provider.Settings

相關源碼如下:

Android 流媒體系列(一)Android   設定鈴聲分析  
Android 流媒體系列(一)Android   設定鈴聲分析  
Android 流媒體系列(一)Android   設定鈴聲分析  
Android 流媒體系列(一)Android   設定鈴聲分析  
Android 流媒體系列(一)Android   設定鈴聲分析  
Android 流媒體系列(一)Android   設定鈴聲分析  

settings.db結構如下:

Android 流媒體系列(一)Android   設定鈴聲分析  

上面示例中指定的TYPE_NOTIFICATION的資料如下(藍色部分):

Android 流媒體系列(一)Android   設定鈴聲分析  

最後傳回的就是file:///..........這個String資料,再轉化成URI傳回給調用者

OK,那麼設定鈴聲的API, setAc.......執行的過程也類似:

Android 流媒體系列(一)Android   設定鈴聲分析  
Android 流媒體系列(一)Android   設定鈴聲分析  
Android 流媒體系列(一)Android   設定鈴聲分析  
Android 流媒體系列(一)Android   設定鈴聲分析  

最後總結下,從整個過程可以看到android系統的一些設計思想

1,設定鈴聲之前,要先知道有哪些系統鈴聲,是以需要掃描,android提供了xxx.media這個contentProvider為此服務,對應的資料庫為internal.db/external-xx.db

2,拿到鈴聲,真正需要設定的時候,提供了Setting類管理這個過程,其對應的資料庫為settings.db

  2.1 首先檢查是否涉及到系統的一些安全設定參數,這裡定義了Secure類來管理,如果涉及到系統安全,那麼又分為兩種情況:

    2.1.1 如果是查詢,則操作secure 表查詢

    2.1.2 如果是寫操作,則直接return

  2.2 不涉及到系統安全,就屬于正常設定,接着定義了System類管理

3,查詢操作的實際操作類NameValueCache, 其中定義了

  緩存name/value鍵值對的集合,避免每次操作都去操作資料庫

  可以由調用者指定的uri,便于根據uri決定去操作哪張表

以及寫操作的NameValueTable類,因為寫操作涉及到id, 是以繼承了BaseColumns類

=========================================

=========================================以下是轉載附帶參考:

今天給大家講android的多媒體資料庫。MediaStore這個類是android系統提供的一個多媒體資料庫,android中多媒體資訊都可以從這裡提取。這個MediaStore包括了多媒體資料庫的所有資訊,包括音頻,視訊和圖像,android把所有的多媒體資料庫接口進行了封裝,所有的資料庫不用自己進行建立,直接調用利用ContentResolver去掉用那些封裝好的接口就可以進行資料庫的操作了。今天我就介紹一些這些接口的用法。 

    首先,要得到一個ContentResolver執行個體,ContentResolver可以這樣擷取,利用一個Activity或者Service的Context即可。如下所示: 

    ContentResolver mResolver = ctx.getContentResolver(); 

    上面的那個ctx的就是一個context,Activity.this就是那個Context,這個Context就相當于一個上下文環境。得到這個Context後就可以調用getContentResolver接口擷取ContentResolver執行個體了。ContentResolver執行個體獲得後,就可以進行各種查詢,下面我就以音頻資料庫為例講解增删改查的方法,視訊和圖像和音頻非常類似。 

    在講解各種查詢之前,我給大家介紹下怎麼看android都提供了哪些多媒體表。在adb shell中,找到/data/data/com.android.providers.media/databases/下,然後找到SD卡的資料庫檔案(一般是一個.db檔案),然後輸入指令sqlite3加上這個資料庫的名字就可以查詢android的多媒體資料庫了。.table指令可以列出所有多媒體資料庫的表,.scheme加上表名可以查詢表中的所有列名。這裡可以利用SQL語句來檢視你想要的資料,記得最後一定要記住每條語句後面都加上分号。下面開始講述怎麼在這些表上進行增删改查。 

    查詢,代碼如下所示: 

    Cursor cursor = resolver.query(_uri, prjs, selections, selectArgs, order); 

    ContentResolver的query方法接受幾個參數,參數意義如下: 

    Uri:這個Uri代表要查詢的資料庫名稱加上表的名稱。這個Uri一般都直接從MediaStore裡取得,例如我要取所有歌的資訊,就必須利用MediaStore.Audio.Media. EXTERNAL _CONTENT_URI這個Uri。專輯資訊要利用MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI這個Uri來查詢,其他查詢也都類似。 

    Prjs:這個參數代表要從表中選擇的列,用一個String數組來表示。 

     Selections:相當于SQL語句中的where子句,就是代表你的查詢條件。 

    selectArgs:這個參數是說你的Selections裡有?這個符号是,這裡可以以實際值代替這個問号。如果Selections這個沒有?的話,那麼這個String數組可以為null。 

     Order:說明查詢結果按什麼來排序。 

    上面就是各個參數的意義,它傳回的查詢結果一個Cursor,這個Cursor就相當于資料庫查詢的中Result,用法和它差不多。 

------------------------------------------------------------------------------------------------------------------- 

    增加,代碼如下是以: 

    ContentValues values = new ContentValues(); 

    values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER,0); 

    resolver.insert(_uri, values); 

    這個insert傳遞的參數隻有兩個,一個是Uri(同查詢那個Uri),另一個是ContentValues。這個ContentValuses對應于資料庫的一行資料,隻要用put方法把每個列的設定好之後,直接利用insert方法去插入就好了。 

    更新,代碼如下: 

    ContentResolver resolver = ctx.getContentResolver(); 

    Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 

    values.put(MediaStore.Audio.Media.DATE_MODIFIED, sid); 

    resolver.update(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,values, where, selectionArgs); 

    上面update方法和查詢還有增加裡的參數都很類似,這裡就不再重複叙述了,大家也可直接參考google的文檔,那裡也寫的很清楚。 

    删除,代碼如下: 

    nbsp;   resolver.delete(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,where, selectionArgs); 

    delete和更新的方法很類似 。