Xamarin.Android 電話の発信検知と通話履歴の取得
1 発信検知
(1) NEW_OUTGOING_CALL

電話アプリは、発信時に「NEW_OUTGOING_CALL」をブロードキャストします。
ブロードキャストレシーバで、これをフックすれば、発信を検知することが可能です。
[BroadcastReceiver] [IntentFilter(new[] { "android.intent.action.NEW_OUTGOING_CALL" })] public class PhoneStateReceiver : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { //発信される電話番号の取得 var number = intent.GetStringExtra(Intent.ExtraPhoneNumber); Toast.MakeText(context, "発信中 : "+ number, ToastLength.Short).Show(); } }
なお、NEW_OUTGOING_CALLを受け取るためには、パーミッションPROCESS_OUTGOING_CALLSが必要です。
(2) 発信停止

特定の番号への発信をキャンセルするには、InvokeAbortBroadcast()でブロードキャスト自体を止めます。
[BroadcastReceiver] [IntentFilter(new[] { "android.intent.action.NEW_OUTGOING_CALL" })] public class PhoneStateReceiver : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { var number = intent.GetStringExtra(Intent.ExtraPhoneNumber); //発信先が「123」の場合、発信をキャンセルする if (number == "123"){ ResultData = null; InvokeAbortBroadcast(); //ブロードキャストを停止する Toast.MakeText(context, number + " への発信をキャンセルしました。", ToastLength.Short).Show(); } } }
2 通話履歴の取得


コンテンツリゾルバで、CallLog.Calls.ContentUri を指定して通話履歴を取得できます。
下記のサンプルでは、取得した日付がJava.Util.Dataなので、使い慣れた.NetのSystem.DateTimeに変換しています。
(1)Java.Util.Data
1970-01-01 00:00:00からのミリ秒単位の経過時間
(2)System.ateTime
0000-01-01 00:00:00からのマイクロ秒単位の経過時間
var cursor = ContentResolver.Query(CallLog.Calls.ContentUri, null, null, null,CallLog.Calls.DefaultSortOrder); var sb = new System.Text.StringBuilder(); if (cursor.MoveToFirst()){ do{ // 通話先 var name = cursor.GetString(cursor.GetColumnIndex(CallLog.Calls.CachedName)); if (name == null){ name = "登録なし"; } // 電話番号 var number = cursor.GetString(cursor.GetColumnIndex(CallLog.Calls.Number)); // 日時 var ms = cursor.GetLong(cursor.GetColumnIndex(CallLog.Calls.Date)); // JavaのDateで取得されたものを.NeのDateTimeに変換する(必須ではありません) const long epochValue = 62135596800000L; //0000年から1970年までのミリ秒 ms = (ms + epochValue)*10000; var dt = new DateTime(ms); // 通話種別 var calltype = cursor.GetString(cursor.GetColumnIndex(CallLog.Calls.Type)); if (calltype == "1"){ calltype = "着信"; } else if (calltype == "2"){ calltype = "発信"; } else if (calltype == "3"){ calltype = "不在着信"; } sb.Append(String.Format("{0} {1} {2} {3}\r\n", dt.ToString("g"), calltype, name, number)); } while (cursor.MoveToNext()); } FindViewById<TextView>(Resource.Id.textViewLog).Text = sb.ToString();
通話履歴へのアクセスには、パーミッションREAD_CONTACTSが必要です。