I have android service which I need to return a result after it has been started. So:
1) I start the service
2) The service does something
3) The service returns a result
I thought that maybe I can use a singleton class to take the result. I created a singleton class in order to make the service save the result in it and then take the result from the service by an activity. Here there's the code of the class:
public class Result {
//SIGLETON DECLARATION
private static Result mInstance = null;
public static Result getInstance() {
if (mInstance == null) {
mInstance = new Result();
}
return mInstance;
}
private Result() {
}
//CODE
Object result;
boolean resultIsSet = false;
public void deletePreviousResult() {
this.result = null;
resultIsSet = false;
}
public void setResult(Object result) {
Log.w("result", "setResult");
this.result = result;
resultIsSet = true;
}
public Object getResult() {
Log.w("result", "getResult");
while(resultIsSet == false) {}
return this.result;
}
Here's the code that I use to get the result:
public int getInfo() {
Result.getInstance().deletePreviousResult();
//start the service and ask to save the result in singleton class
Intent myIntent = new Intent(mInstanceContext, MediaPlayerService.class);
myIntent.setAction("getInfo");
mInstanceContext.startService(myIntent);
//take the result
return (Integer) Result.getInstance().getResult();
}
What is doing in onStartCommand
is:
Result.getInstance().setResult(mMediaPlayer.getCurrentPosition());
where mMediaPlayer
is a MediaPlayer object.
However the problem is that if setResult
is also supposed to be called in onStartCommand
, it is never called! Why? Is it my approach wrong?
This code you have in
getInfo()
:assumes that when you call
startService()
the service is started andonStartCommand()
is called synchronously so that in the next statement you can get the result usingResult.getInstance().getResult()
.Unfortunately, it doesn't work that way. Calling
startService()
isn't like calling a method on an object. What you do when you callstartService()
is that you tell Android that you want that service to be started at the next available moment. SinceonStartCommand()
in your service needs to be called on the main thread, usually this means that Android will start your service and callonStartCommand()
at the next time when Android gets control of the main thread (ie: when all your activity methods have returned). In any case, you can't determine when the service will be started or whenonStartCommand()
will be called. It is an asynchronous call, so you need to rely on a callback mechanism. This means that you need to write some kind of callback method that the service can call when it has done the work and wants to return the result to you.There are various ways to do this. You could have the service send an Intent to your activity. You could have the service broadcast an Intent with the results. You could bind to the service and register a callback listener (see developer documentation for bound services). There are probably other ways too.