免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
總結(jié)篇之六:ContentProvider之讀寫聯(lián)系人

很多事情,絕大多數(shù)人都會在開始的時候滿懷熱情,而能堅持到底的卻是寥寥無幾。對待自己的目標(biāo),虎頭蛇尾絕不可取,半途而廢只會一無所成,我們必須持之以恒的做下去,堅持到底才能摘取勝利的果實。最近也忙了起來,忙著給自己充電,深知這項任務(wù)的艱巨,不是一天兩天的事,所以也借用這句警言來告誡自己,堅持不懈的走下去。

今天我們來講解一下如何利用ContentProvider機制讀寫聯(lián)系人信息。

在Android中,ContentProvider是一種數(shù)據(jù)包裝器,適合在不同進程間實現(xiàn)信息的共享。例如,在Android中SQLite數(shù)據(jù)庫是一個典型的數(shù)據(jù)源,我們可以把它封裝到ContentProvider中,這樣就可以很好的為其他應(yīng)用提供信息共享服務(wù)。其他應(yīng)用在訪問ContentProvider時,可以使用一組類似REST的URI的方式進行數(shù)據(jù)操作,大大簡化了讀寫信息的復(fù)雜度。例如,如果要從封裝圖書數(shù)據(jù)庫的ContentProvider獲取一組圖書,需要使用類似以下形式的URI:

content://com.scott.book.BookProvider/books

而要從圖書數(shù)據(jù)庫中獲取指定圖書(比如23號圖書),需要使用類似以下形式的URI:

content://com.scott.book.BookProvider/books/23

注:ContentProvider是一個抽象類,定義了一系列操作數(shù)據(jù)的方法模板,BookProvider需要實現(xiàn)這些方法,實現(xiàn)圖書信息的各種操作。

那么,現(xiàn)在知道了具體的URI之后,我們又如何操作進而取得數(shù)據(jù)呢?

此時,我們就要了解ContentResolver這個類,它跟ContentProvider是對應(yīng)的關(guān)系,我們正是通過它來與ContentProvider進行數(shù)據(jù)交換的。android.content.Context類為我們定義了getContentResolver()方法,用于獲取一個ContentResolver對象,如果我們在運行期可以通過getContext()獲取當(dāng)前Context實例對象,就可以通過這個實例對象所提供的getContentResolver()方法獲取到ContentResolver類型的實例對象,進而可以操作對應(yīng)的數(shù)據(jù)。

下面我們就通過聯(lián)系人實例對這種機制進行演示。

在Android中,聯(lián)系人的操作都是通過一個統(tǒng)一的途徑來讀寫數(shù)據(jù)的,我們打開/data/data/com.android.providers.contacts可以看到聯(lián)系人的數(shù)據(jù)源:


有興趣的朋友可以導(dǎo)出這個文件,用專業(yè)的工具軟件打開看一下表結(jié)構(gòu)。

對這個SQLite類型的數(shù)據(jù)源的封裝后,聯(lián)系人就以ContentProvider的形式為其他應(yīng)用進程提供聯(lián)系人的讀寫服務(wù),我們就可以順利成章的操作自己的聯(lián)系人信息了。

為了方便測試,我們先添加兩個聯(lián)系人到數(shù)據(jù)源中,如圖所示:



我們看到,每個聯(lián)系人都有兩個電話號碼和兩個郵箱賬號,分別為家庭座機號碼、移動手機號碼、家庭郵箱賬號和工作郵箱賬號。當(dāng)然在添加聯(lián)系人時有很多其他信息,我們這里都沒有填寫,只選擇了最常用的電話和郵箱,主要是方便演示這個過程。

在演示代碼之前,我們需要了解一下android.provider.ContactsContract這個類(注:在較早的版本中是android.provider.Contacts這個類,不過現(xiàn)在已被廢棄,不建議使用),它定義了各種聯(lián)系人相關(guān)的URI和每一種類型信息的屬性信息:


有興趣的朋友還可以讀一下源代碼,不過比較多,而且內(nèi)部類使用的特別多,讀起來有一定的困難,還是要做好心理準(zhǔn)備。

