我正在研究Java应用程序需要与本机守护程序进行交互的要求。 Java应用程序发出命令,如Start,Stop等等。本机守护程序处理这些请求并将响应发送回Java应用程序。 我正在使用binder机制在Java应用程序和本机守护进程之间进行交互。
但是,在处理来自本机守护程序的响应时,我发现了一个致命的异常:
--------- beginning of crash
02-27 21:07:58.507 3401 3401 E AndroidRuntime: FATAL EXCEPTION: main
02-27 21:07:58.507 3401 3401 E AndroidRuntime: Process: com.symbol.demosettings, PID: 3401
02-27 21:07:58.507 3401 3401 E AndroidRuntime: java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.wifi.WIFI_STATE_CHANGED flg=0x4000010 (has extras) } in com.symbol.demosettings.SettingsActivity$GeneralPreferenceFragment$1@4f51a41
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$-android_app_LoadedApk$ReceiverDispatcher$Args_52497(LoadedApk.java:1323)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at android.app.-$Lambda$aS31cHIhRx41653CMnd4gZqshIQ.$m$7(Unknown Source:4)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at android.app.-$Lambda$aS31cHIhRx41653CMnd4gZqshIQ.run(Unknown Source:39)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:790)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:99)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at android.os.Looper.loop(Looper.java:164)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6501)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: Caused by: java.lang.RuntimeException: Unknown exception code: 47 msg null
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at android.os.Parcel.readException(Parcel.java:2020)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at android.os.Parcel.readException(Parcel.java:1950)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at yancy.github.nativeservice.IDemoService$Stub$Proxy.AddNumber(IDemoService.java:97)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at com.symbol.demosettings.SettingsActivity$GeneralPreferenceFragment.bindDemoService(SettingsActivity.java:576)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at com.symbol.demosettings.SettingsActivity$GeneralPreferenceFragment.-wrap1(Unknown Source:0)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at com.symbol.demosettings.SettingsActivity$GeneralPreferenceFragment$1.onReceive(SettingsActivity.java:377)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$-android_app_LoadedApk$ReceiverDispatcher$Args_52497(LoadedApk.java:1313)
02-27 21:07:58.507 3401 3401 E AndroidRuntime: ... 9 more
02-27 21:07:58.511 1585 1604 W ActivityManager: Force finishing activity com.symbol.demosettings/.SettingsActivity
与动态守护进程交互的SettingsActivity.java片段如下:
private BroadcastReceiver WifiStateChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int extraWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE ,
WifiManager.WIFI_STATE_UNKNOWN);
switch (extraWifiState) {
case WifiManager.WIFI_STATE_ENABLED:
bindDemoService();
break;
case WifiManager.WIFI_STATE_ENABLING:
break;
case WifiManager.WIFI_STATE_UNKNOWN:
break;
}
}
};
private void bindDemoService() {
try {
IBinder b = ServiceManager.getService("yancy.github.nativeservice.IDemoService");
if(b != null) {
final IDemoService service =
IDemoService.Stub.asInterface(b);
if(service != null) {
Log.d("DEMOSERVICE", "AddNumber(23, 24): " + service.AddNumber(1, 2));
Log.d("DEMOSERVICE", "MaxNumber(23, 24): " + service.MaxNumber(10, 11));
Log.d("DEMOSERVICE", "MaxNumber(33, 24): " + service.MaxNumber(20, 21));
} else {
Log.d("DEMOSERVICE", "MainActivity asInterface fail.");
}
} else {
Log.d("DEMOSERVICE", "MainActivity get native service fail.");
}
} catch(RemoteException e) {
Log.d("DEMOSERVICE", "ERROR:" + e.getMessage());
}
}
下面给出了相应的AIDL(IDemoService.aidl):
package yancy.github.nativeservice;
interface IDemoService {
int AddNumber(int a, int b);
int MaxNumber(int a, int b);
}
本机守护程序部分如下:
DemoService.cpp:
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "IDemoService.h"
#include "DemoService.h"
#define LOG_NDEBUG 0
#define LOG_TAG "DEMOSERVICE"
#include <utils/Log.h>
int DemoService::AddNumber(int a,int b)
{
ALOGD("DemoService AddNumber a:%d, b:%d\n", a, b);
return a + b;
}
int DemoService::MaxNumber(int a,int b)
{
ALOGD("DemoService MaxNumber a:%d, b:%d\n", a, b);
return a > b ? a : b;
}
int main(int argc, char** argv)
{
DemoService::instance();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
IDemoService.cpp:
#define LOG_NDEBUG 0
#define LOG_TAG "DEMOSERVICE"
#include <utils/Log.h>
#include "IDemoService.h"
using namespace android;
class BpDemoService : public BpInterface<IDemoService>
{
public:
BpDemoService(const sp<IBinder>& impl) : BpInterface<IDemoService>(impl){};
int AddNumber(int a, int b)
{
ALOGD("BpDemoService AddNumber a:%d , b:%d\n", a, b);
Parcel data;
data.writeInterfaceToken(IDemoService::getInterfaceDescriptor());
data.writeInt32(a);
data.writeInt32(b);
Parcel reply;
remote()->transact(ADD_NUMBER, data, &reply);
if (reply.readExceptionCode() != 0) {
ALOGD("IDemoService got an exception %i", reply.readExceptionCode());
return -1;
}
return reply.readInt32();
}
int MaxNumber(int a, int b)
{
ALOGD("BpDemoService MaxNumber a:%d , b:%d\n", a, b);
Parcel data;
data.writeInterfaceToken(IDemoService::getInterfaceDescriptor());
data.writeInt32(a);
data.writeInt32(b);
Parcel reply;
remote()->transact(MAX_NUMBER, data, &reply);
if (reply.readExceptionCode() != 0) {
ALOGD("IDemoService got an exception %i", reply.readExceptionCode());
return -1;
}
return reply.readInt32();
}
};
IMPLEMENT_META_INTERFACE(DemoService, SERVICE_NAME);
status_t BnDemoService::onTransact(uint32_t code,const Parcel & data,Parcel * reply, uint32_t flags)
{
switch(code)
{
case ADD_NUMBER:
{
CHECK_INTERFACE(IDemoService, data, reply);
int ret = AddNumber(data.readInt32(), data.readInt32());
ALOGD("BpDemoService ADD_NUMBER ret:%d\n", ret);
reply->writeInt32(ret);
return NO_ERROR;
}
case MAX_NUMBER:
{
CHECK_INTERFACE(IDemoService, data, reply);
int ret = MaxNumber(data.readInt32(), data.readInt32());
ALOGD("BpDemoService MAX_NUMBER ret:%d\n", ret);
reply->writeInt32(ret);
return NO_ERROR;
}
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
DemoService.h:
#ifndef __DEMO_SERVICE_H__
#define __DEMO_SERVICE_H__
#include "IDemoService.h"
class DemoService : public BnDemoService
{
public:
int AddNumber(int a, int b);
int MaxNumber(int a, int b);
static void instance()
{
defaultServiceManager()->addService(String16(SERVICE_NAME), new DemoService());
};
};
#endif /* __DEMO_SERVICE_H__ */
IDemoService.h:
#ifndef __I_DEMO_SERVICE_H__
#define __I_DEMO_SERVICE_H__
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
using namespace android;
#define SERVICE_NAME "yancy.github.nativeservice.IDemoService"
enum {
ADD_NUMBER = IBinder::FIRST_CALL_TRANSACTION,
MAX_NUMBER
};
class IDemoService : public IInterface
{
public:
DECLARE_META_INTERFACE(DemoService);
virtual int AddNumber(int a, int b) = 0;
virtual int MaxNumber(int a, int b) = 0;
};
class BnDemoService : public BnInterface<IDemoService>
{
public:
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
};
#endif /* __I_DEMO_SERVICE_H__ */