androidserviceipcaidlandroid-binder

Return a different Binder from already bound service


I have a Service which is already bound by an external App via AIDL.

However, there are some service requests which require to start an Activity. Since I cannot call startActivityForResult from within a Service I decided to Bind my local Activities to the service as well.

(PseudoCode) looks like this:

class MyService extends Service{
    public IBinder onBind(Intent intent){
        if (intent.hasExtra("LocalBindingRequest")){
            return getLocalBinder();
        else {
           return getAidlBinder();
        }
    }
}

class ExternalApp extends Activity{
    void someFunc(){
        Intent i = new Intent(new ComponentName("com.my.pkg", "com.my.pkg.MyService");
        bindService(i, myServiceConnection, Context.BIND_AUTO_CREATE);
    }
}

class InternalApp extends Activity{
    MyService mService;

    void someFunc(){
        Intent i = new Intent(new ComponentName("com.my.pkg", "com.my.pkg.MyService")
           .putExtra("LocalBindingRequest", true);
        bindService(i, myServiceConnection, Context.BIND_AUTO_CREATE);
    }

    public void onServiceConnected(ComponentName cn, IBinder service){
        InternalBinder ib = (LocalBinder)service;
        mService = ib.getService();

    }
}

Flow is like this:

java.lan.ClassCastException: AidlService cannot be cast to InternalBinder


Isn't it possible for a Service to return a different Binder?

If not, what can I do, to propagate a Result back to MyService which is already bound?


Solution

  • Ok I should have read the docs stating in onBind(Intent)

    Intent: The Intent that was used to bind to this service, as given to Context.bindService. Note that any extras that were included with the Intent at that point will not be seen here.

    Thats why I was given the Aidl Service. The fix would be:

    class InternalApp extends Activity{
        MyService mService;
    
        void someFunc(){
            Intent i = new Intent(new ComponentName("com.my.pkg", "com.my.pkg.MyService");
            i.setAction("LocalBindingRequest");
            bindService(i, myServiceConnection, Context.BIND_AUTO_CREATE);
        }
    
        public void onServiceConnected(ComponentName cn, IBinder service){
            InternalBinder ib = (LocalBinder)service;
            mService = ib.getService();
    
        }
    }
    
    
    class MyService extends Service{
        public IBinder onBind(Intent intent){
            if ("LocalBindingRequest".equals(intent.getAction()){
                return getLocalBinder();
            else {
               return getAidlBinder();
            }
        }
    }
    

    And we can have separate Binders for each binding request