java.lang.ClassCastException: android.os.BinderProxy 无法转换为 com.leonard.sg.okcoin.service.SyncAndTradeService$SyncAndTradeBinder

java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.leonard.sg.okcoin.service.SyncAndTradeService$SyncAndTradeBinder

我试图将MainActivity绑定到前台服务,然后得到以下异常,已经搜索了一个多小时,不知道我做错了什么,请救救我。

java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.leonard.sg.okcoin.service.SyncAndTradeService$SyncAndTradeBinder
        at com.leonard.sg.okcoin.MainActivity.onServiceConnected(MainActivity.java:50)
        at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1101)
        at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1118)
        at android.os.Handler.handleCallback(Handler.java:725)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:5227)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
        at dalvik.system.NativeStart.main(Native Method)

我的MainActivity中的代码:

private SyncAndTradeService syncAndTradeService;
private boolean hasBounded = false;

private Intent syncAndTradeServiceIntent;

private ServiceConnection syncAndTradeServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        SyncAndTradeService.SyncAndTradeBinder syncAndTradeBinder = (SyncAndTradeService.SyncAndTradeBinder) service;
        syncAndTradeService = syncAndTradeBinder.getSyncAndTradeService();
        hasBounded = true;
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        syncAndTradeService = null;
        hasBounded = false;
    }
};

我尝试在 onCreate 方法中这样做:

syncAndTradeServiceIntent = new Intent(this, SyncAndTradeService.class);

bindService(syncAndTradeServiceIntent, syncAndTradeServiceConnection, Context.BIND_AUTO_CREATE);

这是我的服务代码:

public class SyncAndTradeService extends Service {

    public static final int MY_FOREGROUND_SERVICE_START_ID = 996539;

    private IBinder syncAndTradeBinder = new SyncAndTradeBinder();

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        startSyncAndTradeService();

        return Service.START_REDELIVER_INTENT;
    }

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

    @Override
    public boolean onUnbind(Intent intent) {
        return false;
    }

    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    public class SyncAndTradeBinder extends Binder {

        public SyncAndTradeService getSyncAndTradeService() {
            return SyncAndTradeService.this;
        }

    }

    private void startSyncAndTradeService() {
        startForeground(MY_FOREGROUND_SERVICE_START_ID, buildFixedNotification());
    }

    private Notification buildFixedNotification() {

        Intent notificationIntent = new Intent(this, MainActivity.class);

        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

        Notification notification = new Notification.Builder(this)
            .setContentTitle("OKCoin Robot")
            .setContentText("OKCoin robot is running in background")
            .setSmallIcon(R.drawable.bitcoin)
            .setContentIntent(pendingIntent)
            .build();

        return notification;
    }

}

这是我在 Manifest.xml

中的服务声明
<service
    android:name=".service.SyncAndTradeService"
    android:exported="false"
    android:icon="@drawable/bitcoin"
    android:process=":SyncAndTrade">
</service>

等不及了,趁着一整天的空闲时间继续研究,幸运的找到了解决办法,希望能对像我这样的初学者有所帮助。

  • 如果你 运行 服务与你的应用程序在同一个进程中,这意味着你应该在 Manifest.xml 中声明服务而不是 'android:process',如果你这样做,那么以上绝对没问题。
  • 当您尝试将您的应用程序组件绑定到 运行 在不同进程中的服务时,将抛出上述异常
  • 所以解决方案是用 AIDL 包装你的 IBinder。
  • 以下是基于上述代码的代码

定义你的 AIDL 接口

package com.leonard.sg.okcoin.service.robot.aidl;

interface ISyncAndTradeService {

    boolean startTradeEngine();

}

然后将您服务中的 onBind 方法更改为:

@Override
public IBinder onBind(Intent intent) {
    return new ISyncAndTradeService.Stub() {

        @Override
        public boolean startTradeEngine() throws RemoteException {
            return false;
        }
    };
}

然后将构建服务连接class细化为:

private ISyncAndTradeService syncAndTradeService;
private boolean hasBounded = false;

private Intent syncAndTradeServiceIntent;

private ServiceConnection syncAndTradeServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        syncAndTradeService = ISyncAndTradeService.Stub.asInterface((IBinder) service);
        hasBounded = true;
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        syncAndTradeService = null;
        hasBounded = false;
    }
};

那么一切正常

但这又引发了另一个问题,根据服务声明属性'android:process'的google文档,我们可以这样做:

android:process The name of the process where the service is to run. Normally, all components of an application run in the default process created for the application. It has the same name as the application package. The element's process attribute can set a different default for all components. But component can override the default with its own process attribute, allowing you to spread your application across multiple processes. If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the service runs in that process. If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage.

但实际上,如果我声明 'android:process' 以字符开头,无论是小写还是大写,我都会得到这个错误:

DEVICE SHELL COMMAND: pm install -r "/data/local/tmp/com.leonard.sg.okcoin"
pkg: /data/local/tmp/com.leonard.sg.okcoin
Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED]

唯一的选择是以':'或'.'开头

我刚刚删除了 activity 中的以下行。它工作正常。 android:process=":UsbEventReceiverActivityProcess"