I have a setup where I am running a background service in Android with an attached BroadcastReceiver listening for particular types of Intents. Those intents are then used by the broadcast receiver to call specific methods in the service. Below is code describing the structure of the service:
public class MyService extends Service {
private class ServiceBroadcastReceiver extends BroadcastReceiver {
private MyService getMyService() {
return MyService.this;
}
public IntentFilter getASReceiverFilter() {
IntentFilter filter = new IntentFilter()
filter.addAction(Constants.ACTION_DO_SOMETHING);
return filter;
}
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
MyService svc = getMyService();
String intentAction = intent.getAction();
Log.i(Constants.LOG_TAG, "Now trying to dispatch following action: " + intentAction);
//Dispatch to the appropriate method in MyService.
if (intentAction.equals(AppServiceConstants.ACTION_DO_SOMETHING)) {
svc.doSomething();
}
}
}
private ServiceBroadcastReceiver mRequestReceiver = new ServiceBroadcastReceiver();
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
Log.i(Constants.LOG_TAG, "Service Created!");
//Register for broadcast messages indicating the add music button was pressed
mRequestReceiver = new ServiceBroadcastReceiver();
registerReceiver(mRequestReceiver, mRequestReceiver.getASReceiverFilter());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(Constants.LOG_TAG, "Service Starting ... ");
// If we get killed, after returning from here, restart
return START_STICKY;
}
/***********************************************************************************
* Service Dispatch Methods
*/
protected void doSomething() {
Log.i(Constants.LOG_TAG, "Doing something");
}
}
My issue is with getting this service and its broadcast receiver to capture broadcasted intents from throughout my app. If I do something like the following ….
getApplicationContext().sendBroadcast(new Intent(Constants.ACTION_DO_SOMETHING));
.. it only works if I invoke that from within an Activity. However, I want to be able to “do something” even when the application first starts up, so I have put that statement in my own custom Application subclass in the onCreate() method, right after I create the MyService and start it up. For some reason, the broadcast is not working from within the Application class code when the app start up, but it will work if I put it in some code within an activity (eg in the onCreate() method of the activity). I can confirm that the service’s onCreate() and onStartCommand() methods are being invoked prior to broadcasting the intent in my Application object, but it simply doesn’t seem to get the intent and do the associated work.
Any help would be appreciated.
Update:
Here is how I send the broadcast from my application (note that I start the service first):
public class MyApplication extends Application {
@Override
public void onCreate() {
Intent intent = new Intent(getApplicationContext(), MyService.class);
getApplicationContext().startService(intent);
getApplicationContext().sendBroadcast(new Intent(Constants.ACTION_DO_SOMETHING));
}
}
Note that I’m starting the service before I actually do the broadcast. The service DOES NOT receive the broadcast, but if I do a similar call from an activity that I start up later, it does receive.
Your
Applicationis created before any other component in the process. So inonCreate()there is noSerivcerunning. And if you send broadcast at the moment when Application’sonCreate()is called,Servicehas no broadcast receiver registered because it wasn’t even created.So, in other words, you service is not receiving broadcast notification because broadcast receiver is not yet registered. And its not yet registered because
Serviceis not yet started. And it can’t be started before Application’sonCreate()returns by design.You can directly start service using
Context.startService()from Application’sonCreate(). You’ll be able to path all the required data throughIntent.Updated answer to an updated question:
When you call:
You ask Android to start service at some later time. The service is not started right away. It’s only scheduled to start later. In fact it will definitely not start before you return from Application’s
onCreate()function. That’s because all Service’s lifecycle callback functions (likeonCreate()andonStart()) are called from main UI thread. And Applicaiton’sonCreateis currently blocking main UI thread.So when you send broadcast using these lines of code:
You actually ask to start service at some later time, then immediately after that you send broadcast. And because service didn’t even had chance to start and to register for this broadcast
notifications, it will not receive anything when it actually gets started.
You could change your service’s
onStart()code to handle the intent and then start service using: