2012/06/24

Android で電話帳から選択した人の電話番号一覧を取得するサンプル。

デスマって凄いですね。
どうもこんにちは。

Android のいいところ Intent 連携。
そんな便利機能で電話帳と連携して、選択した人の電話番号を取得したい。

ただし選択した人の電話番号が一つとは限らない。
Google 先生に聞いてみたら一つだけ取得するサンプルは結構あるんだけど、
そこから全件取得するってのはなかった(と思う)。

なのでこしらえた。
対象は Android 2.x 以上。 ICS も行けるかと思う(実機では試してない)。
  1. [連絡先]ボタンをクリックしたら、[電話帳]が開く。
  2. [電話帳]から任意に選択する。
  3. 選択された人が複数電話番号を持っていたら、ダイアログを表示して選択する。
  4. 選択した電話番号を表示する。
こんな流れ。

AndroidManifest.xml には以下のパーミッションの追記を忘れずに。
<uses-permission android:name="android.permission.READ_CONTACTS"/>

レイアウトファイルはどうでもいいけど・・・。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="連絡先" />
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
view raw main.xml hosted with ❤ by GitHub
package com.example;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
/**
* @author peko
*
*/
public class MainActivity extends Activity implements DialogInterface.OnClickListener {
private static final String TAG = "MainActivity";
private static final int PICK_CONTACT = 1111;
private AlertDialog.Builder _alertDialogBuilder;
private TextView _phoneNumberTextView;
private String[] _phoneNumbers;
/*
* (non-Javadoc)
*
* @see android.app.Activity#onCreate(android.os.Bundle)
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.main);
this._alertDialogBuilder = new AlertDialog.Builder(this);
this._phoneNumberTextView = (TextView) this.findViewById(R.id.text);
((Button) this.findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent pickIntent = new Intent(Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(pickIntent, MainActivity.PICK_CONTACT);
}
});
}
/*
* (non-Javadoc)
*
* @see android.app.Activity#onActivityResult(int, int,
* android.content.Intent)
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == MainActivity.PICK_CONTACT) {
if (resultCode == Activity.RESULT_OK) {
if (null != data) {
Uri contactData = data.getData();
String displayName = this._getDisplayName(contactData);
this._phoneNumbers = this._getPhoneNumbers(displayName);
if (this._phoneNumbers.length > 1) {
this._createNumberSelectAlertDialog(displayName, this._phoneNumbers);
} else if (this._phoneNumbers.length == 1) {
this._phoneNumberTextView.setText(this._phoneNumbers[0]);
}
}
}
}
}
/*
* (non-Javadoc)
*
* @see
* android.content.DialogInterface.OnClickListener#onClick(android.content
* .DialogInterface, int)
*/
@Override
public void onClick(DialogInterface dialog, int which) {
String selectedPhoneNumber = this._phoneNumbers[which];
this._phoneNumberTextView.setText(selectedPhoneNumber);
}
/**
* コンタクトリストのURIから表示名を取得する
*
* @param contactData
* @return
*/
private String _getDisplayName(Uri contactData) {
String displayName = null;
if (null != contactData) {
ContentResolver contentResolver = this.getContentResolver();
Cursor cursor = contentResolver.query(contactData, null, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
displayName = cursor.getString(columnIndex);
cursor.close();
}
return displayName;
}
/**
* コンタクトリストから表示名で検索して、その名前に紐付いている電話番号を取得する
*
* @param displayName
* @return
*/
private String[] _getPhoneNumbers(String displayName) {
ContentResolver contentResolver = this.getContentResolver();
Cursor cursor = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + "=?",
new String[] { displayName }, null);
cursor.moveToFirst();
String[] names = new String[cursor.getCount()];
do {
int index = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String number = cursor.getString(index);
names[cursor.getPosition()] = number;
} while (cursor.moveToNext());
cursor.close();
return names;
}
/**
* 電話番号選択のダイアログを出す
*
* @param title
* @param items
*/
private void _createNumberSelectAlertDialog(String title, String[] items) {
this._alertDialogBuilder.setTitle(title);
this._alertDialogBuilder.setItems(items, this);
AlertDialog alert = this._alertDialogBuilder.create();
alert.show();
}
}


表示名を取得して、その表示名をキーにもう一回検索かけてと・・・。
なんか回りくどい。いい方法無いかな・・・。

まあ、なんで ICS も行けると思うって書いたかというと、
ContentResolver#query()
って書いたとこ。
Activity#managedQuery()にしてたんだけど API Level 15 から deprecated になったみたいで、
使わないほうがいいらしい。
ココらへんもググった情報の多くは managedQuery 使ってるサンプルが多かった。

とりあえず ContentResolver#query() にしてお茶を濁して、
Froyo 以降を対象にした場合の最適解があればそちらに移行しようかと。
コンテンツプロバイダーがなんかややこしくてわかりづらいのはぼくだけ・・・?

手持ちの Galaxy S 2.3.6 ではとりあえず動いてます。