2011年8月6日土曜日

[Android] 2.1以上の電話帳(つまりContacts)とたたかってみるんだぜ その1

電話帳って2.1から変更されたんですよね。
ゆえにそんなにリファレンスサイトがないので自分でどーこーしてみることにした。
某会議でよく電話帳が話題になるので
まー、興味がでたっていえばでたんですけど。

Androidでは電話帳DBなるものが標準で搭載されている。
/data/data/com.android.providers.contacts/databases/contacts2.db
という場所にあったりする。
実際にデータをpullなどでぬいてきて
SQLite3のビューアーとかでみるとたしかにデータがはいっている。

が、これがすごくわかりづらい。
一回に解説したいですが、私にもわかってない箇所があるので
まー、それはゆっくりと。
とりあえず2.1からでは「ごっそりと仕組みが変わった」ということを覚えていただきたいです。
覚えなくてもいいけど。

では、簡単につかってみましょう。
前提条件として電話帳にこんな感じのデータをいれておきます。



















これは標準電話帳の画面です。
で、最終的にこんな感じにする。



















今回はかるーくテストなんで名前だけの表示にしています。
本来なら、下に電話番号をだすなり、メアドだすなり好きにしていいんですが
仕事中の休み時間にできることは限られているので(1時間しかない)。
時間があればそのうちハイパーなものをつくりたんですが、はてさて。

では本日のコードです。

まずはレイアウトのXMLを。

  1. <!--xml version="1.0" encoding="utf-8"?-->  
  2. <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent">  
  3.     <listview android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/listView"></listview>  
  4. </linearlayout>  

簡単にListViewだけを表示しているのでこれだけです。
つづいてはこちらに名前を入れるコード。

  1. import android.app.Activity;  
  2. import android.database.Cursor;  
  3. import android.os.Bundle;  
  4. import android.provider.ContactsContract;  
  5. import android.widget.ArrayAdapter;  
  6. import android.widget.ListView;  
  7.   
  8. public class AddressListActivity extends Activity {  
  9.    
  10.  private ListView mListView;  
  11.    
  12.  @Override  
  13.     public void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         setContentView(R.layout.address_list);  
  16.           
  17.         // 表示  
  18.         mListView = (ListView) findViewById(R.id.listView);  
  19.         mListView.setAdapter(displayNameList());  
  20.     
  21.  }  
  22.    
  23.  // DBから取り出してごにょっとする  
  24.  private ArrayAdapter<string> displayNameList() {  
  25.     
  26.   // DBアクセス  
  27.   databaseAccess access = new databaseAccess(this);  
  28.   Cursor cursor = access.selectAllAddress();  
  29.     
  30.   cursor.moveToFirst();  
  31.   ArrayAdapter<string> adapter = new ArrayAdapter<string>(this,android.R.layout.simple_list_item_1);  
  32.     
  33.   // Contactsのデータを管理しているRAW_CONACT_ID  
  34.   int idIndex = cursor.getColumnIndexOrThrow(ContactsContract.Data.RAW_CONTACT_ID);  
  35.   // 表示名  
  36.   int nameIndex = cursor.getColumnIndexOrThrow(ContactsContract.Data.DISPLAY_NAME);  
  37.   // idにとりあえずの初期値を入れておく  
  38.   int id = 0;  
  39.     
  40.   while (!cursor.isAfterLast()) {  
  41.    // idが変わったら次の人  
  42.    if(id != cursor.getInt(idIndex)) {  
  43.     // idの入れ替え  
  44.     id = cursor.getInt(idIndex);  
  45.     // 表示名取得  
  46.     adapter.add(cursor.getString(nameIndex));  
  47.       
  48.       
  49.    }  
  50.    cursor.moveToNext();  
  51.   }  
  52.     
  53.   cursor.close();  
  54.     
  55.   return adapter;  
  56.     
  57.     
  58.     
  59.  }  
  60.    
  61. }  
  62. </string></string></string>  

コメントいれてあるのですが、実は上のコードにはDBにアクセスする処理はございません。
アクセスするにはこちらのコードを。
別にクラスを分ける必要性はなかったのですが、
あとあと入力とかを拡張しようと思っていたのでわけました。

  1. import android.content.Context;  
  2. import android.database.Cursor;  
  3. import android.net.Uri;  
  4. import android.provider.ContactsContract;  
  5.   
  6. public class databaseAccess {  
  7.    
  8.  private Context context;  
  9.  private Uri uri = ContactsContract.Data.CONTENT_URI;  
  10.    
  11.  // コンストラクタ  
  12.  public databaseAccess(Context context){  
  13.   this.context = context;  
  14.     
  15.  }  
  16.    
  17.  /** 
  18.   * DB全件返しメソッド 
  19.   * @return 
  20.   */  
  21.  public Cursor selectAllAddress() {  
  22.   return context.getContentResolver().query(uri, nullnullnullnull);  
  23.  }  
  24.   
  25. }  

クエリのつかいかたですが、

  1. Cursor android.content.ContentResolver.query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)  

という記述がDevelopersなんとかっていう解説書(もう忘れた)にあります。
場所を指定して、取り出すものを指定。さらに条件・・・といったところでしょうか。
今回は簡易なのでいやでも全件返すようにしています。

全件返すことでもちろん名前以外にも電話番号まで帰ってきているので

  1. while (!cursor.isAfterLast()) {  
  2.  // idが変わったら次の人  
  3.  if(id != cursor.getInt(idIndex)) {  
  4.   // idの入れ替え  
  5.   id = cursor.getInt(idIndex);  
  6.   // 表示名取得  
  7.   adapter.add(cursor.getString(nameIndex));  
  8.     
  9.     
  10.  }  
  11.  cursor.moveToNext();  
  12. }  

このあたりのところでいろいろ分岐させています。
IDは一人につき1つなので、そのIDが切り替わったら次の人。
同じIDが名前を2回もっていることもあるのでこういう重複チェックをかけています。
なぜ名前を2回もっているのかというと・・・

「ID」「表示名」「電話番号」
「ID」「表示名」「苗字」

というようなデータ構造になっているためです。
表示名は何回もはいってくるのですね(汗)


なのでまわりくどいコードになっています。
このあたりは私の調査不足なのでおいおいかっこいいコードに(そりゃもう鼻血がでるほど)していけたらいいなーとおもいますがな。


そんな感じで第一回電話帳会議終了。

ではもどるぞ!!だいじゅうよんてい(ry)

はい、仕事します。

0 件のコメント:

コメントを投稿