Skip to content

Relationship between Receivers, Intents, and Activities/Services

December 28, 2009

Hey everyone,

Thought I would devote this post towards helping people set up receivers, sending intents around, and starting services.

By the end of this post, the goal is to familiarize you with the concept of a “receiver” and how they are typically (at least in my experience) used in Android.

Google’s Android uses the concept of a receiver and the concept of “broadcasting” intents to help you essentially listen for certain actions that occur on the phone. You can implement a receiver to listen to your own intents which you might send around internally within your application (i.e. perhaps a change was made to one of your application’s data sets and you want to broadcast this to your receiver and have the receiver do some additional work), but again, in my experience receivers are most often used to listen to intents which are broadcasted by the system itself! (For a list of which actions are broadcasted take a look at and scroll down to the Summary section and check out which actions are “Activity” actions and which are “Broadcast” actions.)

So here’s how you would set one up. In your Android manifest define a new receiver to be:

<receiver android:name=".receivers.PhoneIntentReceiver" android:enabled="true">
		<action android:name="android.intent.action.PHONE_STATE"></action>

Basically, you are defining a receiver object called PhoneIntentReceiver in your manifest which is enabled and which will listen for system broadcasts with the action type PHONE_STATE. This particular intent gets broadcasted by the system whenever there is an incoming call or whenever you hangup an existing phone call (i.e. when the state of your phone changes). Now, let’s create the actual class which will look something like this:

