解剖Android聯繫人之一,基於2.1

摘要:最近要做個聯繫人相關的東西,所以需要研究研究Android的聯繫人數據結構比較不同,看起來比較混亂,作爲新手來講的我。但還是得上啊,因爲就我一個人先看了幾天的API,References,源碼之類的(當然不是時時在看,這會兒翻翻,那會兒看看),比較迷糊,也有點理解,理解最多的就是他不是常理中想像的那樣。說到聯繫人,有個類不得不說,那就是ContactsContract,我是基於2.1看的,這個類有5000多行,也夠多的說實話,Android裏面內部類,回調這些玩意用的太多了。。
標籤:android

最近要做個聯繫人相關的東西,所以需要研究研究

Android的聯繫人數據結構比較不同,看起來比較混亂,作爲新手來講的我。

但還是得上啊,因爲就我一個人

先看了幾天的API,References,源碼之類的(當然不是時時在看,這會兒翻翻,那會兒看看),比較迷糊,也有點理解,理解最多的就是他不是常理中想像的那樣。

說到聯繫人,有個類不得不說,那就是ContactsContract,我是基於2.1看的,這個類有5000多行,也夠多的

說實話,Android裏面內部類,回調這些玩意用的太多了。。。

當然說了這麼多的時候我還是不清楚聯繫人的結構

記得某位大神說的,理論不懂就實踐,實踐不懂就理論,我也比較喜歡這樣,但我啥時候才能成爲大神呢,至少是個小神吧

於是我開始實踐,準備從數據庫下手,它裏面的數據最終是存在sqlite裏面的,於是就要把這個數據庫導出來瞧瞧

我開始想把我的Android Phone裏的聯繫人給導出來,裏面有些聯繫人的數據,或許可以用來分析,看下

但因爲找不到數據線,就此作罷

於是開始導模擬器中的庫,裏面也是有數據的,是我測試的時候放進去的

位置位於/data/data/com.android.providers.contacts/databases/contacts2.db
不管是用命令adb pull,還是DDMS中的File Explorer都是可以導出到宿主機的
可能有些人上面這個文件的位置不一樣,具體翻翻就知道他在哪了
然後就是sqlite3命令了
看客們不要高興太早,我連自己都沒有把握,接下來會是什麼樣子,我只是把這一個過程記錄下來

$ sqlite3 contacts2.db
SQLite version 3.6.22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>
看到有.help命令,當然第一個就是輸入他了

sqlite> .help
.backup ?DB? FILE      Backup DB (default "main") to FILE
.bail ON|OFF           Stop after hitting an error.  Default OFF
.databases             List names and files of attached databases
.dump ?TABLE? ...      Dump the database in an SQL text format
                         If TABLE specified, only dump tables matching
                         LIKE pattern TABLE.
.echo ON|OFF           Turn command echo on or off
.exit                  Exit this program
.explain ?ON|OFF?      Turn output mode suitable for EXPLAIN on or off.
                         With no args, it turns EXPLAIN on.
.genfkey ?OPTIONS?     Options are:
                         --no-drop: Do not drop old fkey triggers.
                         --ignore-errors: Ignore tables with fkey errors
                         --exec: Execute generated SQL immediately
                       See file tool/genfkey.README in the source
                       distribution for further information.
.header(s) ON|OFF      Turn display of headers on or off
.help                  Show this message
.import FILE TABLE     Import data from FILE into TABLE
.indices ?TABLE?       Show names of all indices
                         If TABLE specified, only show indices for tables
                         matching LIKE pattern TABLE.
.load FILE ?ENTRY?     Load an extension library
.log FILE|off          Turn logging on or off.  FILE can be stderr/stdout
.mode MODE ?TABLE?     Set output mode where MODE is one of:
                         csv      Comma-separated values
                         column   Left-aligned columns.  (See .width)
                         html     HTML <table> code
                         insert   SQL insert statements for TABLE
                         line     One value per line
                         list     Values delimited by .separator string
                         tabs     Tab-separated values
                         tcl      TCL list elements
.nullvalue STRING      Print STRING in place of NULL values
.output FILENAME       Send output to FILENAME
.output stdout         Send output to the screen
.prompt MAIN CONTINUE  Replace the standard prompts
.quit                  Exit this program
.read FILENAME         Execute SQL in FILENAME
.restore ?DB? FILE     Restore content of DB (default "main") from FILE
.schema ?TABLE?        Show the CREATE statements
                         If TABLE specified, only show tables matching
                         LIKE pattern TABLE.
.separator STRING      Change separator used by output mode and .import
.show                  Show the current values for various settings
.tables ?TABLE?        List names of tables
                         If TABLE specified, only list tables matching
                         LIKE pattern TABLE.
