2

We bind to our local service (same process) in Application subclass but sometimes we are getting a ClassCastException. I have no idea how to fix it since everyone says the exception occurs if the service process is different than your application. How can this be fixed?

Application subclass:

public class App extends Application implements ServiceConnection {
  private ServiceApi exposedServiceApi;
  private EventBus eventBus;

  @Override public void onCreate() {
    super.onCreate();
    bindToService();
  }

      public void bindToService() {
        if (isConnectedToService()) {
          return;
        }

        boolean successfulBindCall =
            bindService(new Intent(this, MainService.class), this, BIND_IMPORTANT | BIND_AUTO_CREATE);
        if (successfulBindCall) {
          Timber.d("bindService() returned true --> onServiceConnected() will be called soon.");
        } else {
          throw new RuntimeException("bindService() returned false, this is an unrecoverable state.");
        }

  }



      @Override public void onServiceConnected(ComponentName componentName, IBinder service) {
        Timber.d("App has connected to service %s", componentName.toShortString());
        if (componentName.getClassName().equals(MainService.class.getName())) {
          try {
            exposedServiceApi = (ServiceApi) service;
            eventBus.post(new MainServiceConnectedEvent());

          } catch (ClassCastException e) {
            Timber.e(e, "Could not cast IBinder to ServiceApi!");
            exposedServiceApi = null;
          }
        }
      }

      @Override public void onServiceDisconnected(ComponentName componentName) {
        Timber.d("App has disconnected from service %s", componentName.toShortString());
        if (componentName.getClassName().equals(MainService.class.getName())) {
          exposedServiceApi = null;
          eventBus.post(new MainServiceDisconnectedEvent());
        }
      }
}

Service.onBind():

  @Override public IBinder onBind(Intent intent) {
    return new ServiceBinder();
  }

ServiceBinder: (inner class of MainService)

  private class ServiceBinder extends Binder implements ServiceApi {
     // implementation of ServiceApi
  }

Manifest:

<service
android:name=".service.MainService"
android:exported="false"
android:icon="@drawable/ic_launcher"
android:stopWithTask="true"/>

Error:

java.lang.ClassCastException: android.os.BinderProxy cannot be cast to ee.mtakso.driver.service.ServiceApi at ee.mtakso.App.onServiceConnected(App.java:152) at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1139) at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1156) at android.os.Handler.handleCallback(Handler.java:725) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:153) at android.app.ActivityThread.main(ActivityThread.java:5341) at java.lang.reflect.Method.invokeNative(Method.java) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:929) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696) at dalvik.system.NativeStart.main(NativeStart.java)

Nima
  • 6,383
  • 7
  • 46
  • 68
  • Post code from `onBind()` in your service. – David Wasser Jul 02 '15 at 10:15
  • Do you have other services in your app? – David Wasser Jul 02 '15 at 10:53
  • What device are you seeing these errors on? – David Wasser Jul 02 '15 at 10:57
  • Sorry for all the questions. Are you binding to any other services (external services) using the application global context? – David Wasser Jul 02 '15 at 11:01
  • @DavidWasser every device is having the same issue (LG g3, nexus 5, sony z3 etc.). I'm not binding to any other service explicitly but there is Crashlytics and LeakCanary and Google Analytics which are started with Application context. – Nima Jul 02 '15 at 11:13
  • @DavidWasser But since I'm checking the component name before casting, that shouldn't be the reason. – Nima Jul 02 '15 at 11:13
  • I think I know what the problem is. However, I want to do some testing first so that I can provide you a clear answer. I can do this later tonight. Sorry for the delay. – David Wasser Jul 02 '15 at 11:24
  • @DavidWasser Thanks a bunch, looking forward to your answer. :) – Nima Jul 02 '15 at 11:33
  • Argh. Not getting the results I expected. Do you have the `android:process` attribute set for any components in your manifest? – David Wasser Jul 02 '15 at 15:51
  • @DavidWasser no, but I do have a few activities that are started with service context and NEW_TASK | CLEAR_TASK flag, not sure if that makes a difference at all. – Nima Jul 03 '15 at 11:42
  • No, that shouldn't matter. I was hoping that [this answer](http://stackoverflow.com/a/28545134/769265) would shed some light on the problem. However, I created a test program to test my hypothesis and could not reproduce the problem. Even if I bound to another Service running in another process, an attempt to bind to a local service always returned the correct local binder. In general, I don't like your architecture, as `onCreate()` is called from your custom `Application` class whenever Android creates a new process for your application. – David Wasser Jul 03 '15 at 19:36
  • ...better would be that you initiate the binding to the service from an Activity, even if you use the application Context to perform the binding. However, I don't think that will solve your problem either. Unfortunately, I have run out of ideas :-( – David Wasser Jul 03 '15 at 19:38
  • If you can, post your entire manifest. Maybe I will see something in there. – David Wasser Jul 03 '15 at 19:38
  • Did you ever solve this problem? I realize a year has gone by, I'm interested if you ever figured this out. – David Wasser Jul 20 '16 at 18:29

0 Answers0