java.lang.ClassCastException: android.os.BinderProxy无法转换为LocalBinder。

17

我有一个Service,我试图将其绑定到我的主Activity,但是我收到了一个java.lang.ClassCastException:android.os.BinderProxy无法转换为com.walintukai.rubix.ConnectionService$LocalBinder的错误。

我已经在清单文件中声明了这个服务。为什么会出现这种情况?

清单文件声明

<service android:name=".ConnectionService" />

服务(简化代码)

public class ConnectionService extends Service {

static final String TAG = ConnectionService.class.getName();

private BluetoothAdapter mBtAdapter = null;
public BluetoothGatt mBluetoothGatt = null;
private ConnectionServiceEventListener mIRedBearServiceEventListener;
HashMap<String, BluetoothDevice> mDevices = null;
private BluetoothGattCharacteristic txCharc = null;
private final IBinder mBinder = new LocalBinder();

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

public class LocalBinder extends Binder {
    public ConnectionService getService() {
        return ConnectionService.this;
    }
}

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

    final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    mBtAdapter = bluetoothManager.getAdapter();

    if (mBtAdapter == null) 
        return;

    if (mDevices == null) 
        mDevices = new HashMap<String, BluetoothDevice>();
}

@Override
public void onDestroy() {
    if (mBluetoothGatt == null)
        return;

    mBluetoothGatt.close();
    mBluetoothGatt = null;

    super.onDestroy();
}

}

主活动

public class MainActivity extends ActionBarActivity {

private ConnectionService service;

ServiceConnection connection = new ServiceConnection() {

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.i("ConnectionService", "Disconnected");
        service = null;
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        LocalBinder binder = (LocalBinder) service;
        service = (IBinder) binder.getService();

        if (service != null) {
            Log.i("RedBearService", "Connected");

        }
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction().add(R.id.container, ViewPagerFragment.newInstance()).commit();
    }
}

@Override
public void onStart() {
    super.onStart();
    startService();
}

@Override
public void onStop() {
    super.onStop();
    stopService();
}

private void startService() {
    Intent service = new Intent(this, ConnectionService.class);
    bindService(service, connection, Context.BIND_AUTO_CREATE);
}

private void stopService() {
    unbindService(connection);
}
07-30 17:19:39.065: E/AndroidRuntime(20891): java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.walintukai.rubix.ConnectionService$LocalBinder
07-30 17:19:39.065: E/AndroidRuntime(20891):    at com.walintukai.rubix.MainActivity$1.onServiceConnected(MainActivity.java:58)
07-30 17:19:39.065: E/AndroidRuntime(20891):    at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1110)
07-30 17:19:39.065: E/AndroidRuntime(20891):    at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1127)
07-30 17:19:39.065: E/AndroidRuntime(20891):    at android.os.Handler.handleCallback(Handler.java:733)
07-30 17:19:39.065: E/AndroidRuntime(20891):    at android.os.Handler.dispatchMessage(Handler.java:95)
07-30 17:19:39.065: E/AndroidRuntime(20891):    at android.os.Looper.loop(Looper.java:136)
07-30 17:19:39.065: E/AndroidRuntime(20891):    at android.app.ActivityThread.main(ActivityThread.java:5050)
07-30 17:19:39.065: E/AndroidRuntime(20891):    at java.lang.reflect.Method.invokeNative(Native Method)
07-30 17:19:39.065: E/AndroidRuntime(20891):    at java.lang.reflect.Method.invoke(Method.java:515)
07-30 17:19:39.065: E/AndroidRuntime(20891):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
07-30 17:19:39.065: E/AndroidRuntime(20891):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
07-30 17:19:39.065: E/AndroidRuntime(20891):    at dalvik.system.NativeStart.main(Native Method)

4
您是否在与应用程序相同的进程上启动服务? - Onik
@Onik 应该是的。我怎么检查呢?我正在我的主 Activity 的 onStart 调用中启动和绑定服务。 - The Nomad
你能提供你的主要活动代码吗? - Oleg Gryb
已编辑以包括主活动和清单声明。 - The Nomad
你确定你的简化代码是正确的吗?该活动的onServiceConnected方法错误地将getService方法的返回值强制转换回IBinder。 - Larry Schiefer
显示剩余3条评论
3个回答

15

这个问题已经几年了,而且被接受的答案对我没有用。也许自从提问和回答之后,Android环境发生了一些变化。

但是我偶然发现了一个简单的解决方案,它起作用了。我在SO上看到了另一个问题,他们试图启动2个服务,并且有类似的错误(Getting java.lang.ClassCastException: android.os.BinderProxy every time i declare and run two services)。其中一个答案(@Coeffect)提到2个服务不一定在同一个进程中运行。

我想可能(很可能?)在我的情况下,活动和服务在不同的进程中运行。所以我在我的活动和服务器中都添加了android:process元素,然后问题解决了。

下面是一个例子AndroidManifest.xml。请注意,<activity><service>标签都包括android:process=":location"

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="net.byteslinger.locationservice">

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <application
        android:process=":location"
        android:allowBackup="true"
        android:icon="@mipmap/icon"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/icon"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:process=":location"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:process=":location"
            android:name=".LocationService"
            android:enabled="true" />
    </application>

</manifest>

3
有趣。因为当你在“application”上设置进程时,它会自动为其他组件(activity、service、receiver等)设置进程。而且,在“application”上设置进程通常与不设置没有什么区别,因为如果省略“process”标签,所有组件已经在同一个进程中运行。 - frankish
2
为什么要在Activity中添加 android:process - IgorGanapolsky

13

你搞反了:

public void onServiceConnected(ComponentName name, IBinder service) {
    LocalBinder binder = (LocalBinder) service;
    service = (IBinder) binder.getService();
    ...
}

应该是:

public void onServiceConnected(ComponentName name, IBinder service) {
    LocalBinder binder = (LocalBinder) service;
    MainActivity.this.service = (ConnectionService) binder.getService();
    ...
}

2
我刚刚弄明白了,但是既然你同时发布了,我就把分数给你。 - The Nomad

-1

我也遇到了这个问题。我的情况是这样的。

我的活动和服务不在同一个进程中。

<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=".MyService"
       android:process=":remoute"/>

我想将服务与活动绑定在一起。然后我遇到了同样的问题。我用这种方法解决了它。

@Override
public IBinder onBind(Intent arg0) {
    int numb = arg0.getIntExtra("numb", 0);
    Log.e("WillWolf", "numb-->" + numb);
    if(numb == 1) {
        Log.e("WillWolf", "local binder");
        return new LocalBinder();
    } else {
        Log.e("WillWolf", "remote binder");
        return remoteBinder;
    }
}

请注意,当您多次调用bindService()方法时,默认情况下只会回调一次onBind()。如果您希望onBind()执行多次,则应执行以下操作。
Intent intent = new Intent(context, MyService.class);
    intent.setType("remote");// should be different
    context.bindService(intent, coon, Context.BIND_AUTO_CREATE);

我希望它能对你有所帮助。

这里的remoteBinder是什么? - Lior Iluz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接