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 information 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:
private class CallStateListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
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_RINGING
, CALL_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 needed 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:
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:
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) {
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) {
startService(intent);
buttonToggleDetect.setText("Turn off");
textViewDetectState.setText("Detecting");
}
else {
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" />
<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 here.