Reputation: 41838
I am not certain how to resolve this, but in one Activity I call startService, and then immediately call to start the next Activity.
This works, the service starts, and begins to process the data as expected.
I go to the next Activity, and in onResume
I call the AsyncTask
to bind the service.
So, the basic flow is that I call the AsyncTask, the bindService
returns false, so mConnection is never called.
So, the problem is why is bindService
returning false?
The reason I put the binding in an AsyncTask is that I had the thread sleep for 10 seconds before binding to see if the service needed to start up first.
I also started the service inside this activity, first, in the onCreate method, and so waited 10 seconds, but bindService
still returns false.
private class BindServiceTask extends AsyncTask<Void, Void, Boolean> {
protected Boolean doInBackground(Void... params) {
return bindService(
new Intent(IMyCallback.class.getName()),
mConnection, Context.BIND_AUTO_CREATE);
}
protected void onPostExecute(Boolean b) {
if (b) {
Log.i(TAG, "onResume - binding succeeded");
Toast.makeText(mContext, "Bound to service succeeded",
Toast.LENGTH_LONG).show();
} else {
Log.i(TAG, "onResume - binding failed");
Toast.makeText(mContext, "Bound to service failed",
Toast.LENGTH_LONG).show();
}
}
}
private IMyCallback mCallback = new IMyCallback.Stub() {
@Override
public void dataChanged(double[] info) throws RemoteException {
mHandler.sendMessage(mHandler.obtainMessage(LOCATION_MSG, info));
}
};
IMyService mIRemoteService;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
Log.i(TAG, "onServiceConnected");
mIRemoteService = IMyService.Stub.asInterface(service);
try {
Log.i(TAG, "registering callback");
mIRemoteService.registerCallback(mCallback);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
}
public void onServiceDisconnected(ComponentName className) {
Log.e(TAG, "Service has unexpectedly disconnected");
mIRemoteService = null;
}
};
Upvotes: 3
Views: 7198
Reputation: 41838
The problem appears to have been a problem with the manifest.
I was missing the intent-filter to tell the system which services could be bound to:
<service
android:name=".MyService"
android:process=":remote" >
<intent-filter>
<!--
These are the interfaces supported by the service, which
you can bind to.
-->
<action android:name="my.com.services.IMyCallback" />
<action android:name="my.com.services.IMySecondaryService" />
<!--
This is an action code you can use to select the service
without explicitly supplying the implementation class.
-->
<action android:name="my.com.activity.MY_SERVICE" />
</intent-filter>
</service>
Upvotes: 2
Reputation: 5547
When you call bindService()
it won't necessarily return your service connection or API to access the service. It happens asynchronously. You need a callback like this:
class PictureUploadQueueServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder service){
Log.d(TAG, "PictureUpload Service Connected!");
pictureUploadQueueApi = PictureUploadQueueServiceApi.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName name){
Log.d(TAG, "PictureUpload Service Connection Closed!");
pictureUploadQueueApi = null;
}
};
Your call to do the bind should look like this:
getApplicationContext().bindService(new Intent("org.me.xxxx.PictureUploadQueueServiceApi"),
pictureUploadQueueServiceConnection,
Context.BIND_AUTO_CREATE
);
Make sure in your service you are implementing the API Stub and returning an instance of it in your onBind()
method:
private PictureUploadQueueServiceApi.Stub api = new PictureUploadQueueServiceApi.Stub() {
@Override
public void queuePictureUpload(String remoteURI, String localURI, String target, String description, String callback) throws RemoteException {
appendPictureUpload(remoteURI, localURI, target, description, callback);
}
@Override
public boolean isEmpty() {
return queue.size() == 0 ? true : false;
};
};
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "Bound Intent: " + intent);
return api;
}
Lastly, to complete the example, the AIDL file for my example looks like this:
interface PictureUploadQueueServiceApi {
void queuePictureUpload(String remoteURI, String localURI, String target, String description, String callback);
boolean isEmpty();
}
Upvotes: 1