SIN@SAPPOROWORKSの覚書

C#を中心に、夜な夜な試行錯誤したコードの記録です。

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

【 Xamarin 記事一覧 】

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が必要です。


【 Xamarin 記事一覧 】