45

I want to use dynamically registered BroadcastReceiver that has a reference to an Activity so it can modify its UI. I am using Context.registerReceiver() method but receiver's onReceive() method is never called.

Here is the sample code showing the problem:

package com.example;

import android.app.Activity;
import android.app.IntentService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;

public class RegisterBroadcastReceiver extends Activity {

    public static class MyIntentService extends IntentService {

        public MyIntentService() {
            super(MyIntentService.class.getSimpleName());
        }

        @Override
        protected void onHandleIntent(Intent intent) {
            Intent i = new Intent(this, MyBroadcastReceiver.class);
            sendBroadcast(i);
        }
    }

    public class MyBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i(MyBroadcastReceiver.class.getSimpleName(),
                  "received broadcast");
        }

    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    MyBroadcastReceiver mReceiver = new MyBroadcastReceiver();

    @Override
    protected void onResume() {
        super.onResume();

        IntentFilter intentFilter = new IntentFilter();
        registerReceiver(mReceiver, intentFilter);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU) {
            Intent i = new Intent(this, MyIntentService.class);
            startService(i);
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(mReceiver);
    }

}
naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Urboss
  • 1,255
  • 2
  • 10
  • 17

2 Answers2

40

The whole code if somebody need it.

void alarm(Context context, Calendar calendar) {
    AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE);

    final String SOME_ACTION = "com.android.mytabs.MytabsActivity.AlarmReceiver";
    IntentFilter intentFilter = new IntentFilter(SOME_ACTION);

    AlarmReceiver mReceiver = new AlarmReceiver();
    context.registerReceiver(mReceiver, intentFilter);

    Intent anotherIntent = new Intent(SOME_ACTION);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, anotherIntent, 0);
    alramManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);

    Toast.makeText(context, "Added", Toast.LENGTH_LONG).show();
}

class AlarmReceiver extends BroadcastReceiver {     
    @Override
    public void onReceive(Context context, Intent arg1) {
        Toast.makeText(context, "Started", Toast.LENGTH_LONG).show();
    }
}
Melquiades
  • 8,496
  • 1
  • 31
  • 46
Mike
  • 775
  • 8
  • 3
18

Broadcast receivers receive events of a certain type. I don't think you can invoke them by class name.

First, your IntentFilter must contain an event.

static final String SOME_ACTION = "com.yourcompany.yourapp.SOME_ACTION";
IntentFilter intentFilter = new IntentFilter(SOME_ACTION);

Second, when you send a broadcast, use this same action:

Intent i = new Intent(SOME_ACTION);
sendBroadcast(i);

Third, do you really need MyIntentService to be inline? Static? [EDIT] I discovered that MyIntentSerivce MUST be static if it is inline.

Fourth, is your service declared in the AndroidManifest.xml?

Emmanuel
  • 16,791
  • 6
  • 48
  • 74
  • You are right with action it is working, however besides of modifying UI I want this broadcast to be private and was hopping to achieve it in this way. If it is possible, specifying an action should not be required because I know my app's component which I want to handle the broadcast. Intent service does not need to be an inner class - it is only for legibility of this example. My service in this example was not declared in the manifest - I have corrected the question. – Urboss Nov 09 '10 at 15:25
  • 1
    You don't need to use a broadcast receiver if you're opening a specific activity. Just use startActivity. – Falmarri Nov 09 '10 at 16:41
  • Falmarri here is right; broadcasting is only if you want to send a message to zero or many components. Otherwise, if it's just a single activity, just call that activity directly. The other advantage is that that activity will be started if it's not already. Not so for broadcasts. – Emmanuel Nov 09 '10 at 21:32
  • 1
    I want to update an activity if it is in foreground, otherwise I want to show a notification. I have already achieved it with static variable, without using a broadcast receiver. It seems that it is impossible to send private broadcast only to components of given class of your app. – Urboss Nov 10 '10 at 07:44