Java应用程序和本机守护程序之间的交互 ​​- Parcel.readException

时间:2018-02-28 18:33:15

标签: android android-binder

我正在研究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__ */

0 个答案:

没有答案