4

I need to have a two way communication between my activity and a running IntentService.

The scenario is like this: the app can schedule alarms which on run, start an IntentService which fetches some data from web and process it. There are three possible situations when IntentService finishes:

  1. The app is in focus, which means that when the IntentService will finish, the app needs to refresh its views with the new data.

  2. The app is closed and when opened after IntentService has finished the work, so the app will have access to processed data

  3. The app is opened while the IntentService is running, in which case I need to have a way from the activity to ask the IntentService if its doing something in the background.

For 1. I have already implemented a BroadcastReceiver in my activity which gets registered with the LocalBroadcastManager. When IntentService finishes the work, sends a broadcast and the activity reacts. This works fine

For 2. There is nothing needed to be done

For 3. I don't know what to do. So far I've tried this:

In Activity:

LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(BROADCAST_SEND_TO_SERVICE));

In IntentService

private LocalBroadcastManager localBroadcastManager;
    private BroadcastReceiver broadcastReceiverService = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(BROADCAST_SEND_TO_SERVICE)) {
               //does not reach this place
               //Send back a broadcast to activity telling that it is working
            }
        }
    };

  @Override
    protected void onHandleIntent(Intent intent) {


        localBroadcastManager = LocalBroadcastManager.getInstance(context);
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BROADCAST_SEND_TO_SERVICE);
        localBroadcastManager.registerReceiver(broadcastReceiverService, intentFilter);
.... //do things

}

The problem with my implementation is that n the IntentService the BroadcastReceiver does not fire onReceive. Any suggestions or maybe a simpler way for the Activity to ask the IntentService what it is doing?

LE: Trying to get atomicboolean. In Service:

public static AtomicBoolean isRunning = new AtomicBoolean(false);

 @Override
    protected void onHandleIntent(Intent intent) {
        isRunning.set(true);
        // do work
        // Thread.sleep(30000)
        isRunning.set(false);
}

In Activity, restarting the app while service is running:

    Log(MyIntentService.isRunning.get());

//this returns always false, even if the intent service is running

On AndroidManifest

 <service
            android:name=".services.MyIntentService"
            android:exported="false" />
Alin
  • 14,809
  • 40
  • 129
  • 218
  • 1. You can maintain a flag at application level which will get true and false by intent service. 2. you can also maintain the value in sharedpreference – Shubham Aug 25 '16 at 19:33
  • Switch from `LocalBroadcastManager` to greenrobot's EventBus and use a sticky event to indicate the current status. Or, use a simple `AtomicBoolean` (or some other atomic wrapper) as a `static` field, if your needs are limited. – CommonsWare Aug 25 '16 at 19:35
  • Are the YourIntentService.BROADCAST_SEND_TO_SERVICE and the HomeActivity.BROADCAST_SEND_TO_SERVICE strings equal? From your example code, it looks you may have defined this string variable in both classes. – Janus Varmarken Aug 25 '16 at 20:21
  • @JanusVarmarken yes are the same, I've edited the question. – Alin Aug 25 '16 at 20:57
  • @CommonsWare I wonder why the LocalBroadcastManger works from Service to Activity but not the other way around? I need to take a look at AtomicBoolean as I haven't used it before – Alin Aug 25 '16 at 20:58
  • @Shubham 2. no, 1. can you detail? Thank you – Alin Aug 25 '16 at 20:58
  • if you want two way communication then try "bound service" pattern, see `IntentService#onBind`: "Unless you provide binding for your service, you don't need to implement this method, because the default implementation returns null." – pskink Aug 25 '16 at 21:07
  • This might also be a threading issue. Please try and move the 4 lines of receiver registration code in onHandleIntent to onStartCommand -- and make sure to call super.onStartCommand to let the IntentService initialize itself properly. – Janus Varmarken Aug 25 '16 at 21:26
  • "I wonder why the LocalBroadcastManger works from Service to Activity but not the other way around?" -- it should be fine, but bear in mind that the receiver would be called on the main application thread. If all you want to do is send a message to the service, call `startService()` with a distinct `Intent`, separate from the one that you use for doing its main work (e.g., custom action string). – CommonsWare Aug 26 '16 at 00:37
  • @Alin you will create Application class as singleton and there you can maintain a boolean flag which you will make true in onStartCommand and make false in onDestroy – Shubham Aug 26 '16 at 03:58
  • @JanusVarmarken moved the receiver register to onStartCommand and still the same thing. – Alin Aug 26 '16 at 09:16
  • @CommonsWare I've added an edit trying to use AtomicBoolean but maybe I am missing something? Thank you. – Alin Aug 26 '16 at 09:48
  • That should be fine. Do you have `android:process` on any of your manifest elements? All of these solutions only work if everything is in the same process. – CommonsWare Aug 26 '16 at 10:43
  • @CommonsWare I've added the manifest entry. Well, the code does not run, always returns false... – Alin Aug 26 '16 at 10:46
  • @CommonsWare you are right it should work and it does, as I've been testing it by closing the app from Recents, without knowing that the IntentService will get killed too. I had the impression that the service would keep running until it completes the job. – Alin Aug 26 '16 at 11:07

0 Answers0