public class PhoneIntentReceiver extends BroadcastReceiver {

public void onReceive(Context context, Intent intent) {

      //get the data from the passed intent
      //this is the intent that was broadcasted by the system
      Bundle bundle = intent.getExtras();
      String phoneState = bundle.getString("state");
      String phoneNumber = bundle.getString("incoming_number")
      //perform operations using phoneState data

So notice we extend the BroadcastReceiver class and override the onReceive method. This gets called whenever the intent with action PHONE_STATE is broadcasted, and from there we can get the extra information that was stored in the intent and play around with it. Notice that in this case, the action extra is the “state”, and here the state will be either “RINGING”, “OFFHOOK”, or “IDLE”.

Just a quick side note – I’ve seen people who have additional checks in their receivers that do things like:

if(intent.getAction().equals(android.intent.action.PHONE_STATE)) {
      //do stuff

But this check is a little extraneous because of how our receiver was defined in the manifest. By adding an intent-filter with only one intent as its contents, we’re guaranteed that the only intent that can hit our receiver is one with action PHONE_STATE. Of course it never hurts to check, but just thought I’d make a quick remark.

Now, although I think this is buried somewhere in the documentation on receivers, I just thought I’d mention it here:


Receivers are simply meant to intercept broadcasted intents and obtain the desired information. If you want to do heavy processing with that data, then throw that data back into an intent (or just pass along the original intent) and start a new Activity or Service. Otherwise expect some system time outs.

And so, using our previous example, let’s say we’re only interested in the incoming number and we want to pass this to an Activity and from there process this incoming number (i.e. store it into a database, display it in a TextView, etc). Our code would look something like:

public class PhoneIntentReceiver extends BroadcastReceiver {

public void onReceive(Context context, Intent intent) {

      //get the data from the passed intent
      //this is the intent that was broadcasted by the system
      Bundle bundle = intent.getExtras();

      String phoneNumber = bundle.getString("incoming_number")
      Intent i = new Intent(context, YourActivity.class);
      i.putExtra("number", phoneNumber);


And you’re done! So there you have it, the relationship between Receivers, Intents, and Activities/Services!

Please comment if you thought I left out anything or if you’d like additional information. Other than that, happy coding!

– jwei

28 Comments leave one →
  1. January 8, 2010 1:01 pm

    Hey, ok, I get it, I guess – but does this really work?

  2. January 11, 2010 11:48 am

    Damn, that sound’s so easy if you think about it.

  3. deedee85 permalink
    January 25, 2010 6:57 am

    I’ve done that with SMS Receiver, the activity is well created (or waked-up).
    But there is a problem because none of the methods startActivity() or onActivityResult() or onNewIntent() are called on the activity.

    So there is no way to get the intent extra data in the activity.

    • January 25, 2010 12:52 pm

      I’m sorry could you explain your issue a little more? I’m not quite getting it

  4. deedee85 permalink
    January 26, 2010 1:57 am

    Yes, I think this code will be the better explanation :

    public class YourActivity extends Activity {

    public void startActivity(Intent intent) {
    Log.i(“startActivity”, “This method is never called, why ?”);

    When PhoneIntentReceiver calls context.startActivity(i), I’m waiting for a YourActivity.startActivity access which allows to get intent data.

    But it doesn’t work.

    PS : I use Android SDK 1.5

    • January 26, 2010 2:21 am

      Hm don’t override startActivity (not sure where in the lifecycle of the activity this occurs, but I’ve personally never seen anyone override it or have used it myself). Instead, override onCreate() and in your onCreate() method call getIntent().

      That should do the trick.

  5. deedee85 permalink
    January 26, 2010 3:16 am

    Thanks !

    This solution works when activity is not already launch (in pause state).
    When activity in launch, only onResume() method is called but I can’t get intent data with this.

    I’ve already override startActivity() to communicate data between activities in the same context. I found a sample on internet. But when I look at it, it uses the activity as context, so it works fine. It is not the case here.

    I found a solution by using the BroadcastReceiver as a static variable of the activity class. And then add this into onCreate() method :

    IntentFilter filter = new IntentFilter(“android.provider.Telephony.SMS_RECEIVED”);
    registerReceiver(smsReceiver, filter);

    But I would have prefered an external receiver.

  6. February 12, 2010 1:56 pm

    Hello, I found your blog in a new directory of blogs. I dont know how your blog came up, must have

  7. Martin permalink
    March 15, 2010 8:10 pm

    His comment didn’t really get cut off, it’s spam … Just take a look at his website address.

  8. March 16, 2010 10:48 pm

    When the command “String phoneNumber = bundle.getString(“incoming_number”)” is run, always I get null value. Why?

    • March 16, 2010 10:48 pm

      id need to see all of your code… it shouldn’t return null unless you’re running some API level where this fails and which I’m unaware of

      – jwei

  9. March 16, 2010 11:50 pm

    Here my class for receives PhoneState:
    public class PhoneStateReceiver extends BroadcastReceiver{
    public static final String CUSTOM_INTENT = “per.apps.CallRecorder.intent.action.CALLINFO”;

    public void onReceive(Context context, Intent intent) {
    Bundle bundle = intent.getExtras();
    Intent i = new Intent();

    And here is class for main Activity:
    public class CallRecorder extends ListActivity {
    private static final String ITEM_KEY = “key”;
    ArrayList<HashMap> ListViewItems = new ArrayList<HashMap>();
    private SimpleAdapter adapter;
    Intent intent = null;

    class InternalReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals(PhoneStateReceiver.CUSTOM_INTENT)) {
    Bundle bundle = intent.getExtras();
    String incomingNumber = bundle.getString(“incoming_number”);
    if (incomingNumber!=null)
    Log.d(“DEBUG”, incomingNumber);
    Log.d(“DEBUG”, “NULL”);

    /** Called when the activity is first created. */
    public void onCreate(Bundle savedInstanceState) {

    InternalReceiver ir = new InternalReceiver();
    getApplicationContext().registerReceiver(ir, new IntentFilter(“per.apps.CallRecorder.intent.action.CALLINFO”));

    PhoneStateReceiver psr = new PhoneStateReceiver();
    getApplicationContext().registerReceiver(psr, new IntentFilter(“android.intent.action.PHONE_STATE”));

    Please show me how to fix that bug!

  10. March 16, 2010 11:52 pm

    It works! But I always get null value of incomingNumber.

  11. March 16, 2010 11:54 pm

    Sorry, I missed! API level 4

  12. March 17, 2010 12:23 am

    I just look inside bundle’s data, it just contains “state”, nothing else.

  13. chinnu permalink
    March 18, 2010 7:49 am

    hai every one,

    i have a query.
    how can i write a Broadcast Receiver that will be invoked when user clicks on any application icon.

    i tried by writing

    but it is not called.

    i tried,
    by using Packagemanager i will get ApplicationInfo from that i can know all the application starting activity name and package names. i thought i can use them to registerReceiver
    and my receiver will listen by its launching activity and package name.
    but i strucked.. i am unable to do that.. i think i lost the way..
    please guide me…

  14. Mike permalink
    April 1, 2010 2:17 am

    hi this looks fine but have a small issue. when i start the activity it runs behind the call screen. is there a way to get the activity to front ???? that means to display the new activity on top of default incoming call screen


    • April 2, 2010 3:59 pm

      Hey Mike,

      I don’t believe what you’re trying to do is possible. The only thing I know of that can sit on top of the default incoming call screen is a Toast – not an Activity. If you think a Toast will suffice (i.e. you just want to display something to the user upon receiving an incoming call and you don’t actually need any user input or onclick listeners etc) then I’d suggest looking up how to create a Custom Toast through view inflation.

      Hope this helps.

      – jwei

      • Mike permalink
        April 4, 2010 8:55 pm

        hi jwei,

        thanks for your reply. but i have seen a application like this. there he is opening a web preview on top of incoming call screen.

        The application name is Jarmans ReverseLookup which is a free application.

        if you have time just look in to it.

        your feedback is much needed


  15. Simon permalink
    June 15, 2010 9:34 pm

    Well explained.
    I didn’t realize your receiver would hold up the caller app. If that is true I better be more careful to move any heavy receiver code into a thread or something.

    • June 20, 2010 4:44 pm

      Hey Simon,

      So the receiver class is supposed to be small – basically it’s meant to intercept the broadcast signal, get the intent, get the pieces of information it needs, and then finish right away.

      In the past I’ve tried to do a lot of heavy operations in my receivers, and though I forget what happens exactly (i.e. can’t remember if it force closes or if the receiver simply never gets called) the system can actually detect that you’re doing too much work in the receiver and stop your application.

      Instead, it’s suggested that you use a Service if expensive operations are required. Namely, in the receiver you want to pick up the pieces of data that you need (for instance, the incoming phone number), and then put that into a new Intent and start your Service. Your Service class will then run in the background and your receiver will end and everything will continue.

      Hope this makes sense.

      – jwei

  16. johnny permalink
    August 5, 2010 11:01 am

    Hey jwei512,

    Can you should me your manifest.xml? I want to start an activity once it receives the broadcast.

    public void onReceive(Context context, Intent intent) {

    Toast msg;
    msg = Toast.makeText(context, “Power broadcast received”, Toast.LENGTH_LONG);
    msg.setGravity(Gravity.CENTER, msg.getXOffset() / 2, msg.getYOffset() / 2);;
    Intent i = new Intent(context, DataUploadActivity.class);

    if i comment out the “context.startActivity(i);” it did give out the toast msg. if i did not comment that out, the program stopped, saying unexpected error.

    I wonder if there is anything to do with the manifest.xml file. here is mine:

    Thanks a lot. I really appreciate it.


    • August 26, 2010 7:14 pm

      Hey Johnny,

      I’d need to see the stack trace error. Your code looks like it should work okay so I’m stumped and seeing what the exact error is will help.

      – jwei

  17. Ivan permalink
    December 30, 2010 11:50 pm

    Thanks to this sample and comments I succesfully get the incoming number and I put it to a file 🙂

    I have a question:
    Is there some flag or something which shows if the call is forwarded(redirected) ?

    Best Regards

  18. Jay permalink
    December 8, 2011 11:07 pm

    It was really helpful to me. Thanx.

  19. May 27, 2012 11:24 pm

    How can i hang up the incoming call?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: