java.lang.ClassCastException: android.os.BinderProxy не может быть приведен к 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$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>
2 ответа
Не могу дождаться, поэтому продолжал исследовать, когда я был свободен целый день, к счастью, нашел решение, надеюсь, это поможет некоторым новичкам, таким как я.
- если вы запускаете службу в том же процессе, что и приложение ur, это означает, что вы должны объявить службу в Manifest.xml без 'android:process', если вы делаете это, то вышеприведенное абсолютно нормально работает.
- вышеприведенное исключение будет сгенерировано, когда вы попытаетесь связать ваш компонент приложения со службой, запущенной в другом процессе
- Таким образом, решение заключается в том, чтобы обернуть IBinder с AIDL.
- Ниже приведен код на основе вышеупомянутого
определить интерфейс 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;
}
};
}
затем уточните класс подключения службы сборки к этому:
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;
}
};
тогда все будет работать нормально
но это поднимает еще одну проблему, согласно документации Google по атрибуту 'android: process' декларации сервиса, мы можем сделать это:
android: process Имя процесса, в котором должен запускаться сервис. Обычно все компоненты приложения выполняются в процессе по умолчанию, созданном для приложения. Он имеет то же имя, что и пакет приложения. Атрибут процесса элемента может установить разные значения по умолчанию для всех компонентов. Но компонент может переопределить значение по умолчанию своим собственным атрибутом процесса, что позволяет распределить ваше приложение по нескольким процессам. Если имя, назначенное этому атрибуту, начинается с двоеточия (':'), новый процесс, частный для приложения, создается, когда это необходимо, и служба запускается в этом процессе. Если имя процесса начинается со строчной буквы, служба будет запускаться в глобальном процессе с таким именем, если у него есть разрешение на это. Это позволяет компонентам в разных приложениях совместно использовать процесс, сокращая использование ресурсов.
но на практике, если я объявлю, что "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]
единственный выбор - начать с ':' или '.'
Я просто удаляю строку ниже в своей деятельности. он работает нормально. android:process=":UsbEventReceiverActivityProcess"