contentホームJava【Android】現在のActivityスタックの状態を確認したいAndroidアプリ開発をしていると、現在のActivityスタック(画面の重なり)を確認したくなることありませんか。Androidは画面を開いていくとスタック方式でどんどん上に画面が重なっていき、バックキーを押すと上から順に画面が破棄されていく仕組みになっています。実際に複雑な画面遷移を実現してみようと試行錯誤していると今のActivityスタックの状態が分からなくなったりします。スタックの状態をダンプしてみるといいと思います。USBで端末を繋いで以下のコマンドを叩くとダンプできます。activityただ、このコマンドは出力される情報量が膨大です。そこで、上記コマンドの結果に対して更にgrepをかけて、起動しているタスクとアクティビティの一覧だけ表示されるようフィルタリングすると見やすくなります!コマンド例は以下です。#[0-9]*:"標準のマップアプリを起動して上記コマンドを実行したときの結果はこんな感じになります。所属していることを表しています。その可能性AndroidSDKは端末内部のアドレス帳へアクセスするためのインターフェースとなるContactsAPIを用意しています。端末内連絡先という重要なリソースへのアクセスを担うContactsAPIはアプリ開発の幅を広げるためには重要なAPIではないでしょうか。このAPIの仕様は煩雑で癖が強いです。直感的に欲しいデータにアクセスできませんし、書き込みもできません。根本的なContactsAPIの概念的な部分を分かっていないとちょっとイライラすると思います。似ているアドレス情報の連絡先を勝手に集約してまとめるような仕組みがAndroidOSレベルで用意されていたりするため開発者の混乱を招く原因になっていたりします。データにアクセスするためのキー項目の特徴を知っていないと思わぬことが起きたりします。ネット上に散らばっているサンプルソースを取り敢えず動かしてみて「何かよく分からないけど欲しいデータが取れた!」「でもホントはこういうデータを取り出したいんだけどどう書けばいいか分からない」というケースが結構想定されるAPIなのではないかなーと思います。ContactsAPIについての抑えるべきポイントと概要を説明していきます。Androidではアドレス帳をどういった形態で保持しているかAndroid内部ではSQLiteに連絡先データが保存されているようです。そのSQLiteデータベースに直接アクセスすることはできません。そこでアクセスインターフェースとしてContactsAPIが用意されています。ContactsAPIもかなりSQLite側を意識した作りになっているため、アクセスの仕方自体はほぼ変わりはないです。アドレス帳データのSQLiteのテーブル設計はどうなっているかAndroid内部のDB設計が分かっていないばかりに以前苦労した記憶があります。「何かよく分からないけど欲しいデータが取れた」状態で使っていましたが、テーブル構成が分かった瞬間にかなり道がひらけました。これをもっと早く知っていればよかった...と思いましたが、同じ思いをする人が一人でも減ってくれることを願いER図を用意しました。※緑のフィールドは外部キーです。主要なフィールドのみ載せています。SQLiteは全てのテーブルに_idという一意のサロゲートキーを必ず持ちますが、ContactsAPIにおいてもSQLiteシステムの_idを主キーとして利用しています。全てのテーブルに_idがあるという点が一つのポイントとなります。それではテーブルごとに概要を説明していきます。dataテーブル上記ER図中では最小単位となるテーブルで、行ごとに電話番号やEメールアドレスといった実データが保存されています。ER図の関係の通り一つのraw_contactsレコードに所属するデータが複数あり、データの数だけdataレコード沢山があります。そのデータ種別を区別するためにMIMEタイプというフィールドが用意されています。種類についてはContactsContract.CommonDataKindsのリファレンスを参照してください。data2といったフィールドに格納されています。MIMEタイプごとにそれぞれのdataが何を表すかということが決められています。電話番号の場合はdata1に電話番号、data2に種別(自宅や勤務先)、data3にラベルが格納されています。MIMEタイプごとのdataフィールド群の対応については、先ほどのContactsContract.CommonDataKindsのリファレンスからたどって調べれば分かると思います。raw_contactsテーブルdataテーブルにある一人分の名前や電話番号のデータレコードを一つにまとめます。1レコードで一人分のデータを表現します。直訳で生のコンタクトテーブルになり、後述のコンタクトテーブルよりもより直接的なデータとなります。アカウント名やアカウントタイプといったフィールドもありますが、これは外部のクラウドストレージサービスの情報になります。自分のGoogleアカウントやDocomoアカウントと紐付けて保存されていたりします。contactsテーブルこのテーブルがクセモノです。いくつかのraw_contactsテーブルのレコードを更にまとめます。いうことかというとAndroidには似ている連絡先情報を自動で集約する仕組みが備わっており、ある基準で似ている連絡先と判断された連絡先を一つにまとめるためにこのテーブルは用意されています。いくつかの似ているrow_contactsレコードをひとまとめにしてcontactsレコードを持つことがあるということです。この集約は恒久的なものではなく自動的に集約が解除されたりもします。何を持って似ているかという判断基準はOSでちゃんと定められています。姓名がそれぞれ一致したとか、姓だけ一致したら更にうんにゃらとか。興味がある人は調べてみるとよいでしょう。いった仕組みが用意されている意味としては、raw_contactsテーブルでは複数のアカウントの情報を持つ関係上、クラウドの連絡先と同期をとった時に似たような同一人物のデータが複数端末内にできてしまうため可能な限りそれを一括りにまとめようというような目的のようです。一般的にユーザーに連絡先データを表示する場合はcontactsテーブルのレベルで見せるべきです。そのためのビューも提供されています。普通に考えて一人を特定するためのキーとしてはcontactsテーブルの_id(contacts_id)があればよいこととなります、が、集約機能のための弊害があります。自動集約でレコードがまとめられる時にcontacts_idが変わってしまうことがあります。contacts_idをユーザーを特定するための恒久的なキーとして利用すべきではありません。恒久的に1ユーザーを特定するためにはどうするのか。そのためにルックアップキーというものが用意されています。ユーザーへの参照をアプリ内で持っておきたい場合はこのキーを保持しておくのがよいでしょう。このキーにもデメリットがありますので、次の項の中で解説します。プログラムコードサンプル実際にコードサンプルを紹介していきます。アドレス帳内の全コンタクトにループ処理でアクセスするループで全ユーザーにアクセスします。上記ER図でいうところのcontactsテーブルへのアクセスになります。displayName);}ルックアップキーで特定のユーザーの表示名を取得するコード例ルックアップキーは基本的に固定の検索キーで、ユーザーを特定するためのキーとしては最適ですが検索キーとしての高速性に欠けます。以下がルックアップキーのみでUriを作成し名前を取得する例です。ループで大量に処理をしたりしないのであればこの方法でも問題ないでしょう。c.close();}ルックアップキーとコンタクトIDを組み合わせたユーザー検索contacts_idによる高速な検索とルックアップキーによる確実な検索の2つのメリットを合わせたユーザー検索方法が予め用意されています。contacts_idでの検索を試みて、失敗した場合はルックアップキーを利用した検索を行なってくれます。大量にデータを処理する場合はこの方法でUriを作成すべきです。lookupKey);Dataテーブルの実データの取得contacts_idを元に電話番号を取得してみます。一人に対して複数の電話番号が設定されている場合があるのでカーソルループで取得します。TYPEで絞り込んでいます。cursor.close();}ContactsAPIまとめテーブル構成と自動集約に伴う罠はありますが、逆にいうとそこら辺さえ抑えればさほど難しくないと思います。テーブル構成さえ分かっていれば上記で載せたサンプルコード以外にも色々と応用したアドレス帳アクセスもできるかと思います。あと今回はサンプルコードを載せませんでしたが、プロフィール画像についてもDataテーブル内にBlobで直接格納されています。探せばサンプルあるはずです。それではよいContactsAPIライフを。データベースCharSequenceはインターフェースString型を指定したい部分にCharSequenceって出てきたのでなによと思ったのですが、どうやらインターフェースみたいです。公式リファレンスを見てみると以下のような説明が書かれています。シーケンスへの統一された読み取り専用アクセスを提供します。ちなみにこのインターフェースを実装しているクラス一覧は以下の通り。StringCharBufferStringBufferStringBuilderたまに引数の型で出てくるので覚えておくといいかもしれません。31Author明日を今日より生きやすく。johnregan3.ホーム。