編輯:關於Android編程
以 root 權限進入 adb shell,使用 sqlite3 打開位於手機上/data/data/com.android.providers.media/databases上的一個數據庫。以 external 開頭的數據庫存儲的是 SD 卡媒體信息,一張卡對應一個,所以如果手機使用過多張卡會有多個數據庫。以 internal 開頭的數據庫存儲手機內部存儲器的媒體信息。因為一般用戶無法訪問手機內部存儲器,而且這兩個數據庫結構是大體上是相同的,所以只需要關注 external 數據庫即可。
Note:數據庫都是以類似 external-ffffffff.db 的形式命名的, 後面的 8 個 16 進制字符是該 SD 卡 FAT 分區的 Volume ID。該 ID 是分區時決定的,只有重新分區或者手動改變才會更改,可以防止插入不同 SD 卡時數據庫沖突。要簡單了解 FAT 文件系統請看Understanding FAT Filesystems
接著在 sqlite3 執行命令 .schema 即可導出創建數據庫的 SQL 語句,也就是數據庫模式,具體如下(單擊展開代碼):
Note: 如果手機沒有 sqlite3 程序,可以搜索編譯過的源代碼的 out 目錄找到可執行文件,大約 90kb,然後 adb push 到手機的 /system/bin/ 目錄。安裝 sqlite3、查詢數據庫均需要 adb root 權限。 Android 的多媒體數據庫主要由表、視圖、索引以及觸發器組成。
接著還需要把數據庫轉換成圖,手工轉換的話就是根據 SQL 語句自行畫圖;推薦懶人使用自動轉換,先使用 adb pull 把數據庫導出,再使用 Power Designer 或者 Visio 的逆向工程(Reverse Engineer)功能生成物理數據模型(Physical Data Model)。注意要連接 sqlite 數據庫文件的話需要先安裝 sqlite 的 ODBC 驅動,教程在這裡:SQLite ODBC Driver
圖片數據庫由兩個表組成,分別是 images 和 thumbnails,物理數據模型如下所示(Power Designer 逆向工程生成)
Note: 如何數據庫物理模型圖:
Note: SQLite 從 3.6.19 版才開始支持外鍵約束,但並沒有使用此特性,而是通過操作數據庫的程序(如 MediaScanner)以及觸發器來維護數據庫的一致性。這裡可以了解 SQLite 的外鍵支持情況
數據表字段解析如下:
images:圖片信息
thumbnails:縮略圖
數據表字段解析如下:
video:視頻信息
videothumbnails:視頻縮略圖
音頻數據庫是最復雜的,由 10 個表組成。物理數據模型如下所示:
album_art:專輯封面
albums:專輯信息
android_metadata:當前字符編碼
artists:藝術家
audio_genres:流派
audio_genres_map:音頻流派映射
Note: 為何要建立映射表:為了消除數據冗余。假如有大量音頻屬於同一流派,如果沒有映射表則需要每個音頻都需要記錄同樣的流派數據,有了映射表之後則只有一條記錄就夠了。這符合數據庫設計的第三范式(the 3rd normal form)
audio_meta:音頻信息
audio_playlists:播放列表
audio_playlists_map:音頻播放列表映射
在 Android 數據庫當中基本上使用自增 id 值作為主鍵,並建立了索引。索引可以加快數據查找速度,但由於需要維護索引所以插入/刪除等寫入操作速度會變慢。索引如下:
1
CREATEINDEXalbum_id_idxonaudio_meta(album_id);
2
CREATEINDEXalbum_idxonalbums(album);
3
CREATEINDEXalbumkey_indexonalbums(album_key);
4
CREATEINDEXartist_id_idxonaudio_meta(artist_id);
5
CREATEINDEXartist_idxonartists(artist);
6
CREATEINDEXartistkey_indexonartists(artist_key);
7
CREATEINDEXimage_bucket_indexONimages(bucket_id, datetaken);
8
CREATEINDEXimage_id_indexonthumbnails(image_id);
9
CREATEINDEXsort_indexonimages(datetakenASC, _idASC);
10
CREATEINDEXtitle_idxonaudio_meta(title);
11
CREATEINDEXtitlekey_indexonaudio_meta(title_key);
12
CREATEINDEXvideo_bucket_indexONvideo(bucket_id, datetaken);
13
CREATEINDEXvideo_id_indexonvideothumbnails(video_id);
由於比較簡單就不解釋了,要深入了解索引可以參考這個關於 SQL Server 的分析MySQL索引背後的數據結構及算法原理,原理應該是差不多的。
視圖類似於表,但並非獨立存在,是從其他表裡面查詢數據得到的。使用視圖可以加快數據庫查詢速度,不用每次都執行復雜的 SQL 語句查詢。圖如下所示:
Note: 如何看視圖:圖下面的部分是數據來源的表,中間是從表中選取的字段,但類似於 COUNT 等 SQL 查詢操作無法在圖上體現,最好還是看實際 SQL 語句。
Note: SQLite 當中視圖都是只讀的,也就是說不能對視圖進行插入、更新、刪除等操作。但是可以在視圖建立INSTEAD OF 觸發器來達到同樣的目的,多媒體數據庫當中的 audio_delete 觸發器就是如此。
觸發器是為了維護數據庫刪除操作而建立的,因為所刪除的表可能與另外的表有關系,需要同時刪除另外一個表的字段。可以看以下一個例子:
1
CREATETRIGGERaudio_meta_cleanup
2
DELETEONaudio_meta
3
BEGIN
4
DELETEFROMaudio_genres_mapWHEREaudio_id = old._id;
5
DELETEFROMaudio_playlists_mapWHEREaudio_id = old._id;
6
END;
這是關於 audio_meta 表的觸發器,意思是當刪除此表上的記錄時,同時刪除 audio_genres_map 表上 audio_id 與此表 id 相同的記錄,刪除 audio_playlists_map 表上 audio_id 與此表 id 相同的記錄。這樣當刪除 audio_meta 表的記錄時,另外兩個表的相應記錄也會自動刪除,不會由於漏刪除而殘留多余數據。
插入、更新主要由 MediaScanner 進行,當刪除/移動媒體文件時 MediaScanner 會掃描磁盤並更新數據庫。數據插入主要在 endFile() 方法中進行,例如插入音頻記錄時相關的表都會插入相應的記錄。而圖片、視頻縮略圖,專輯封面這幾個則是第一次取圖片的時候才會生成縮略圖保存到磁盤,並把 記錄插入到數據庫中。
刪除操作主要由觸發器維護。例如當一個應用刪除圖片時,一般只會刪除圖片數據庫,所以必須要有觸發器同時刪除縮略圖數據庫。
先看看效果圖:首先是布局文件<FrameLayout android:layout_width=match_parent android:layout_margin
第1節 Activity的使用Activity幾乎是每個應用必有的組件,所以任何安卓應用的開發幾乎都是從Activity開始的。比如,你希望設計一個計算器應用,要呈現這個
概要 當手機Modem狀態改變後會將狀態變化信息通知到上層,通過《Android 4.4 Kitkat Phone工作流程淺析(八)__Phone狀態分析》
SlidingDrawer效果想必大家也見到過,它就是1.5模擬器上進入應用程序列表的效果。下面是截圖一、簡介 SlidingDrawer隱藏屏外的內容,並允