Forum Xamarin.Android

How to get call information after every incoming/outgoing call in the Xamarin Android?

I would like to receive call details such as number, name (if saved in contacts), dialed/received number, call duration, received/dialed date and time after every incoming and outgoing call.

I have created a phone call watcher class subscribed to base class BroadcastReceiver like below:

using Android.App;
using Android.Content;
using Android.Telephony;

[BroadcastReceiver()]
[IntentFilter(new[] { "android.intent.action.PHONE_STATE", "android.intent.action.NEW_OUTGOING_CALL" }, Priority = (int)IntentFilterPriority.HighPriority)]
public class PhoneCallWatcher : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        // ensure there is information
        if (intent.Extras != null)
        {
            if (intent.Action.Equals(Intent.ActionNewOutgoingCall))
            {
                //outgoing call
            }

            // get the incoming call state
            string state = intent.GetStringExtra(TelephonyManager.ExtraState);

            // check the current state
            if (state == TelephonyManager.ExtraStateRinging)
            {
                // read the incoming call telephone number...
                string telephone = intent.GetStringExtra(TelephonyManager.ExtraIncomingNumber);
                // check the reade telephone
                if (string.IsNullOrEmpty(telephone))
                    telephone = string.Empty;
            }
            else if (state == TelephonyManager.ExtraStateOffhook)
            {
                // incoming call answer
            }
            else if (state == TelephonyManager.ExtraStateIdle)
            {
                // incoming call end
            }
        }
    }
}

and registering above service in MainActivity.cs like below:

//starting phone call watcher service
var phoneCallWatcherIntent = new Intent(ApplicationContext, typeof(PhoneCallWatcher));
SendBroadcast(phoneCallWatcherIntent);

But the above code is not working when I make an outgoing call and receive an incoming call. Please help!

Best Answer

  • thaufeethaufee Member ✭✭
    edited April 2019 Accepted Answer

    It seems it is NOT that easy to read phone call logs from the BroadcastReceiver. Hence, the best way to read phone call logs is from the Android Database through Cursor.

    Below is the code snippet for Xamarin.Android:

    private async Task CheckAndUpdatePhoneCalls(Context context)
    {
        string lastReadTimeMilliseconds = Application.Current.Properties["LastPhoneCallReadMilliseconds"].ToString();
        ICursor cursor = context.ContentResolver.Query(CallLog.Calls.ContentUri, null, CallLog.Calls.Date + " > ?", new string[] { lastReadTimeMilliseconds }, CallLog.Calls.Date + " ASC limit 100");
    
        if (cursor != null)
        {
            int totalCalls = cursor.Count;
    
            if (cursor.MoveToFirst())
            {
                double maxReceivedTimeMilliseconds = 0;
    
                for (int j = 0; j < totalCalls; j++)
                {
                    long calledTimeMilliseconds = long.Parse(cursor.GetString(cursor.GetColumnIndexOrThrow(CallLog.Calls.Date)));
                    string dialedNumber = cursor.GetString(cursor.GetColumnIndexOrThrow(CallLog.Calls.Number));
                    int callDuration = int.Parse(cursor.GetString(cursor.GetColumnIndexOrThrow(CallLog.Calls.Duration)));
                    string callerName = cursor.GetString(cursor.GetColumnIndexOrThrow(CallLog.Calls.CachedName));
                    int callType = int.Parse(cursor.GetString(cursor.GetColumnIndexOrThrow(CallLog.Calls.Type)));
    
                    //you can process this phone call here
    
                    if (maxReceivedTimeMilliseconds < smsReceivedTimeMilliseconds) maxReceivedTimeMilliseconds = smsReceivedTimeMilliseconds;
                    cursor.MoveToNext();
                }
    
                //store the last phone call read date/time stamp to the application property so that the next time, we can read phone call processed after this date and time stamp. 
                if (totalSMS > 0)
                {
                    Application.Current.Properties["LastPhoneCallReadMilliseconds"] = maxReceivedTimeMilliseconds.ToProperString();
                }
            }
            cursor.Close();
        }
    }
    

Answers

  • thaufeethaufee Member ✭✭
    edited April 2019 Accepted Answer

    It seems it is NOT that easy to read phone call logs from the BroadcastReceiver. Hence, the best way to read phone call logs is from the Android Database through Cursor.

    Below is the code snippet for Xamarin.Android:

    private async Task CheckAndUpdatePhoneCalls(Context context)
    {
        string lastReadTimeMilliseconds = Application.Current.Properties["LastPhoneCallReadMilliseconds"].ToString();
        ICursor cursor = context.ContentResolver.Query(CallLog.Calls.ContentUri, null, CallLog.Calls.Date + " > ?", new string[] { lastReadTimeMilliseconds }, CallLog.Calls.Date + " ASC limit 100");
    
        if (cursor != null)
        {
            int totalCalls = cursor.Count;
    
            if (cursor.MoveToFirst())
            {
                double maxReceivedTimeMilliseconds = 0;
    
                for (int j = 0; j < totalCalls; j++)
                {
                    long calledTimeMilliseconds = long.Parse(cursor.GetString(cursor.GetColumnIndexOrThrow(CallLog.Calls.Date)));
                    string dialedNumber = cursor.GetString(cursor.GetColumnIndexOrThrow(CallLog.Calls.Number));
                    int callDuration = int.Parse(cursor.GetString(cursor.GetColumnIndexOrThrow(CallLog.Calls.Duration)));
                    string callerName = cursor.GetString(cursor.GetColumnIndexOrThrow(CallLog.Calls.CachedName));
                    int callType = int.Parse(cursor.GetString(cursor.GetColumnIndexOrThrow(CallLog.Calls.Type)));
    
                    //you can process this phone call here
    
                    if (maxReceivedTimeMilliseconds < smsReceivedTimeMilliseconds) maxReceivedTimeMilliseconds = smsReceivedTimeMilliseconds;
                    cursor.MoveToNext();
                }
    
                //store the last phone call read date/time stamp to the application property so that the next time, we can read phone call processed after this date and time stamp. 
                if (totalSMS > 0)
                {
                    Application.Current.Properties["LastPhoneCallReadMilliseconds"] = maxReceivedTimeMilliseconds.ToProperString();
                }
            }
            cursor.Close();
        }
    }
    
  • jezhjezh Member, Xamarin Team Xamurai

    Congrats, and thanks for sharing the answer.

Sign In or Register to comment.