【Android】12.5 利用Intent讀取和更新通訊錄,androidintent
分類:C#、Android、VS2015;
建立日期:2016-02-23 一、簡介
本節示範如何在安卓系統中通過使用者設定檔(user profile)讀取和更新該手機的所有連絡人資訊,以及如何導航到使用者設定檔中的這些連絡人。 二、基本概念
1、什麼是 User Profile
使用者設定檔(user profile)儲存的是機主資訊以及該手機中所有連絡人的資訊。
假定手機所有者的名字為“Mao mao yu”,那麼,user profile儲存的就是“Mao mao yu”的通訊錄(即機主所有連絡人的姓名、電話、郵箱、……等資訊)。在Android 4中,這個儲存連絡人資訊的應用程式稱為“People app”,而在Android 5.0及更高版本中,這個應用程式又改稱為“Contacts app” 。
Android 6.0(API 23)模擬器已經包含了【通訊錄】功能,利用它可直接手工添加手機所有者姓名及其連絡人,如所示:
單擊【通訊錄】中的某個連絡人,例如單擊機主的名字(或者其他連絡人的名字),就可以在顯示的介面中修改這個人的姓名、電話、郵箱、住址等資訊,或者添加新連絡人,這個功能大家在手機上用的太熟了,這裡就不多說了。
我們這一節的目標就是學習如何在自己的應用程式中通過代碼去添加或修改這個使用者設定檔(user profile)中的資訊,而不是用它自身提供的功能去編輯。
2、許可權要求
要在你的程式中讀和寫手機所有連絡人的資料,你的應用程式必須具有Read_Contacts和Write_Contacts許可權。另外,要讀取和編輯使用者設定檔(user profile),你的應用程式必須具有Read_Profile和Write_Profile許可權。
或者說,必須具有下面的許可權才能讀寫通訊錄和機主的使用者設定檔:
READ_CONTACTS
READ_PROFILE
WRITE_CONTACTS
WRITE_PROFILE
實際上,你手機上下載的各類應用程式,只要有對應的許可權,都可以擷取和修改你的通訊錄(一般手機使用者都不是搞電腦的,因此也不太關心什麼許可權不許可權,直接按下一步點下去,結果是預設都給這些程式賦予了完全的讀寫權限)。或者說,只要你給這些應用程式賦予了對應的讀寫權限,那麼你的通訊錄實際上就沒有一點安全可言了,這些程式想什麼時候擷取就可以什麼時候擷取(泄露出去真是太簡單了),這也是為什麼有那麼多免費的手機應用拚命讓你去下載和使用的原因。
是在VS2015中設定Read_Contacts和Read_Profile的辦法(通過單擊主菜單【項目】下的【屬性】彈出此介面):
按照同樣的辦法,可繼續設定WRITE_CONTACTS和WRITE_PROFILE許可權。
3、擷取通訊錄資訊(Reading Profile Data)
安卓早期的版本是通過ContactContracts.Contacts類來擷取手機上所有連絡人的列表資訊的。從Android 4開始又提供了一個新的ContactsContact.Profile類,該類提供了對裝置所有者使用者設定檔(user profile)的訪問,利用它即可擷取和修改所有連絡人的名稱、電話號碼等資料。
向 ContactsContact.Profile.ContentUri 發出查詢即可讀取設定檔的資料。例如,下面的代碼讀取該使用者設定檔的顯示名稱:
var uri = ContactsContract.Contacts.ContentUri;
string[] projection = {
ContactsContract.Contacts.InterfaceConsts.DisplayName
};
var cursor = ContentResolver.Query(uri, projection, null, null, null);
if (cursor.MoveToFirst ()) {
Console.WriteLine(cursor.GetString (cursor.GetColumnIndex (projection [0])));
}
4、更新連絡人資訊(Update the User's Profile)
應用程式只要有對應的讀寫權限,就可以像其他普通的應用程式一樣與使用者設定檔(user profile)中的資料進行互動。例如,調用ContentResolver.Update方法可更新設定檔中的顯示名稱,該方法通過ContactsContract.Profile.ContentRawContactsUri屬性檢索Uri,如下面的代碼所示:
var values = new ContentValues ();
values.Put (ContactsContract.Contacts.InterfaceConsts.DisplayName, "Mao mao yu");
ContentResolver.Update (ContactsContract.Profile.ContentRawContactsUri,values, null, null);
注意:不能顯式建立使用者設定檔(user's profiile),否則將出現異常。
接下來,可建立一個ReadBackName方法,如下面的代碼所示。調用此方法可驗證添加到使用者設定檔的名稱是否確實被更新了。在這個方法中,首先擷取使用者的設定檔的 URI 並配置投影,從此設定檔中僅僅讀取一列 (使用者的顯示名稱)。為了訪問使用者的設定檔資料,接下來建立了一個遊標對象。如果成功地初始化遊標,則它被移動到使用者設定檔中的第一項。在此位置 (使用者顯示名稱) 的第一列中讀取名稱並將其列印到控制台。如果這些操作成功,ReadBackName 返回 true;否則返回 false。
bool ReadBackName()
{
Android.Net.Uri uri = ContactsContract.Profile.ContentUri;
string[] projection = { ContactsContract.Contacts.InterfaceConsts.DisplayName };
var cursor = ContentResolver.Query(uri, projection, null, null, null);
if (cursor != null)
{
if (cursor.MoveToFirst())
{
Console.WriteLine(cursor.GetString(cursor.GetColumnIndex(projection[0])));
return true;
}
}
return false;
}
添加一個ViewProfile方法,該方法會自動調用Contacts App顯示user profile中的資訊:
void ViewProfile ()
{
Intent intent = new Intent (Intent.ActionView, ContactsContract.Profile.ContentUri);
StartActivity (intent);
}
注意:僅在Android 4及更高版本中才可以使用手機所有者的使用者設定檔。另外,在使用者設定檔可以更新之前,必須先手動建立連絡人。
關於ContactContracts.Profile 的更多資訊,請參見 ContactsContract.Profile 類。 三、樣本—ch1204ReadContacts
本樣本示範如何擷取通訊錄中的連絡人。
1、運行
單擊【讀取通訊錄】按鈕,即得到下面右側的。
單擊【修改機主資訊】按鈕,即得到下面的修改介面:
2、主要設計步驟
(1)設定許可權
在VS2015開發環境下,選擇主菜單的【項目】à【ContactsDemo屬性】,在彈出的視窗中勾選下面的許可權:
READ_CONTACTS
READ_PROFILE
WRITE_CONTACTS
WRITE_PROFILE
或者在【方案總管】中,滑鼠雙擊項目的【Properties】進入設定介面,然後勾選上面的選項。
設定完畢後,在AndroidManifest.xml檔案中就會自動添加下面的代碼:
<uses-permission android:name="android.permission.READ_CONTACTS" /><uses-permission android:name="android.permission.READ_PROFILE" /><uses-permission android:name="android.permission.WRITE_CONTACTS" /><uses-permission android:name="android.permission.WRITE_PROFILE" />
(2)添加改ch1204_Main.axml檔案
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:background="@android:color/background_light" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:text="讀取通訊錄" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnRead" /> <Button android:text="修改機主資訊" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnUpdate" /></LinearLayout>
(3)添加ch1204_ContactListItem.axml檔案
在Resources/layout/下添加該檔案。
<?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="15dip" />
(4)添加ch1204ReadContactActivity.cs檔案
using System.Collections.Generic;using Android.App;using Android.Content;using Android.OS;using Android.Widget;using Android.Provider;namespace MyDemos.SrcDemos{ [Activity(Label = "【例12-4】讀取和更新通訊錄")] public class ch1204ReadContactActivity : ListActivity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); var uri = ContactsContract.Contacts.ContentUri; string[] projection = { ContactsContract.Contacts.InterfaceConsts.Id, ContactsContract.Contacts.InterfaceConsts.DisplayName }; var cursor = ContentResolver.Query(uri, projection, null, null, null); var contactList = new List<string>(); if (cursor.MoveToFirst()) { do { contactList.Add(cursor.GetString(cursor.GetColumnIndex(projection[1]))); } while (cursor.MoveToNext()); } ListAdapter = new ArrayAdapter<string>(this, Resource.Layout.ch1204_ContactListItem, contactList); } }}
注意該類繼承自ListActivity,不是繼承自Activity。
(5)添加ch1204ReadContactsMain.cs檔案
using Android.App;using Android.Content;using Android.OS;using Android.Widget;using Android.Provider;namespace MyDemos.SrcDemos{ [Activity(Label = "【例12-4】讀取和更新通訊錄")] public class ch1204ReadContactsMain : Activity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.ch1204_Main); var btnRead = FindViewById<Button>(Resource.Id.btnRead); btnRead.Click += delegate { StartActivity(typeof(ch1204ReadContactActivity)); }; var btnUpdate = FindViewById<Button>(Resource.Id.btnUpdate); btnUpdate.Click += delegate { NameOwner(); if (ReadBackName()) { Intent intent = new Intent(Intent.ActionView, ContactsContract.Profile.ContentUri); StartActivity(intent); } }; } /// <summary> /// 定義手機機主的名字 /// </summary> void NameOwner() { ContentValues values = new ContentValues(); //將“Rainmj”插入到已存在的user profile中 values.Put(ContactsContract.Contacts.InterfaceConsts.DisplayName, "Rainmj"); //更新user profile ContentResolver.Update(ContactsContract.Profile.ContentRawContactsUri, values, null, null); } /// <summary> /// 檢查“更新user profile”是否成功 /// </summary> /// <returns></returns> bool ReadBackName() { //擷取user profile的Uri Android.Net.Uri uri = ContactsContract.Profile.ContentUri; //配置投影,指定準備從user profile中讀取的列 string[] projection = { ContactsContract.Contacts.InterfaceConsts.DisplayName }; var cursor = ContentResolver.Query(uri, projection, null, null, null); //或者 //CursorLoader loader = new CursorLoader(this, uri, projection, null, null, null); //var cursor = (ICursor)loader.LoadInBackground(); if (cursor != null) { if (cursor.MoveToFirst()) { //Console.WriteLine(cursor.GetString(cursor.GetColumnIndex(projection[0]))); return true; } } return false; } }}
運行即得到所示的效果。