下面我們通過一個項目,來演示一下聯(lián)系人操作的具體過程。新建一個名為provider的項目,創(chuàng)建一個名為ContactsReadTest的測試用例,如下:

  1. package com.scott.provider;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.content.ContentResolver;  
  6. import android.database.Cursor;  
  7. import android.net.Uri;  
  8. import android.provider.ContactsContract;  
  9. import android.test.AndroidTestCase;  
  10. import android.util.Log;  
  11.   
  12. public class ContactsReadTest extends AndroidTestCase {  
  13.       
  14.     private static final String TAG = "ContactsReadTest";  
  15.       
  16.     //[content://com.android.contacts/contacts]  
  17.     private static final Uri CONTACTS_URI = ContactsContract.Contacts.CONTENT_URI;  
  18.     //[content://com.android.contacts/data/phones]  
  19.     private static final Uri PHONES_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;  
  20.     //[content://com.android.contacts/data/emails]  
  21.     private static final Uri EMAIL_URI = ContactsContract.CommonDataKinds.Email.CONTENT_URI;  
  22.       
  23.     private static final String _ID = ContactsContract.Contacts._ID;  
  24.     private static final String DISPLAY_NAME = ContactsContract.Contacts.DISPLAY_NAME;  
  25.     private static final String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;  
  26.     private static final String CONTACT_ID = ContactsContract.Data.CONTACT_ID;  
  27.       
  28.     private static final String PHONE_NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;  
  29.     private static final String PHONE_TYPE = ContactsContract.CommonDataKinds.Phone.TYPE;  
  30.     private static final String EMAIL_DATA = ContactsContract.CommonDataKinds.Email.DATA;  
  31.     private static final String EMAIL_TYPE = ContactsContract.CommonDataKinds.Email.TYPE;  
  32.       
  33.     public void testReadContacts() {  
  34.         ContentResolver resolver = getContext().getContentResolver();  
  35.         Cursor c = resolver.query(CONTACTS_URI, nullnullnullnull);  
  36.         while (c.moveToNext()) {  
  37.             int _id = c.getInt(c.getColumnIndex(_ID));  
  38.             String displayName = c.getString(c.getColumnIndex(DISPLAY_NAME));  
  39.               
  40.             Log.i(TAG, displayName);  
  41.               
  42.             ArrayList<String> phones = new ArrayList<String>();  
  43.             ArrayList<String> emails = new ArrayList<String>();  
  44.               
  45.             String selection = CONTACT_ID + "=" + _id;  //the 'where' clause  
  46.               
  47.             //獲取手機號  
  48.             int hasPhoneNumber = c.getInt(c.getColumnIndex(HAS_PHONE_NUMBER));  
  49.             if (hasPhoneNumber > 0) {  
  50.                 Cursor  phc = resolver.query(PHONES_URI, null, selection, nullnull);  
  51.                 while (phc.moveToNext()) {  
  52.                     String phoneNumber = phc.getString(phc.getColumnIndex(PHONE_NUMBER));  
  53.                     int phoneType = phc.getInt(phc.getColumnIndex(PHONE_TYPE));  
  54.                     phones.add(getPhoneTypeNameById(phoneType) + " : " + phoneNumber);  
  55.                 }  
  56.                 phc.close();  
  57.             }  
  58.               
  59.             Log.i(TAG, "phones: " + phones);  
  60.               
  61.             //獲取郵箱  
  62.             Cursor emc = resolver.query(EMAIL_URI,null, selection, nullnull);  
  63.             while (emc.moveToNext()) {  
  64.                 String emailData = emc.getString(emc.getColumnIndex(EMAIL_DATA));  
  65.                 int emailType = emc.getInt(emc.getColumnIndex(EMAIL_TYPE));  
  66.                 emails.add(getEmailTypeNameById(emailType) + " : " + emailData);  
  67.             }  
  68.             emc.close();  
  69.               
  70.             Log.i(TAG, "emails: " + emails);  
  71.         }  
  72.         c.close();  
  73.     }  
  74.       
  75.     private String getPhoneTypeNameById(int typeId) {  
  76.         switch (typeId) {  
  77.         case ContactsContract.CommonDataKinds.Phone.TYPE_HOME: return "home";  
  78.         case ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE: return "mobile";  
  79.         case ContactsContract.CommonDataKinds.Phone.TYPE_WORK: return "work";  
  80.         defaultreturn "none";  
  81.         }  
  82.     }  
  83.       
  84.     private String getEmailTypeNameById(int typeId) {  
  85.         switch (typeId) {  
  86.         case ContactsContract.CommonDataKinds.Email.TYPE_HOME: return "home";  
  87.         case ContactsContract.CommonDataKinds.Email.TYPE_WORK: return "work";  
  88.         case ContactsContract.CommonDataKinds.Email.TYPE_OTHER: return "other";  
  89.         defaultreturn "none";  
  90.         }  
  91.     }  
  92. }  
為了使這個測試用例運行起來,我們需要在AndroidManifest.xml中配置一下測試設(shè)備的聲明,它與<application>元素處于同一級別位置:

  1. <!-- 配置測試設(shè)備的主類和目標(biāo)包 -->  
  2.     <instrumentation android:name="android.test.InstrumentationTestRunner"  
  3.                      android:targetPackage="com.scott.provider"/>  
