電話帳からメールアドレスを取得するにはAndroid2.1以降

以前、メール関連アプリを開発したが、Android2.1にアップデートしそのアプリを実行すると、 連絡先一覧に新規登録した方が表示されないという不具合が発生した。
調べてみると、Android2.1以降では連絡先の取得方法が変わっていることがわかった。
Android2.1の推奨された方法で連絡先を取得することができたので以下にメモ書き。

//
// メールアドレスが登録されている連絡先だけを一覧表示する
//

// DATA表からメールアドレスを全て取得
ContentResolver cr = getContentResolver();
Cursor dataAddressTable = cr.query(
  Data.CONTENT_URI,
  null,
  Data.MIMETYPE + " = ?",
  new String[]{Email.CONTENT_ITEM_TYPE},
  null);

// ハッシュ変数にアドレスを格納(id, address)
HashMap<String, String> mailHash = new HashMap<String, String>();
while(dataAddressTable.moveToNext()) {
  mailHash.put(
    dataAddressTable.getString(
      dataAddressTable.getColumnIndex(Data.CONTACT_ID)), // ID
    dataAddressTable.getString(
      dataAddressTable.getColumnIndex(Data.DATA1))); // メールアドレス
}

// カーソルを閉じる
dataAddressTable.close();

// ソート文字を格納(連絡先一覧を "ふりがな" 順でソート)
String order_str =
  " CASE" +
  " WHEN IFNULL(" + Data.DATA9 + ", '') = ''" + // Data.DATA9がNULLの場合は空文字を代入
  " THEN 1 ELSE 0" + // Data.DATA9が空文字のレコードを最後にする
  " END, " + Data.DATA9 + " ," +
  " CASE" +
  " WHEN IFNULL(" + Data.DATA7 + ", '') = ''" +
  " THEN 1 ELSE 0" +
  " END, " + Data.DATA7;

// DATA表から連絡先名を全て取得
Cursor dataNameTable = cr.query(
  Data.CONTENT_URI,
  null,
  Data.MIMETYPE + " = ?",
  new String[]{StructuredName.CONTENT_ITEM_TYPE},
  order_str);

// メールアドレスが存在する連絡先だけを名前格納用リストに格納
ArrayList<String> listItems = new ArrayList<String>(); // 名前格納用リスト
while(dataNameTable.moveToNext()) {
  String id = dataNameTable.getString(
    dataNameTable.getColumnIndex(Data.CONTACT_ID));
  if(mailHash.containsKey(id)) {
    listItems.add(dataNameTable.getString(
      dataNameTable.getColumnIndex(Data.DISPLAY_NAME)));
  }
}

// カーソルを閉じる
dataNameTable.close();

// 連絡先一覧をリストビューで表示
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
  this, android.R.layout.simple_list_item_1, listItems);
lv.setAdapter(adapter);
		

以上のコードで、メールアドレスが登録されている連絡先をふりがな順で表示することができる。
今回はData.CONTENT_URIを使い連絡先名やメールアドレスを取得したが、Contacts.CONTENT_URIや Email.CONTENT_URIを使っても取得できるので、それぞれのURIについて調べた内容を下に書き留める。

コンテンツ プロバイダ

URI 説明
Contacts.CONTENT_URI 連絡先
Phone.CONTENT_URI 電話番号
Email.CONTENT_URI メールアドレス
CallLog.Calls.CONTENT_URI 通信履歴
Data.CONTENT_URI 連絡先、メールアドレス、電話番号

Contacts.CONTENT_URI

android.provider.ContactsContract.Contacts.CONTENT_URI

連絡先に登録されている方、全員が格納されている。

項目 説明
_id ユニークなID
display_name 連絡先の表示名
last_time_contacted 最後に連絡した時間

Phone.CONTENT_URI

android.provider.ContactsContract.CommonDataKinds.Phone.CONTENT_URI

連絡先に登録されている方の電話番号が格納されている。

項目 説明
_id ユニークなID
contact_id 連絡先のID
display_name 連絡先の表示名
data1 電話番号
last_time_contacted 最後に連絡した時間

Email.CONTENT_URI

android.provider.ContactsContract.CommonDataKinds.Email.CONTENT_URI

連絡先に登録されている方のメールアドレスが格納されている。

項目 説明
_id ユニークなID
contact_id 連絡先のID
display_name 連絡先の表示名
data1 メールアドレス
last_time_contacted 最後に連絡した時間

注意:last_time_contacted は対象の方へ最後にメールを送信した時間ではなく最後に電話した時間。

CallLog.Calls.CONTENT_URI

android.provider.CallLog.Calls.CONTENT_URI

連絡先に登録されている方への最終通信履歴が格納されている。

項目 説明
_id ユニークなID
name 連絡先の表示名
number 電話番号
date 最終通話日時

Data.CONTENT_URI

android.provider.ContactsContract.Data.CONTENT_URI

連絡先に登録されている方の情報(連絡先名、メールアドレス、電話番号など)が格納されている。

項目 説明
_id ユニークなID
contact_id 連絡先のID
mimetype データの種類
data1 データ
data2 データ
data3 データ
data7 データ
data9 データ
display_name 連絡先の表示名
last_time_contacted 最後に連絡した時間

連絡先名やメールアドレス、電話番号といった情報を区別する項目(列)は mimetype であり詳細は下の通り。

mimetype
格納される内容 説明
vnd.android.cursor.item/phone_v2 電話番号
vnd.android.cursor.item/email_v2 メールアドレス
vnd.android.cursor.item/name 連絡先名

電話番号レコードの場合、data1 には電話番号が格納されている。
メールアドレスレコードの場合、data1 にはメールアドレスが格納されている。
連絡先名レコードの場合、data1 には表示名(姓名)、data2 には表示名(名)、data3 には表示名(姓)、data7 にはふりがな(名)、data9 にはふりがな(姓)が格納されている。

電話帳へアクセスするにはマニフェストにパーミッションを記述し忘れないよう注意してください。

<uses-permission android:name="android.permission.READ_CONTACTS"/>