Search code examples
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).

    • So, to fix this issue one has to start all the application services from any Activity Context rather than using any Global Application Context. Also this issue is independent of the Processes

    • Hence, I moved both SecondService and FirstService into MainActivity Context which fixed the issue.

    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);
    
            }
        }