然后再配置使用測試類庫聲明,它與<activity>元素處于同一級別位置:

  1. <!-- 配置測試要使用的類庫 -->  
  2.    <uses-library android:name="android.test.runner"/>  
最后,還有一個重要的聲明需要配置,就是讀取聯(lián)系人權(quán)限,聲明如下:

  1. <!-- 讀取聯(lián)系人 -->  
  2. <uses-permission android:name="android.permission.READ_CONTACTS"/>  
經(jīng)過以上準(zhǔn)備工作,這個測試用例就可以運轉(zhuǎn)起來了,我們運行一下testReadContacts()方法,打印結(jié)果如下:


看來聯(lián)系人里的信息都被我們準(zhǔn)確無誤的讀取出來了。

如果我們在一個Activity里運行讀取聯(lián)系人的代碼,不僅可以使用ContentResolver直接進行讀取操作(即查詢),還可以使用Activity提供的managedQuery方法方便的實現(xiàn)同樣的效果,我們來看一下這個方法的具體代碼:

  1. public final Cursor managedQuery(Uri uri,  
  2.                                  String[] projection,  
  3.                                  String selection,  
  4.                                  String[] selectionArgs,  
  5.                                  String sortOrder)  
  6. {  
  7.     Cursor c = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);  
  8.     if (c != null) {  
  9.         startManagingCursor(c);  
  10.     }  
  11.     return c;  
  12. }  
我們發(fā)現(xiàn),其實它還是使用了ContentResolver進行查詢操作,但是多了一步startManagingCursor的操作,它會根據(jù)Activity的生命周期對Cursor對象進行管理,避免了一些因Cursor是否釋放引起的問題,所以非常方便,大大簡化了我們的工作量。

