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

标签 java android foreground-service

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

java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.leonard.sg.okcoin.service.SyncAndTradeService$SyncAndTradeBinder
        at com.leonard.sg.okcoin.MainActivity$1.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>

最佳答案

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

  • 如果您在与您的应用程序相同的进程中运行该服务,这意味着您应该在没有“android:process”的 Manifest.xml 中声明该服务,如果您这样做,那么以上内容绝对可以正常工作。
  • 当您尝试将您的应用程序组件绑定(bind)到在不同进程中运行的服务时,将抛出上述异常
  • 所以解决方案是用 AIDL 包装您的 IBinder。
  • 以下是基于上述代码的代码

定义您的 AIDL 接口(interface)

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

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

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]

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

关于java.lang.ClassCastException : android. os.BinderProxy 无法转换为 com.leonard.sg.okcoin.service.SyncAndTradeService$SyncAndTradeBinder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29898364/

相关文章:

android - 如何从我的 Android 应用程序检测已安装的 Chrome 版本?

android - 如何从 Android 中的对话框启动 Activity

java - Android HandlerThread 在没有 UiHandler 的情况下更新 UI

android - 前台通知服务在一加设备中不起作用

java - Gradle 传递依赖解析

java - SHA-256 自定义长度摘要

Java 委托(delegate)?

java - Spring JPA、Eclipselink 和审计

java - 前台服务从 MainActivity 启动操作

Android 8.1.0 前台服务通知问题