5

I am facing the following problem: I need to start an activity from a service. It is very important that the service waits for a result from the activity before continuing to the next method.

Currently I have something like this:

startActivity(new Intent(this, GoogleAuthHelperActivity.class), FLAG_ACTIVITY_NEW_TASK);
//code should wait for the result of the GoogleAuthHelperActivity before continuing
GoogleAuthHelperActivity.apiClient.isConnected();//gives nullpointer

I have the same problem with authenticating to the Dropbox API, so I need a generic solution.

Any ideas how to solve this?

user2810895
  • 1,284
  • 3
  • 19
  • 33

2 Answers2

2

There is no equivalent to startActivityForResult in Service, so you have to roll your own.

First option:

You can use several standard Java tools for this, like Object.wait / Object.notify, that require a shared object reference.

For example, declare somewhere:

public static final Object sharedLock = new Object();

and in your service do:

startActivity(new Intent(this, GoogleAuthHelperActivity.class), FLAG_ACTIVITY_NEW_TASK);
synchronized (sharedLock) {
    sharedLock.wait();
}

and in the activity:

// do something upon request and when finished:
synchronized (sharedLock) {
    sharedLock.notify();
}

There are other more sophisticated classes for this in the java.util.concurrent package that you can use for this. Be careful though, that Services run on the same thread as the Activity, so if you are not starting a new Thread from the Service, then this will not work.

Another possible problem is if you cannot share an object reference between them two (because they run in different processes). Then you have to signal the finishing in some other way.

Second option:

You could split your Service code in two parts (before and after the activity). Run the activity and send a new intent to the Service when you are done. Upon receipt of this second Service, you continue with the second part.

Sebastian
  • 1,076
  • 9
  • 24
  • I implemented your first option as this required the least refactoring – user2810895 Aug 20 '15 at 06:13
  • For the second option, what happens when the first part of the service hasn't finished and you call the second part? – Saurabh Nov 01 '18 at 16:34
  • @user2923505 that's why you use synchronizing primitives: to make sure that the execution continues only after the part you're waiting for has finished. If you have a different situation than the OP, I suggest you check if someone has already asked it, and if not create a new question. – Sebastian Nov 02 '18 at 18:29
0

This can be achieved by creating an interface and implementing your activity from that interface, i am posting a small demo that will help you ...

public interface MyCallBackNotifier {
    public void notify();
}

Extend that interface from your main class where you started your service like this ...

public class MainActivity extends Activity implements MyCallBackNotifier {

    private YourService service;

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

        service = new YourService(this);
        service.start();      // Ant method that you call like start();
    }


    @Override
    public void notify() {
             //this is the place where you have to start other activity or do any other process
    }
}

And in your service class you have to do some thing like this ...

public class YourService {

    private MyCallBackNotifier myCallBackNotifier;

    public YourService(MyCallBackNotifier myCallBackNotifier) {
         this.myCallBackNotifier = MyCallBackNotifier;
    }


    public void start() {

         // Do what so ever you want to do and its will be better to use Asynctask to do background task

         myCallBackNotifier.notify();       // This will call that function in your MainActivty you can pass parameters as well if you want se send some data back to MainActivity

    }

}
Zubair Akber
  • 2,760
  • 13
  • 30