接下來我們將要嘗試將一個聯(lián)系人信息添加到系統(tǒng)聯(lián)系人的數(shù)據(jù)源中,實現(xiàn)對聯(lián)系人的寫入操作。我們新建一個名為ContactsWriteTest的測試用例,如下:

  1. package com.scott.provider;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.content.ContentProviderOperation;  
  6. import android.content.ContentProviderResult;  
  7. import android.content.ContentResolver;  
  8. import android.net.Uri;  
  9. import android.provider.ContactsContract;  
  10. import android.test.AndroidTestCase;  
  11. import android.util.Log;  
  12.   
  13. public class ContactsWriteTest extends AndroidTestCase {  
  14.   
  15.     private static final String TAG = "ContactsWriteTest";  
  16.   
  17.     //[content://com.android.contacts/raw_contacts]  
  18.     private static final Uri RAW_CONTACTS_URI = ContactsContract.RawContacts.CONTENT_URI;  
  19.     //[content://com.android.contacts/data]  
  20.     private static final Uri DATA_URI = ContactsContract.Data.CONTENT_URI;  
  21.       
  22.     private static final String ACCOUNT_TYPE = ContactsContract.RawContacts.ACCOUNT_TYPE;  
  23.     private static final String ACCOUNT_NAME = ContactsContract.RawContacts.ACCOUNT_NAME;  
  24.       
  25.     private static final String RAW_CONTACT_ID = ContactsContract.Data.RAW_CONTACT_ID;  
  26.     private static final String MIMETYPE = ContactsContract.Data.MIMETYPE;  
  27.       
  28.     private static final String NAME_ITEM_TYPE = ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE;  
  29.     private static final String DISPLAY_NAME = ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME;  
  30.       
  31.     private static final String PHONE_ITEM_TYPE = ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE;  
  32.     private static final String PHONE_NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;  
  33.     private static final String PHONE_TYPE = ContactsContract.CommonDataKinds.Phone.TYPE;  
  34.     private static final int PHONE_TYPE_HOME = ContactsContract.CommonDataKinds.Phone.TYPE_HOME;  
  35.     private static final int PHONE_TYPE_MOBILE = ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE;  
  36.       
  37.     private static final String EMAIL_ITEM_TYPE = ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE;  
  38.     private static final String EMAIL_DATA = ContactsContract.CommonDataKinds.Email.DATA;  
  39.     private static final String EMAIL_TYPE = ContactsContract.CommonDataKinds.Email.TYPE;  
  40.     private static final int EMAIL_TYPE_HOME = ContactsContract.CommonDataKinds.Email.TYPE_HOME;  
  41.     private static final int EMAIL_TYPE_WORK = ContactsContract.CommonDataKinds.Email.TYPE_WORK;  
  42.   
  43.     private static final String AUTHORITY = ContactsContract.AUTHORITY;  
  44.       
  45.     public void testWriteContacts() throws Exception {  
  46.         ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();  
  47.   
  48.         ContentProviderOperation operation = ContentProviderOperation.newInsert(RAW_CONTACTS_URI)  
  49.                                     .withValue(ACCOUNT_TYPE, null)  
  50.                                     .withValue(ACCOUNT_NAME, null)  
  51.                                     .build();  
  52.         operations.add(operation);  
  53.   
  54.         //添加聯(lián)系人名稱操作  
  55.         operation = ContentProviderOperation.newInsert(DATA_URI)  
  56.                                     .withValueBackReference(RAW_CONTACT_ID, 0)  
  57.                                     .withValue(MIMETYPE, NAME_ITEM_TYPE)  
  58.                                     .withValue(DISPLAY_NAME, "Scott Liu")  
  59.                                     .build();  
  60.         operations.add(operation);  
  61.   
  62.         //添加家庭座機號碼  
  63.         operation = ContentProviderOperation.newInsert(DATA_URI)  
  64.                                     .withValueBackReference(RAW_CONTACT_ID, 0)  
  65.                                     .withValue(MIMETYPE, PHONE_ITEM_TYPE)  
  66.                                     .withValue(PHONE_TYPE, PHONE_TYPE_HOME)  
  67.                                     .withValue(PHONE_NUMBER, "01034567890")  
  68.                                     .build();  
  69.         operations.add(operation);  
  70.           
  71.         //添加移動手機號碼  
  72.         operation = ContentProviderOperation.newInsert(DATA_URI)  
  73.                                     .withValueBackReference(RAW_CONTACT_ID, 0)  
  74.                                     .withValue(MIMETYPE, PHONE_ITEM_TYPE)  
  75.                                     .withValue(PHONE_TYPE, PHONE_TYPE_MOBILE)  
  76.                                     .withValue(PHONE_NUMBER, "13034567890")  
  77.                                     .build();  
  78.         operations.add(operation);  
  79.   
  80.         //添加家庭郵箱  
  81.         operation = ContentProviderOperation.newInsert(DATA_URI)  
  82.                                     .withValueBackReference(RAW_CONTACT_ID, 0)  
  83.                                     .withValue(MIMETYPE, EMAIL_ITEM_TYPE)  
  84.                                     .withValue(EMAIL_TYPE, EMAIL_TYPE_HOME)  
  85.                                     .withValue(EMAIL_DATA, "scott@android.com")  
  86.                                     .build();  
  87.         operations.add(operation);  
  88.   
  89.         //添加工作郵箱  
  90.         operation = ContentProviderOperation.newInsert(DATA_URI)  
  91.                                     .withValueBackReference(RAW_CONTACT_ID, 0)  
  92.                                     .withValue(MIMETYPE, EMAIL_ITEM_TYPE)  
  93.                                     .withValue(EMAIL_TYPE, EMAIL_TYPE_WORK)  
  94.                                     .withValue(EMAIL_DATA, "scott@msapple.com")  
  95.                                     .build();  
  96.         operations.add(operation);  
  97.           
  98.         ContentResolver resolver = getContext().getContentResolver();  
  99.         //批量執(zhí)行,返回執(zhí)行結(jié)果集  
  100.         ContentProviderResult[] results = resolver.applyBatch(AUTHORITY, operations);  
  101.         for (ContentProviderResult result : results) {  
  102.             Log.i(TAG, result.uri.toString());  
  103.         }  
  104.     }  
  105. }  
在上面的代碼中,我們把整個操作分為幾個ContentProviderOperation操作,并將他們做批處理操作,我們也許注意到,從第二個操作開始,每一項都有一個withValueBackReference(RAW_CONTACT_ID, 0)步驟,它參照了第一項操作新添加的聯(lián)系人的id,因為是批處理,我們插入數(shù)據(jù)前并不知道id的值,不過這個不用擔(dān)心,在進行批處理插入數(shù)據(jù)時,它會重新引用新的id值,不會影響最終的結(jié)果。

當(dāng)然,這個也不能忘了配置寫入聯(lián)系人的權(quán)限聲明:

  1. <!-- 寫入聯(lián)系人 -->  
  2. <uses-permission android:name="android.permission.WRITE_CONTACTS" />  
經(jīng)過以上步驟之后,我們運行一下testWriteContacts()方法,看看聯(lián)系人是否添加進去了:

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
android聯(lián)系人信息的存儲結(jié)構(gòu)
android系統(tǒng)常用URI
獲得手機通訊錄聯(lián)系人信息
第二十講:Content Provider 使用入門
Android 獲取Contacts 聯(lián)系人 姓名 號碼 照片信息
android 通話記錄的增刪改查 .
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服