Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get results from an IntentService back into an Activity?

I am using an IntentService to handle network communications with a server via JSON. The JSON/server part is working fine, but I'm having trouble getting the results back where they are needed. The following code shows how I am starting the intent service from inside onClick(), and then having the service update a global variable to relay the results back to the main activity.

public class GXActivity extends Activity {      private static final String TAG = "GXActivity";      @Override     public void onCreate(Bundle savedInstanceState) {         // === called when the activity is first created          Log.i(TAG, "GXActivity Created");          super.onCreate(savedInstanceState);         setContentView(R.layout.start);          View.OnClickListener handler = new View.OnClickListener() {             public void onClick(View v) {                  // === set up an application context to hold a global variable                 // === called user, to contain results from the intent service                 GXApp appState = ((GXApp) getApplicationContext());                 User user = new User(-1); // initialize user id to -1                 appState.setUser(user);                  // === next start an intent service to get JSON from the server;                 // === this service updates the user global variable with                 // === results from the JSON transaction                 Intent intent = new Intent(this, GXIntentService.class);                 startService(intent);                  // === check app context for results from intent service                 appState = ((GXApp) getApplicationContext());                 if (appState.getUser().getId() != -1)...              }         }     } } 

The problem I'm having is that the intent service that parses the JSON doesn't get invoked until after onCreate() completes, so my code that's looking for the results is stuck looking at uninitialized results.

What should I do differently so the intent service gets called before I check the results? Would it work if I pulled the click listener out of the onCreate() function? Is there a another/better to structure this code? Many thanks.

like image 712
gcl1 Avatar asked Apr 26 '12 13:04

gcl1


People also ask

How do I send a callback from service to activity?

You need to create a BroadcastReceiver in your activity (be sure to register it in onResume() and unregister it in onPause() ) and notify it via a broadcast, providing an Intent .

How do you communicate between service and activity?

This example demonstrates how do I communicate between Activity and Service in android. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml.

How do I get context in IntentService?

You can get the context in onStartCommand() function. Show activity on this post. Show activity on this post. You can use Intent service class as Context.

Can an IntentService execute multiple tasks sequentially?

1) Is it possible to have multiple intentService threads at the same time or not? No, each IntentService only has one HandlerThread that it uses to execute requests in the order that "startService" is called.


2 Answers

You should look at creating your own ResultReceiver subclass in your activity. ResultReceiver implements Parcelable so can be passed from your Activity to your Service as an extra on the Intent.

You'll need to do something like this:

  1. Implement a subclass of ResultReceiver within your activity class. The key method to implement is onReceiveResult(). This method provides you a with Bundle of result data which can be used to pass whatever information you are retrieving in your Service. Simply unpack the data you need and use it to update your activity.

  2. In your activity, create a new instance of your custom ResultReceiver and add it to the Intent you use to start your service.

  3. In your Service's onStartCommand() method, retrieve the ResultReceiver passed in on the Intent and store it in a local member variable.

  4. Once your Service completes its work, have it call send() on the ResultReceiver passing whatever data you want to send back to the activity in a Bundle.

This is a pretty effective pattern and means you're not storing data in nasty static variables.

like image 76
tomtheguvnor Avatar answered Sep 24 '22 22:09

tomtheguvnor


There's many ways to do stuffs in background getting back a result (AsyncTask, bind an Activity to a Service...), but if you want to mantain your IntentService's code you can simply:

1- send a broadcast intent (that contains the status in its extended data) at the end of the work in your IntentService

2- implement a LocalBroadcastReceiver in your Activity that consumes the data from the Intent

This is also the recommended way in the official documentation (if you want to mantain your IntentService):

https://developer.android.com/training/run-background-service/report-status.html

like image 41
DSoldo Avatar answered Sep 23 '22 22:09

DSoldo