QuickContact & ContactsContract
久しぶりの投稿です。今回は軽くQuickContactを使ってみたいと思います。QuickContactを表示するのは1行で出来てしまうのですが、必要とするContactのDataを取得するのに苦しめられましたので備忘録として書いておきたいと思います
実装の要点は下記です
- Manifest xmlにContactを読むためのpermissionを記載
- Contact._IDとContact.LOOKUP_KEYを取得
- ContactsContract.Contacts.getLookupUri()の引数にContact._IDとContact.LOOKUP_KEYを渡しlookUpUriを取得
- ContactsContract.QuickContact.showQuickContact()でQuickContactを表示
- 第2引数にQuickContactのbubbleの先を表示するView(or Widgetの場合はViewのRect)を指定
- 第3引数にlookupUriを指定
気づいた点をまとめます
- ContactsContract.Contact._IDと同一なのはContactsContract.Data.CONTACT_ID。ContactsContract.Data._IDとは違う
んで実装
- Manifest xml一部
<!-- Manifest xmlにContactを読むためのpermissionを記載 --> <uses-permission android:name="android.permission.READ_CONTACTS"/>
- Activity
package com.android.practice; import android.app.ListActivity; import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import android.widget.AdapterView.OnItemClickListener; public class ContactListActivity extends ListActivity{ private static final String TAG = "ContactListActivity"; private BaseAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override protected void onStart() { super.onStart(); } @Override protected void onResume() { super.onResume(); mAdapter = new MyContactsAdapter(this); setListAdapter(mAdapter); ListView listView = getListView(); listView.setOnItemClickListener(new OnItemClickListener(){ public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //lookUpUriを取得する Uri lookupUri = ((MyContactsAdapter)mAdapter).getLookupUri(position); //ContactsContract.QuickContact.showQuickContact()でQuickContactを表示 //第2引数にQuickContactのbubbleの先を表示するView(or Widgetの場合はViewのRect)を指定 //第3引数にlookupUriを指定 ContactsContract.QuickContact.showQuickContact(getApplicationContext(), view, lookupUri, ContactsContract.QuickContact.MODE_LARGE, null); } }); } @Override protected void onPause() { super.onPause(); ((MyContactsAdapter)mAdapter).finish(); } @Override protected void onStop() { // TODO Auto-generated method stub super.onStop(); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); } public static class MyContactsAdapter extends BaseAdapter{ private static final String NO_NAME = "No name set"; private static final String NO_NUMBER = "No number set"; private Context mContext; private Cursor mCursor; public MyContactsAdapter(Context context){ mContext = context; //Contact情報を取得するためにContacts._IDを取得 //lookUpUriを取得するためにContacts.LOOKUP_KEYをcolumnを取得 mCursor = mContext.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, new String[]{ContactsContract.Contacts._ID, ContactsContract.Contacts.LOOKUP_KEY}, null, null, null); } public Uri getLookupUri(int position){ Uri result = null; if(mCursor.moveToPosition(position)){ //Contact._IDとContact.LOOKUP_KEYを取得 long id = mCursor.getLong(mCursor.getColumnIndex(ContactsContract.Contacts._ID)); String lookUpKey = mCursor.getString(mCursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); //ContactsContract.Contacts.getLookupUri()の引数にContact._IDとContact.LOOKUP_KEYを渡しlookUpUriを取得 result = ContactsContract.Contacts.getLookupUri(id, lookUpKey); } return result; } public int getCount() { Log.d(TAG, "Count: " + mCursor.getCount()); return mCursor.getCount(); } public Object getItem(int position) { return getContactInfo(position); } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { View view = null; ViewHolder holder = null; if(convertView == null){ view = ((LayoutInflater)mContext.getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(R.layout.contact_row, null); holder = new ViewHolder(); holder.mPhoto = (ImageView)view.findViewById(R.id.photo); holder.mDisplayName = (TextView)view.findViewById(R.id.display_name); holder.mNumber = (TextView)view.findViewById(R.id.number); view.setTag(holder); }else{ view = convertView; holder = (ViewHolder)view.getTag(); } ContactInfo info = getContactInfo(position); holder.mPhoto.setImageBitmap(info.mPhoto); holder.mDisplayName.setText(info.mDisplayName); holder.mNumber.setText(info.mNumber); return view; } public void finish(){ if(mCursor != null){ //Cursor objectをclose。必ずcloseする必要がある mCursor.close(); } } private ContactInfo getContactInfo(int position){ ContactInfo result = null; if(mCursor.moveToPosition(position)){ long id = mCursor.getLong(mCursor.getColumnIndex(ContactsContract.Contacts._ID)); result = new ContactInfo(); //Contact._IDをもとにPhotoを取得 result.mPhoto = getContactPhoto(id); //Contact._IDをもとにDisplay nameを取得 result.mDisplayName = getDisplayName(id); //Contact._IDをもとにPhone numberを取得 result.mNumber = getNumber(id); Log.d(TAG, "getContactInfo: mDisplayName: " + result.mDisplayName + " mNumber: " + result.mNumber); } return result; } private Bitmap getContactPhoto(long id){ Bitmap result = null; Cursor cursor = null; try{ //Contact._IDと同一なのはContactsContract.Data.CONTACT_ID。ContactsContract.Data._IDとは違う cursor = mContext.getContentResolver().query(ContactsContract.Data.CONTENT_URI, new String[]{ContactsContract.CommonDataKinds.Photo.PHOTO}, "ContactsContract.Data.CONTACT_ID = ?", new String[]{String.valueOf(id)}, null); if(cursor != null && cursor.getCount() != 0 && cursor.moveToFirst()){ Log.d(TAG, "getContactPhoto: count: " + cursor.getCount() + " id: " + id); //Photoのdataを取得 byte[] data = cursor.getBlob(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Photo.PHOTO)); if(data != null){ //byte arrayからbitmapを作成 result = BitmapFactory.decodeByteArray(data, 0, data.length, null); } } if(result == null){ result = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.icon); } }finally{ if(cursor != null){ cursor.close(); } } return result; } private String getDisplayName(long id){ String result = null; Cursor cursor = null; try{ //ContactsContract.Contact._IDと同一なのはContactsContract.Data.CONTACT_ID。ContactsContract.Data._IDとは違う cursor = mContext.getContentResolver().query(ContactsContract.Data.CONTENT_URI, new String[]{ContactsContract.Data.DISPLAY_NAME}, "ContactsContract.Data.CONTACT_ID = ?", new String[]{String.valueOf(id)}, null); if(cursor != null && cursor.getCount() != 0 && cursor.moveToFirst()){ Log.d(TAG, "getDisplayName: count: " + cursor.getCount() + " id: " + id); result = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME)); } if(result == null){ result = NO_NAME; } }finally{ if(cursor != null){ cursor.close(); } } return result; } private String getNumber(long id){ String result = null; Cursor cursor = null; try{ //ContactsContract.Contact._IDと同一なのはContactsContract.Data.CONTACT_ID。ContactsContract.Data._IDとは違う cursor = mContext.getContentResolver().query(ContactsContract.Data.CONTENT_URI, new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER}, "ContactsContract.Data.CONTACT_ID = ?", new String[]{String.valueOf(id)}, null); if(cursor != null && cursor.getCount() != 0 && cursor.moveToFirst()){ Log.d(TAG, "getNumber count: " + cursor.getCount() + " id: " + id); result = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); } if(result == null){ result = NO_NUMBER; } }finally{ if(cursor != null){ cursor.close(); } } return result; } } public static class ViewHolder{ public ImageView mPhoto; public TextView mDisplayName; public TextView mNumber; } public static class ContactInfo{ public Bitmap mPhoto; public String mDisplayName; public String mNumber; } }
下記に参考にしたsiteをリンクしておきます。
- Android Dev Site
ContactsContract.QuickContact
ContactsContract
ContactsContract.Data
ContactsContract.PhoneLookup
- Other
stackoverflow-widgetでQuickContactを表示する方法
Working with Android Contacts