javaandroidandroid-serviceandroid-service-binding

Getting java.lang.ClassCastException: android.os.BinderProxy every time i declare and run two services


I am encountering following binder.proxy exception every time i declare and run two services. One service runs in different Process(Private to app) and another service runs in same process as My Application is running in(Default App Process) with a Binder Implementation.

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.service.check"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <application
        android:name="com.service.check.MainApplication"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

         <service
            android:name="com.service.check.SecondService"
            android:exported="false"/>

        <service
            android:name="com.service.check.FirstService"
            android:process=":newProcess" >
        </service>
    </application>

</manifest>

I am launching my first service in MainActivity on Button click as:

MainActivity.java

public class MainActivity extends ActionBarActivity implements OnClickListener {

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

        mLanchServiceBtn=(Button) findViewById(R.id.launch_btn);

        mLanchServiceBtn.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
       //Starting first service
        Intent launch=new Intent(this,FirstService.class);
        startService(launch);

    }
}

And second service in MainApplication class as.

MainApplication.java

    public class MainApplication extends Application {

        private SecondService.LocalBinder mBinder;
        private ServiceConnection mConnection = new ServiceConnection() {

            @Override
            public void onServiceConnected(ComponentName className, IBinder service) {
                mBinder = (LocalBinder) service;
            }

            @Override
            public void onServiceDisconnected(ComponentName arg0) {
            }
        };

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

            //starting second service               
            Intent launch=new Intent(this,SecondService.class);
            startService(launch);

            //Binding to it 
            bindService(launch, mConnection, BIND_AUTO_CREATE);
        }

    }

FirstService.java

public class FirstService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

SecondService.java

public class SecondService extends Service{

    //Service Containing Local Binder
    private LocalBinder mBinder=new LocalBinder();
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
    class LocalBinder extends Binder{

        public LocalBinder() {
        }
    }
}

StackTrace:

 02-05 10:32:25.035: E/AndroidRuntime(1424): Process:

 com.service.check:newProcess, PID: 1424 02-05 10:32:25.035:
 E/AndroidRuntime(1424): java.lang.ClassCastException:
 android.os.BinderProxy cannot be cast to
 com.service.check.SecondService$LocalBinder 02-05 10:32:25.035:
 E/AndroidRuntime(1424):    at
 com.service.check.MainApplication$1.onServiceConnected(MainApplication.java:23)
 02-05 10:32:25.035: E/AndroidRuntime(1424):    at
 android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1101)

I have referred the following links to sort out the issue which says, if my activity and service are in separate processes then we should not bind the way I have done.

Android service android.os.BinderProxy error

java.lang.ClassCastException: android.os.BinderProxy cannot be cast to LocalBinder

But in my case: I am binding to SecondService from MainApplication and both are running in same Process(i.e Default Application Process). Still I am facing binderProxy exception in SecondService , And my FirstService runs in separate process which I am not even binding to.

Please help me out with this situation and, Suggest me a best possible way so that I can implement same scenario without any crash.


Solution

  • Found an answer after doing some research and debugging,

    If we create and bind any service to a MainApplication class(then service gets binded to whole ApplicationContext or BaseContext) and if same application contains other services which are binded to Activity specific Context(s),

    //Declared in MainApplication
    @Override
    public void onServiceConnected(ComponentName className, IBinder service) {
                    mBinder = (LocalBinder) service;
         }
    

    In OnServiceConnected() We will get binder object for both the Services( SecondService Started in MainApplication(registered with BaseContext will get local binderObject) class and FirstService started MainActivity(will get android.os.binderProxyObject hence causing ClassCastException).

    MainActivity.java

        private Button mLanchServiceBtn;
        private SecondService.LocalBinder mBinder;
        private ServiceConnection mConnection = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName className, IBinder service) {
                    mBinder = (LocalBinder) service;
                }
                @Override
                public void onServiceDisconnected(ComponentName arg0) {
                }
         };
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
    
                mLanchServiceBtn=(Button) findViewById(R.id.launch_btn);
    
                mLanchServiceBtn.setOnClickListener(this);
    
    
    
                //starting second service in activity
    
                Intent launch=new Intent(this,SecondService.class);
                startService(launch);
    
                //Binding to it 
                bindService(launch, mConnection, BIND_AUTO_CREATE);
            }
    
    
            @Override
            public boolean onCreateOptionsMenu(Menu menu) {
                // Inflate the menu; this adds items to the action bar if it is present.
                getMenuInflater().inflate(R.menu.main, menu);
                return true;
            }
    
            @Override
            public boolean onOptionsItemSelected(MenuItem item) {
                int id = item.getItemId();
                if (id == R.id.action_settings) {
                    return true;
                }
                return super.onOptionsItemSelected(item);
            }
    
    
            @Override
            public void onClick(View v) {
    
               //Starting FirstService also from MainActivity
                Intent launch=new Intent(this,FirstService.class);
                startService(launch);
    
            }
        }