我试图将 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/