.timeout MS            Try opening locked tables for MS milliseconds
.width NUM1 NUM2 ...   Set column widths for "column" mode
.timer ON|OFF          Turn the CPU timer measurement on or off

出來的東西目前也不是很有用,就是一些命令的用法,其中有個命令是.table,這是我們需要的,他這裏的命令前面都是帶dot symbol的,該死的,網絡又斷了,這麼不給力的網

sqlite&gt; .tables
_sync_state                       status_updates                 
_sync_state_metadata              v1_settings                    
activities                        view_contacts                  
agg_exceptions                    view_contacts_restricted       
android_metadata                  view_data                      
calls                             view_data_restricted           
contact_entities_view             view_groups                    
contact_entities_view_restricted  view_raw_contacts              
contacts                          view_raw_contacts_restricted   
data                              view_v1_contact_methods        
groups                            view_v1_extensions             
mimetypes                         view_v1_group_membership       
name_lookup                       view_v1_groups                 
nickname_lookup                   view_v1_organizations          
packages                          view_v1_people                 
phone_lookup                      view_v1_phones                 
raw_contacts                      view_v1_photos                 
settings                       

這下面一共有這麼多表

前幾天還是看過一些資料的,ContactsContract有很多個內部類,其中有Data,RawContacts,Contacts之類的
這表裏面也有類似的這幾個表,當然都要打開看看咯

sqlite&gt; select * from contacts;
1|海 郭|||0|0|0|0|1|1|0nE044748D16||0

sqlite&gt; select * from raw_contacts; 
1|0||||2|1|0|1|0|0||0|0||0|海 郭|40||||

sqlite&gt; select * from data;
1||4|1|0|0|0|壞人|1|||||||||||||||||
2||5|1|0|0|0|http://lucane.javaeye.com|7|||||||||||||||||
3||3|1|0|0|0|長板坡宜昌, 湖北 443200|1||長板坡|||宜昌|湖北|443200||||||||||
4||6|1|0|0|0|非人||||||||||||||||||
5||7|1|0|0|0|1-504-115-9854|1||45895114051|||||||||||||||
6||7|1|0|0|0|1-226-548-89|2||988456221|||||||||||||||
7||2|1|0|0|0|304683630|3|||4||||||||||||||
8||8|1|0|0|0|home|1||翻譯官|||||||||||||||
9||9|1|0|0|0|海 郭|海|郭||||||||||||||||
10||1|1|0|0|0|xscript#live.com|2|||||||||||||||||
11||1|1|0|0|0|xseaer#gmail.com|1|||||||||||||||||

這都是我自己的的信息,真真假假,假假真真
命令行看着不怎麼清晰,我前幾天還在找和安裝sqlite的圖形化界面,結果未遂

可能新手看官看不出來啥東西,不過我有點看清楚了,因爲我知道這有些數據項是什麼意思

當然這所有的表當中可能還有些是視圖,感興趣的也可以都select出來看看

當然這還有些表是要select出來看的,比如mimetypes,

sqlite&gt; select * from mimetypes;
1|vnd.android.cursor.item/email_v2
2|vnd.android.cursor.item/im
3|vnd.android.cursor.item/postal-address_v2
4|vnd.android.cursor.item/nickname
5|vnd.android.cursor.item/website
6|vnd.android.cursor.item/note
7|vnd.android.cursor.item/phone_v2
8|vnd.android.cursor.item/organization
9|vnd.android.cursor.item/name
10|vnd.android.cursor.item/photo
11|vnd.android.cursor.item/group_membership

sqlite&gt; select * from view_data;
1|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/nickname|壞人|1|||||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
2|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/website|http://lucane.javaeye.com|7|||||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
3|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/postal-address_v2|長板坡宜昌, 湖北 443200|1||長板坡|||宜昌|湖北|443200||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
4|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/note|非人||||||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
5|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/phone_v2|1-504-115-9854|1||45895114051|||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
6|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/phone_v2|1-226-548-89|2||988456221|||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
7|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/im|304683630|3|||4||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
8|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/organization|home|1||翻譯官|||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
9|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/name|海 郭|海|郭||||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
10|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/email_v2|xscript#live.com|2|||||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
11|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/email_v2|xseaer#gmail.com|1|||||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||

比如看到view_data裏面的數據是不是又有點開心了呢?

順路把其他幾個view也查處來看看吧

sqlite&gt; select * from view_contacts;
1||海 郭|1|1|0nE044748D16||1|0|0|0|0|

