Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art

Doing Something When the Phone Rings

Author: Johan Pelgrim -- Published? true -- FormatLanguage: W

Problem:

You want to act on an incoming phone call and do something with the incoming number.

Solution:

This can be achieved by implementing a Broadcast receiver and listening for a TelephonyManager.ACTION_PHONE_STATE_CHANGED action.

Discussion:

If you want to do something when the phone rings you have to implement a broadcast receiver which listens for the TelephonyManager.ACTION_PHONE_STATE_CHANGED intent action. This is a broadcast intent action indicating that the call state (cellular) on the device has changed.

1. Create a class IncomingCallInterceptor which extends BroadcastReceiver.

2. Override the onReceive method to handle incoming broadcast messages.

3. The EXTRA_STATE intent extra in this case indicates the new call state.

4. If (and only if) the new state is RINGING, a second intent extra EXTRA_INCOMING_NUMBER provides the incoming phone number as a String.

5. We extract the number information from the EXTRA_INCOMING_NUMBER intent extra.

Note: Additionally you can act on a state change to OFFHOOK or IDLE when the user picks up the phone or ends/rejects the phone call respectively.

package nl.codestone.cookbook.incomingcallinterceptor;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.widget.Toast;

public class IncomingCallInterceptor extends BroadcastReceiver {                                    // 1

    @Override
    public void onReceive(Context context, Intent intent) {                                         // 2
        String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);                         // 3
        String msg = "Phone state changed to " + state;
        
        if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) {                                   // 4
            String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);  // 5
            msg += ". Incoming number is " + incomingNumber;
            
            // TODO This would be a good place to "Do something when the phone rings" ;-)
            
        }
        
        Toast.makeText(context, msg, Toast.LENGTH_LONG).show();

    }

}

6. We have to register our IncomingCallInterceptor as a <receiver> within the <application> element in the AndroidManifest.xml file.

7. We register an <intent-filter> ...

8. and an <action value which registers our receiver to listen for TelephonyManager.ACTION_PHONE_STATE_CHANGED broadcast messages.

9. Finally we have to register a <uses-permission> so we are allowed to listen to phone state changes.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="nl.codestone.cookbook.incomingcallinterceptor"
    android:versionCode="1"
    android:versionName="1.0">
    <uses-sdk android:minSdkVersion="3" />

    <application android:icon="@drawable/icon" android:label="Incoming Call Interceptor">

        <receiver android:name="IncomingCallInterceptor">                     // 6
            <intent-filter>                                                   // 7
                 <action android:name="android.intent.action.PHONE_STATE"/>   // 8
            </intent-filter>
        </receiver>

    </application>

    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>     // 9
    
</manifest>

If all is well you should see something like this when the phone rings:

What happens if two receivers listen for phone state changes?

In general, a broadcast message is just that, a message which is sent out to many receivers at the same time. This is the case for normal broadcast messages which is used to send out the ACTION_PHONE_STATE_CHANGED intent as well. All receivers of the broadcast are run in an undefined order, often at the same time and for that reason order is not applicable.

In other cases the system sends out ordered broadcast which is described in more detail in the Recipe Process outgoing calls.

Final notes

When your BroadcastReceiver does not finish within 10 seconds the Android framework will show the infamous Application Not Responding (ANR) dialog, giving your users the possibility to kill your program. If you need to do some processing which takes longer than 10 seconds implement a Service and call the service method.

It is also not advised to start an activity from a BroadcastReceiver, as it will spawn a new screen that will steal focus from whatever application the user is currently has running. If your application has something to show the user in response to an Intent broadcast, it should do so using the Notification Manager.

See Also:

Recipe Process outgoing calls http://developer.android.com/reference/android/content/BroadcastReceiver.html http://developer.android.com/reference/android/telephony/TelephonyManager.html#ACTION_PHONE_STATE_CHANGED

Download:

The source code for this project can be downloaded from https://github.com/downloads/jpelgrim/androidcookbook/IncomingCallInterceptor.zip.

Download:

The source code for this project is in the Android Cookbook repository at http://github.com/IanDarwin/Android-Cookbook-Examples, in the subdirectory TelephonyManager.
jpelgrim 2011-05-05 01:15:57.565 Hi Todd, Sorry for the late reply. I received your comments via e-mail, but didn't see them on the website (they had to be moderator approved by Ian), so I couldn't respond earlier. Thanks for the compliments and kudos for yourself for finding a solution for your technical problem ;-) Sometimes a good old restart or "Project... clean" will magically fix things for you. Which sounds a bit scary in my opinion, but still... problem solved (by you!) Cheers, Johan
todd.deland 2011-04-28 11:40:10.305 Got it working, not sure what I did, but works great now. My logcat had errors about "bad process" so I ended up restarting Eclipse and it went away. Thanks for the great tutorial!
todd.deland 2011-04-28 10:52:50.626 Great tutorial! I copy/pasted and I can't get it to work :( It installs fine, and even trying to debug no break points hit (but will they in a BroadcastReceiver?) Any tips?