Search code examples
androidandroid-intentbroadcastreceiverandroid-service

Sending explicit intent doesn't work


I want to send explicit intent from Service with specified component to Activity. I have defined BroadcastReceiver dynamically in MainActivity.java.

When I don't set component for Intent, it is received in the activity. But with specified component then it doesn't work. Why is it?

BroadcastService.java:

public class BroadcastService extends IntentService {

    @Override
    public void onCreate() {
        super.onCreate();
        intent = new Intent();
        ComponentName component = new ComponentName(
                MainActivity.class.getPackage().getName(),
                MainActivity.class.getName());
        intent.setComponent(component);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        intent.putExtra("time", new Date().toLocaleString());
        sendBroadcast(intent);
    }
}

MainActivity.java:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            updateUI(intent);
        }
    };
}

Solution

  • As the documentation of Intent.setComponent() says:

    (Usually optional) Explicitly set the component to handle the intent. If left with the default value of null, the system will determine the appropriate class to use based on the other fields (action, data, type, categories) in the Intent. If this class is defined, the specified class will always be used regardless of the other fields. You should only set this value when you know you absolutely want a specific class to be used; otherwise it is better to let the system find the appropriate class so that you will respect the installed applications and user preferences.

    But you're doing:

    intent = new Intent();
    ComponentName component = new ComponentName(
            MainActivity.class.getPackage().getName(),
            MainActivity.class.getName());
    intent.setComponent(component);
    

    That means you set a component which points to MainActivity, not the broadcast receiver inside the MainActivity, hence it doesn't work.

    To fix, you can move your inner broadcast receiver to a separate class. But if so, you can't interact with the controls in MainActivity. There are many other ways to archive your goal. I suggest ResultReceiver (available in API 3+). When starting your service, you put a ResultReceiver into the intent. When the service wants to send information to the activity, you do it via the ResultReceiver given.