mucchinのAndroid戦記

Androidアプリからの通話ログの取得方法

Androidアプリから、端末の通話ログを取得する方法は?

Androidアプリでは、他のアプリケーションの情報を、コンテントプロバイダと呼ばれる機構を使って取得する事が出来ます。(用意されていれば。)
通話ログとは、着信履歴、発信履歴、不在着信履歴の事ですが、この通話ログの情報も、自分で作るAndroidアプリケーションから取得する事ができます。


Androidアプリの通話ログの取得方法

それでは、サンプルコードとともに、通話ログの取得方法を見てみましょう。
以前の記事でもちらほらと紹介していますが、getContentResolver().query()というメソッドを使います。


Cursor c = getContentResolver().query(
         CallLog.Calls.CONTENT_URI,
         projection,
         selection,
         selectionArgs,
         order
       );
引数の説明をしていきます。
第一引数は、情報を取得するAndroidアプリを示すURIを指定します。
通話ログの場合は、CallLog.Calls.CONTENT_URIとなります。
通話ログ以外にも、他にもたくさん用意されています。(下記参照)
Androidのコンテントプロバイダで使えるURI一覧(1)
Androidのコンテントプロバイダで使えるURI一覧(2)
Androidのコンテントプロバイダで使えるURI一覧(3)
第二引数のprojectionは、取得する情報の配列を指定します。
イメージは、SQLのSELECT句に該当します。
例えば、以下のように指定します。
String[] projection =
      new String[]{CallLog.Calls.TYPE,CallLog.Calls.NUMBER,};
指定できる情報は、下記の通りです。(CallLog.CallsクラスのAPIリファレンスより)
CACHED_NAME
その通話履歴が発生した段階で、その番号に紐付いたコンタクト(電話帳)があれば、その電話帳で登録していた名前が取得できます。
但し、履歴発生後に、電話帳のデータを変えてもすぐには反映されないようです。
英語で書いているAPIリファレンスにも、それらしき事が記述されています。
例えば、「080-xxxx-xxxx」という番号で、Aさんを電話帳に登録していたとして、発信しますと、
その後は、「A」という名前が残っています。
その後、電話帳で「A」さんの番号を「080-yyyy-yyyy」へ変えても、そのまま通話ログでは「080-xxxx-xxxx」に対する名前は、「A」と出てます。
ですが、電話帳変更後、一度発着信すると、その時点で全て?の履歴に反映されるみたいです。
この動作は正しい仕様なのかどうか不明ですが・・・。
なお、紐付いてる名前が無いときは、nullが返されます。

CACHED_NUMBER_LABEL
先ほどのCACHED_NAME同様の仕様ですが、電話帳の名前ではなく「カスタムナンバータイプ」です。何かと言いますと、以下の画面の「Costom」に当たる文字列です。

電話帳の編集時、電話番号の左側をクリック(タップ)すると、番号のラベルを選択できますが、そのときに「カスタム」を選択すると、任意の文字列を打ち込む事ができますが、その文字列が取得できます。

CACHED_NUMBER_TYPE
先ほどのCACHED_NUMBER_LABEL同様の仕様ですが、「カスタム」ではなくて、「自宅」「勤務先」等のあらかじめ用意されているものを指定した場合に、それを示す数値が取得できます。
しかし、APIリファレンスにはどれがいくつって情報がまるで書いてないですね。
仕方ないので動かしましたら、以下のような感じでした。


自宅:1 / 携帯:2 / 勤務先:3 / FAX(勤務先):4
FAX(自宅):5 / ポケベル:6 / その他:7
コールバック:8 / クルマ:9 / 会社代表番号:10
ISDN: 11 / メイン:12 / FAX(その他):13
無線:14 / テレックス:15 / TTY TTD:16
携帯電話(勤務先):17 / ポケベル(勤務先):18
アシスタント:19 / MMS:20 / カスタム:0
以上ですかね。めちゃくちゃ種類あるし!
何のことだかわからないものもありますね。
TTYは確か、耳が聞こえない方の為の機器だったような記憶があります。
スマートフォンの時代にポケベルは使わないだろうと思いましたが(笑)

DATE
その履歴発生時の時間です。
「milliseconds since the epoch」とAPIリファレンスに記載されています。
epochとは、「起源」とかそういう意味ですので、Android端末のほんとに最初の時間からの経過時間をミリセカンド秒単位で返す、という事です。
新しい順に取得したいとか、古い順に取得したい場合は、このDATEを、後述のOrderで指定します。

DURATION
通話時間の秒数を取得できます。

NEW
APIリファレンスでは、「Whether or not the call has been acknowledged」と書いてます。
不在着信、着信、発信をAndroidエミュレータで試したのですが、全て「1」でした。
こちらから発信して、相手側が出なかった場合に「0」になるのかもしれません。
実機をお持ちの方はお試し下さい・・・。
結果を教えてくれたら更に嬉しいです。

「NEW」の件ですが、親切な方からコメントを頂きました。
確認済みの不在着信の場合に「0」になります。
その他の場合、例えばこちらから発信した場合や、通話した着信、確認をしていない不在着信は「1」になります。

NUMBER
その履歴の電話番号を文字列として取得できます。

TYPE
発信、着信、不在着信のいずれかを示す数値を取得できます。
数値は、CallLog.Callsクラスの定数として用意されています。
OUTGOING_TYPE・・・発信
INCOMING_TYPE・・・着信
OUTGOING_TYPE・・・不在着信

長くなりましたが、第二引数の説明は以上です。


スポンサーリンク




第三引数、第四引数は、取得するレコードの条件を指定します。
例えば以下のような感じです。
String selection =
  CallLog.Calls.NUMBER + ” = ” + phonenumber ;
上記のselectionを第三引数に使いますと、phonenumberという変数に設定している電話番号だけの履歴を取得するという意味合いになります。
上記の場合は、第四引数はnullでOKです。

ちなみに第四引数は、第三引数に「?」を使用する場合に使います。
例えば、以下のようにします。


String selection =
  CallLog.Calls.NUMBER + ” =?”;

String[] selectionArgs =
  new String[] {“09011111111″,”09022222222”};


query()メソッドの第3引数に上記のselection、第四引数にselectionArgsを指定すると、電話番号が、09011111111か09022222222の履歴のみが取得できます。
第五引数は、データ取得時の順番です。
例えば、以下のようにします。
String order = CallLog.Calls.DATE + ” desc”;
このorderをquery()メソッドの第五引数に指定するとDATEの降順、つまり新しい順に通話ログのデータを取得する、という事になります。
上記のように、引数を思いのままに指定して、getContentResolver().query()を実行し、戻り値として得られるCursorインスタンスとして、通話ログの一覧を取得できます。

Cursorインスタンスの操作方法は、SQLiteと全く同じです。
下記の記事の「Cursorインスタンスの使い方」というところを見てください。
Androidアプリのデータ保存方法の一つ「SQLite」の使い方 レコード検索編

ちなみに、レコードのカラム毎のデータを取得する場合、データの型に応じてメソッドを変えなければなりません。
getString()で取得するカラム
CACHED_NAME / CACHED_NUMBER_LABEL / NUMBER
getInt()で取得するカラム
CACHED_NUMBER_TYPE / DATE / DURATION / NEW / TYPE
※DATE、DURATIONはgetLong()の方がいいかもしれません。
※TYPEはgetBoolean()の方がいいかもしれません。


なお、CallsLog.Call(通話ログ)のコンテントプロバイダを使用するときは、実装するAndroidアプリにパーミッションの設定が必要になります。
下記を参照してください。
通話ログのパーミッション