4

I'm using an intent service to communicate with a server to get data for an app. I'd like the app to wait until the data it requests has been sent back (hopefully meaning that the IntentService the data has been requested from has finished running) before the app attempts to access or use the variables the data is to be stored in. How would I go about doing this? thanks!

bgenchel
  • 3,739
  • 4
  • 19
  • 28
  • "I'd like the app to wait" -- please be much more specific. What is "the app"? What do you mean by "before the app attempts to access or use the variables the data"? – CommonsWare Aug 14 '14 at 23:09
  • i'd like it to not do anything while the intent service makes the http request (what i meant by communicate with the server). and then once that request has returned, perform the action, the action being a multitude of different processing steps i'd like to perform with the data. The app, meaning the app that I am working on that is using an intent service to communicate with a server (make http requests). – bgenchel Aug 14 '14 at 23:16
  • "i'd like it" -- what is "it"? Please post the source code of "it", or at least say what specific Android class "it" is. We have no way to know what "it" is. All we know is that "it" is not the `IntentService`, by the way you are constructing your sentences, but that is not much to go on. "meaning the app that I am working on" -- that's a circular definition. Android developers write activities, services, content providers, broadcast receivers, and things that those components use. What is "it" and "the app" with respect to these Android constructs? – CommonsWare Aug 14 '14 at 23:18
  • it being the app. the app that i am developing which is why i am asking this question. the app that uses an intent service to make http requests. the app that I want to process data returned from those http requests. I just want to know how the app can be notified when an http request, made through an intent service, has finished and returned data, and have the app not be performing any actions until that data has been returned. – bgenchel Aug 14 '14 at 23:23

1 Answers1

8

Easiest way is to have your IntentService send a Broadcast once it is done gathering data from the server, which you can listen to in your UI thread (e.g. Activity).

public final class Constants {
    ...
    // Defines a custom Intent action
    public static final String BROADCAST_ACTION =
        "com.example.yourapp.BROADCAST";
    ...
    // Defines the key for the status "extra" in an Intent
    public static final String EXTENDED_DATA_STATUS =
        "com.example.yourapp.STATUS";
    ...
}

public class MyIntentService extends IntentService {
    @Override
    protected void onHandleIntent(Intent workIntent) {
        // Gets data from the incoming Intent
        String dataString = workIntent.getDataString();
        ...
        // Do work here, based on the contents of dataString
        // E.g. get data from a server in your case
        ...

        // Puts the status into the Intent
        String status = "..."; // any data that you want to send back to receivers
        Intent localIntent =
            new Intent(Constants.BROADCAST_ACTION)
                    .putExtra(Constants.EXTENDED_DATA_STATUS, status);
        // Broadcasts the Intent to receivers in this app.
        LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
    }
}

Then create your broadcast receiver (either a separate class or inner class within your Activity)

E.g.

// Broadcast receiver for receiving status updates from the IntentService
private class MyResponseReceiver extends BroadcastReceiver {
    // Called when the BroadcastReceiver gets an Intent it's registered to receive
    @
    public void onReceive(Context context, Intent intent) {
        ...
        /*
         * You get notified here when your IntentService is done
         * obtaining data form the server!
         */
        ...
    }
}

Now the final step is to register the BroadcastReceiver in your Activity:

IntentFilter statusIntentFilter = new IntentFilter(
      Constants.BROADCAST_ACTION);
MyResponseReceiver responseReceiver =
      new MyResponseReceiver();
// Registers the MyResponseReceiver and its intent filters
LocalBroadcastManager.getInstance(this).registerReceiver(
      responseReceiver, statusIntentFilter );
Thira
  • 1,555
  • 1
  • 13
  • 24
  • ok, so, good answer, yes. but not what I was looking for. I have performed all the above already, but, now, given that i've done that, lets say I hand to my IntentService an intent which will return a string, and then at some point after i send that intent, I make a call to the resulting string. If I have no wait, there is a possibility that I may call on that string before it has been populated, before the intent has returned. Specifically in my case, I am getting the string from the broadcast receiver. If i call it before the receiver has received its broadcast, null pointer exception. – bgenchel Aug 14 '14 at 23:35
  • Better to do a null check and notify the user to either try again that operation (since the only way that can happen is if the user initiated that sequence of events in the first place!), or the app keep track of that state (i.e. user wanted to do that operation) and perform it automatically once the string is received from the server. Better to keep a state variable and handle those scenarios appropriately unless you want to block the UI while the background task is being executed. Use AsycTask to display a spinner dialog until the required data is received from the server) – Thira Aug 14 '14 at 23:57
  • 1
    Basically you have three options when performing background tasks: 1. Block the entire UI and prevent user from doing things until the background operation is done. 2. Block only certain elements within the UI until the background operation is done (need to be very careful about state transitions and navigating to other activities/fragments). 3. Let the user do whatever, but give appropriate feedback to the user if they attempt to do things that are not possible (e.g. trying to do something that use that string you were talking about before it becomes available). – Thira Aug 15 '14 at 00:00
  • so, that second comment you made. How would one go about keeping track of the 'state'? That sounds like exactly what I would like to do. – bgenchel Aug 15 '14 at 17:06
  • keep a boolean value (e.g. isInvokingService), you set it to true before invoking the service operation. Then you set it back to false inside the MyResponseReceiver (make that an anonymous class to make things simpler). – Thira Sep 01 '14 at 11:49