sqlite&gt; select * from view_contacts_restricted;
1||海 郭|1|1|0nE044748D16||1|0|0|0|0|

sqlite&gt; select * from view_data_restricted;
1|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/nickname|壞人|1|||||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
2|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/website|http://lucane.javaeye.com|7|||||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
3|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/postal-address_v2|長板坡宜昌, 湖北 443200|1||長板坡|||宜昌|湖北|443200||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
4|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/note|非人||||||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
5|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/phone_v2|1-504-115-9854|1||45895114051|||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
6|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/phone_v2|1-226-548-89|2||988456221|||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
7|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/im|304683630|3|||4||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
8|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/organization|home|1||翻譯官|||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
9|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/name|海 郭|海|郭||||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
10|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/email_v2|xscript#live.com|2|||||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||
11|1|1||||2|1|||||0|0|0||vnd.android.cursor.item/email_v2|xseaer@#mail.com|1|||||||||||||||||||0|0|0|0|海 郭|0nE044748D16||1||

比較讓我失望的是android_metadata,settings這些表當中沒有查詢出什麼數據
因爲我總覺得這些mimetypes什麼的應該和某個數字或字符相對應(後來發現了mimetypes中的文字就是和該表當中貌似第一列主鍵的這個東西對應的,在其他的表中也是直接存的這個數字)

恩,接着再往下看吧,該搞那塊了?

這些表當中數據的存放不是通常的一個字段對應下面的數據都是這個意思,比如username字段下的數據都是用戶名

在data表當中,至少我們現在可以明顯的看出來在data表中,每行數據有指定他的類型,說他是什麼,他就是什麼

用原話來說基本就是這樣Generic data column, the meaning is {@link #MIMETYPE} specific
大概可能就是說當每一條數據的MIMETYPE定了,那麼它每一列代表的含義也就定了

這種方式大概就是爲了擴展的需要吧,當年我們也有這麼幹的時候

不知道大家對這個查詢出來的數據有沒有和我們平時不同的感覺
我感覺它缺了個title,雖然他的title含義不是固定的,但我總想看看

於是想把他弄出來看看
還記得我們最開始的時候.help出來有很多命令,我們只用了.table這個最關鍵的
既然想看錶的結構麼,當然就是desc或者describe這些命令了,不才我雖然正式開始Rock Android纔不久,但是以前還是搞SSH的,Oracle和MySQL還是略懂一二的

不過沒有發現類似的命令,倒是發現了個.schema(Show the CREATE statements)命令,既然圖形化的看不見,看SQL也是一樣的

sqlite&gt; .schema data

CREATE TABLE data (_id INTEGER PRIMARY KEY AUTOINCREMENT,package_id INTEGER REFERENCES package(_id),mimetype_id INTEGER REFERENCES mimetype(_id) NOT NULL,raw_contact_id INTEGER REFERENCES raw_contacts(_id) NOT NULL,is_primary INTEGER NOT NULL DEFAULT 0,is_super_primary INTEGER NOT NULL DEFAULT 0,data_version INTEGER NOT NULL DEFAULT 0,data1 TEXT,data2 TEXT,data3 TEXT,data4 TEXT,data5 TEXT,data6 TEXT,data7 TEXT,data8 TEXT,data9 TEXT,data10 TEXT,data11 TEXT,data12 TEXT,data13 TEXT,data14 TEXT,data15 TEXT,data_sync1 TEXT, data_sync2 TEXT, data_sync3 TEXT, data_sync4 TEXT );
CREATE INDEX data_mimetype_data1_index ON data (mimetype_id,data1);
CREATE INDEX data_raw_contact_id ON data (raw_contact_id);
CREATE TRIGGER data_deleted BEFORE DELETE ON data BEGIN    UPDATE raw_contacts     SET version=version+1      WHERE _id=OLD.raw_contact_id;   DELETE FROM phone_lookup     WHERE data_id=OLD._id;   DELETE FROM status_updates     WHERE status_update_data_id=OLD._id;   DELETE FROM name_lookup     WHERE data_id=OLD._id; END;
CREATE TRIGGER data_updated BEFORE UPDATE ON data BEGIN    UPDATE data     SET data_version=OLD.data_version+1      WHERE _id=OLD._id;   UPDATE raw_contacts     SET version=version+1      WHERE _id=OLD.raw_contact_id; END;

好長啊,又是表,又是索引,又是觸發器,這麼一個小數據庫開是挺專業的
好吧,既然沒有圖形化的,我手動給他畫個,刷個牙,回來再繼續,晚上10點半了

文章來自: 程序員俱樂部(www.cxyclub.cn) 詳文參考:http://www.cxyclub.cn/n/5984/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章