Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Tagged as

Detecting incoming and outgoing phone calls on Android

, 13 Mar 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
In this article I'll show you how to detect incoming and outgoing phone calls on the Android platform.

Introduction

In this article I'll show you how to detect incoming and outgoing phone calls on the Android platform. It can be useful if you need to perform some action when a call is made. For example, to block it, to log it, or send call info to a server.

This article gives step-by-step instructions on how to create a simple demo app that will detect incoming and outgoing phone calls and show a "toast" message with phone number. You can extend and use this code for your own needs.

Incoming calls

For incoming calls we need to use the TelephonyManager class and its method listen to register a listener that will receive call state, data connection, network, SIM, and other events related to telephony. We are interested only in the call state notifications. This requires android.permission.READ_PHONE_STATE permission.

So, create our listener class derived from PhoneStateListener, and override the onCallStateChanged method, as follows:

/**
* Listener to detect incoming calls. 
*/
private class CallStateListener extends PhoneStateListener {
  @Override
  public void onCallStateChanged(int state, String incomingNumber) {
      switch (state) {
          case TelephonyManager.CALL_STATE_RINGING:
          // called when someone is ringing to this phone
    
          Toast.makeText(ctx, 
                  "Incoming: "+incomingNumber, 
                  Toast.LENGTH_LONG).show();
          break;
      }
  }
}

Now I'll explain the onCallStateChanged method.

First argument - state is the call state, it can be CALL_STATE_RINGINGCALL_STATE_OFFHOOK, or CALL_STATE_IDLE. Ringing is the state when someone is calling us, offhook is when there is active or on hold call,  and idle is when nobody is calling us and there is no active call. We are interested in the ringing state.

Second argument - incomingNumber, it's the number who is calling us.

As shown in the code above, the listener shows the "toast" message with the phone number when an incoming call is ringing.

Next, get an instance of TelephonyManager and register the listener:

tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE);

When the app is no longer need to receive notifications, it must unregister a listener by call:

tm.listen(callStateListener, PhoneStateListener.LISTEN_NONE);

Outgoing calls

For outgoing calls, the system sends a broadcast action android.intent.action.NEW_OUTGOING_CALL. We need to make a broadcast receiver, that will receive the intent with this action.

To receive this broadcast, the android.permission.PROCESS_OUTGOING_CALLS permission is required.

Create the broadcast receiver class:

/**
* Broadcast receiver to detect the outgoing calls.
*/
public class OutgoingReceiver extends BroadcastReceiver {
     public OutgoingReceiver() {
     }

     @Override
     public void onReceive(Context context, Intent intent) {
         String number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
         
         Toast.makeText(ctx, 
           "Outgoing: "+number, 
           Toast.LENGTH_LONG).show();
     }
}

As with incoming calls, this code will show a "toast" message with phone number when there is an outgoing call.

Register the broadcast receiver:

IntentFilter intentFilter = new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL);
ctx.registerReceiver(outgoingReceiver, intentFilter);

We finished with the calls detection code. And now we need to create an activity that will enable/disable calls detection. It will be an activity with a simple UI, with a textview showing detection status, button to enable/disable detection, and exit button.

But here is another issue - when our activity loses focus, calls detection is disabled. To prevent this, we have to make a service that will run and that will enable detection on start, and disable on stop.

Create the service:

/**
 * Call detect service. 
 * This service is needed, because MainActivity can lost it's focus,
 * and calls will not be detected.
 * 
 * @author Moskvichev Andrey V.
 *
 */
public class CallDetectService extends Service {
    private CallHelper callHelper;
 
    public CallDetectService() {
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        callHelper = new CallHelper(this);
  
        int res = super.onStartCommand(intent, flags, startId);
        callHelper.start();
        return res;
    }
 
    @Override
    public void onDestroy() {
        super.onDestroy();
  
        callHelper.stop();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // not supporting binding
        return null;
   }
}

Create the activity.

Get the UI elements and set the onclick button handlers:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    textViewDetectState = (TextView) findViewById(R.id.textViewDetectState);
    
    buttonToggleDetect = (Button) findViewById(R.id.buttonDetectToggle);
    buttonToggleDetect.setOnClickListener(new OnClickListener() {
         @Override
         public void onClick(View v) {
             setDetectEnabled(!detectEnabled);
         }
    });
    
    buttonExit = (Button) findViewById(R.id.buttonExit);
    buttonExit.setOnClickListener(new OnClickListener() {
         @Override
         public void onClick(View v) {
             setDetectEnabled(false);
             MainActivity.this.finish();
         }
    });
}

Create the setDetectEnabled method that will toggle calls detection:

private void setDetectEnabled(boolean enable) {
    detectEnabled = enable;
 
    Intent intent = new Intent(this, CallDetectService.class);
    if (enable) {
          // start detect service 
          startService(intent);
        
          buttonToggleDetect.setText("Turn off");
          textViewDetectState.setText("Detecting");
    }
    else {
          // stop detect service
          stopService(intent);
  
          buttonToggleDetect.setText("Turn on");
          textViewDetectState.setText("Not detecting");
    }
}

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.bitgriff.androidcalls"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
    
   <!--
         Permissions required for calls detection.
        -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
    
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".CallDetectService"
            android:enabled="true"
            android:exported="false" >
        </service>
    </application>

</manifest>

Summary

I showed you how to detect incoming and outgoing phone calls on Android. It is all quite simple. Please send me your comments and suggestions.

In the next articles, I'll show you other aspects of Android platform programming (networking, threads, multimedia processing, integration with websites and webservices, etc). You can download the latest version of the source code for this article at: AndroidCalls.zip.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Андрей Москвичёв
CEO BitGriff LLC
Russian Federation Russian Federation
My name is Andrey Moskvichev.
 
I'm a software developer with more than 14 years of programming experience.
 
I specialize in networking, Unix systems (Linux, FreeBSD), mobile programming, computer graphics, software archtecture, reverse engineering, dataprocessing systems, AI, computer vision.
 
I'm interested in all new cutting edge technologies.
 
You can also look at my blog at: http://bitgriff.blogspot.ru
It's intended to share some of my knowledge about network, mobile, desktop and web programming, their integration issues and solutions.
Follow on   Twitter

Comments and Discussions

 
QuestionMy vote 5 PinmemberWuRunZhe2-Sep-14 17:16 
QuestionMy application crashing when using your code with a small addition of "writing to file" PinmemberMember 1095618718-Jul-14 8:16 
AnswerRe: My application crashing when using your code with a small addition of "writing to file" PinmemberMember 1095618718-Jul-14 10:00 
QuestionMultiple callbacks to onCallStateChanged() PinmemberSLCompulsion26-Jun-14 7:44 
QuestionDetect ringing state at outgoing call PinmemberMember 1077727625-Jun-14 11:10 
GeneralMy vote of 5 PinmemberScyalsdk13-Jun-14 5:50 
QuestionAndroid Project Control incoming messages from certain numbers Pinmembermakhondi28-Oct-13 6:46 
AnswerRe: Android Project Control incoming messages from certain numbers PinprofessionalАндрей Москвичёв30-Oct-13 21:32 
Questioncorrection of code PinmemberIsha Gupta1-Aug-13 0:59 
AnswerRe: correction of code PinprofessionalАндрей Москвичёв30-Oct-13 21:31 
QuestionSome confusing Pinmemberduong217914-Jun-13 18:13 
AnswerRe: Some confusing PinmemberАндрей Москвичёв22-Jun-13 0:08 
Questionwhy incomming call detection dosen't use ctx.registerReceiver Pinmembertieubuidoi12312-Jun-13 17:54 
Questionwhy incomming call detection dosen't use ctx.registerReceiver Pinmembertieubuidoi12312-Jun-13 17:54 
AnswerRe: why incomming call detection dosen't use ctx.registerReceiver PinmemberАндрей Москвичёв22-Jun-13 0:05 
QuestionThank you PinmemberJayarajantk29-Apr-13 23:30 
GeneralMy vote of 5 PinmemberSudhakar Shinde16-Mar-13 20:39 
GeneralRe: My vote of 5 PinmemberАндрей Москвичёв16-Mar-13 21:02 
Thank you very much!
GeneralMy vote of 5 PinmemberMihai MOGA11-Mar-13 22:50 
GeneralRe: My vote of 5 PinmemberАндрей Москвичёв12-Mar-13 8:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411019.1 | Last Updated 13 Mar 2013
Article Copyright 2013 by Андрей Москвичёв
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid