如何广播意图中的可包裹物体? [英] How to broadcast a parcelable object in an intent?

查看:56
本文介绍了如何广播意图中的可包裹物体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Java/Android的新手,正在尝试开发与USB CAN总线适配器通信的adroid应用程序.我通过CANBusController类以字符串形式接收来自适配器的消息,并建立了一个可打包的类CANMessage,该类将接收到的字符串转换为我可以使用的形式(int Id,int Length,byte []数据).现在,我试图显示我收到的消息.我有一个片段,CANBusControlFragment,它声明了BroadcastReceiver.收到消息后,我将构建我的CANMessage,并将其及其字符串放入一个包中,将该包放入一个Intent中,然后使用sendBroadcast(intent):

I'm new to Java / Android and trying to develop an adroid application which communicates with a USB CAN Bus adapter. I receive messages from the adapter in a string via my CANBusController class and I have built a parcelable class, CANMessage, which converts the string received into a form I can use (int Id, int Length, byte[] data). Now I'm trying to display the message I have received. I have a Fragment, CANBusControlFragment, which declares a BroadcastReceiver. When a message is a received, I build my CANMessage, place it and its string into a bundle, place the bundle into an Intent, and use sendBroadcast(intent):

CANBusController
{
    public void handleMessage(Message msg)
    {
        Bundle bundle = msg.getData();
        CANMessage canMsg = bundle.getParcelable("CAN_MESSAGE");
        if (canMsg != null)
        {
            Intent intent = new Intent();
            intent.setAction(BroadcastActions.CAN_MESSAGE_RECEIVED);
            //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.putExtra("CAN_MESSAGE", canMsg);
            intent.putExtra("STRING_MESSAGE", canMsg.toString());
            parentContext.sendBroadcast(intent);
        }
    }
}

CANBusControlFragment extends Fragment
{
    private final BroadcastReceiver canMsgReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            String action = intent.getAction();
            Bundle bundle = intent.getExtras();
            try
            {
                if (BroadcastActions.CAN_MESSAGE_RECEIVED.equals(action))
                {
                    synchronized(this)
                    {
                        String str = bundle.getString("STRING_MESSAGE"); // <-- Crash
                        CANMessage canMsg = bundle.getParcelable("CAN_MESSAGE"); // 
                        Append(str);
                        Append(canMsg.toString();
                    }
                }
            }
            catch (Exception ex)
                print exception
        }
    }
}

如果我将CANMessage添加到包中,当我尝试getString或getParcelable时,我的应用程序将在BroadcastReceiver的onReceived方法中崩溃,并出现Null指针异常.如果我不包括CANMessage,则该应用程序将正常运行.我相信CANMessage可以正确实现Parcelable,因为我已经通过执行所有相同的步骤(广播消息除外)对其进行了测试:构建CANMessage,将BunParcelable放入Bundle,将Bundle放入Intent,将Bundle移出Intent,将getParcelable移出Intent.捆绑包.

If I add the CANMessage to the bundle, my application will crash in the onReceived method of the BroadcastReceiver with a Null Pointer Exception when I try to getString or getParcelable. If I do not include the CANMessage, then the application will work fine. I believe CANMessage implements Parcelable correctly, since I've tested it by performing all of the same steps except for broadcasting the message: Build CANMessage, putParcelable in Bundle, put Bundle in Intent, grab the Bundle out of the Intent, getParcelable out of the bundle.

感谢您的帮助.谢谢:)

I appreciate any help. Thanks :)

编辑-LogCat信息: 看来错误出在我的包裹方法中.尝试readByteArray(byte [])会使应用程序崩溃.

EDIT - LogCat information: It appears the error is in my parcel methods. Trying to readByteArray(byte[]) crashes the app.

11-12 09:17:44.568: E/AndroidRuntime(3087): FATAL EXCEPTION: main

11-12 09:17:44.568: E/AndroidRuntime(3087): java.lang.RuntimeException: Error receiving broadcast Intent { act=com.sb2tablet.CAN_MESSAGE_RECEIVED flg=0x10000010 (has extras) } in com.sb2tablet.CANBusControlFragment$1@9e8f6e00
11-12 09:17:44.568: E/AndroidRuntime(3087):     at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:768)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at android.os.Handler.handleCallback(Handler.java:725)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at android.os.Handler.dispatchMessage(Handler.java:92)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at android.os.Looper.loop(Looper.java:137)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at android.app.ActivityThread.main(ActivityThread.java:5041)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at java.lang.reflect.Method.invokeNative(Native Method)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at java.lang.reflect.Method.invoke(Method.java:511)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at dalvik.system.NativeStart.main(Native Method)
11-12 09:17:44.568: E/AndroidRuntime(3087): Caused by: java.lang.NullPointerException
11-12 09:17:44.568: E/AndroidRuntime(3087):     at android.os.Parcel.readByteArray(Parcel.java:1594)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at com.sb2tablet.models.CANMessage.<init>(CANMessage.java:93)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at com.sb2tablet.models.CANMessage$1.createFromParcel(CANMessage.java:18)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at com.sb2tablet.models.CANMessage$1.createFromParcel(CANMessage.java:1)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at android.os.Parcel.readParcelable(Parcel.java:2103)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at android.os.Parcel.readValue(Parcel.java:1965)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at android.os.Parcel.readMapInternal(Parcel.java:2226)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at android.os.Bundle.unparcel(Bundle.java:223)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at android.os.Bundle.containsKey(Bundle.java:271)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at android.content.Intent.hasExtra(Intent.java:4121)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at com.sb2tablet.CANBusControlFragment$1.onReceive(CANBusControlFragment.java:51)
11-12 09:17:44.568: E/AndroidRuntime(3087):     at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:758)

编辑-writeToParcel和宗地:

Edit - writeToParcel and Parcel in:

public void writeToParcel(Parcel out, int flags)
{
    out.writeValue(id);    // int
    out.writeValue(len);   // int
    out.writevalue(data);  // byteArray, the value is not null here
    //out.writeByArray(data);
}

public CANMessage(Parcel in)
{
    id = in.readInt();
    len = in.readInt();
    in.readByteArray(data); // Actual crash is here
}

编辑-测试用例1-似乎多余的数据已添加到我的包裹中,我不确定如何添加.

EDIT - Test Case 1 - It seems extra data is added to my parcel, I'm not sure how.

public void writeToParcel(Parcel out, int flags)
{
    out.writeValue(id);    // int = 256
    out.writeValue(len);   // int = 2, length of byte array
    out.writevalue(data);  // byte array = { 17, 51 }
}

public CANMessage(Parcel in)
{
    len = in.readInt();        // 1
    id = in.readInt();         // 256
    len = in.readInt();        // 1
    len = in.readInt();        // 2
    int i = in.readInt();      // 13
    if (data == null) data = new byte[len];
    in.readByteArray(data);    // data = { 17, 51 }
}

编辑-测试用例2

public void writeToParcel(Parcel out, int flags)
{
    out.writeValue(id);       // int = 256
    out.writeValue(len);      // int = 2, length of byte array
    out.writeByteArray(data); // byte array = { 17, 51 }
}

public CANMessage(Parcel in)
{
    len = in.readInt();        // 1
    id = in.readInt();         // 256
    len = in.readInt();        // 1
    len = in.readInt();        // 2
    len = in.readInt();        // 2
    if (data == null) data = new byte[len];
    // in.readByteArray(data); // Crashes
    int i = in.readInt();      // 13073 = 0x3311 = byte[] { 17, 51 }
}

推荐答案

读取字节数组时,您需要事先分配(至少)正确大小的字节数组.像这样:

When you read a byte array, you need to have previously allocated a byte array of (at least) the correct size. Like this:

byte[] blah = new byte[100];
in.readByteArray(blah);

此外,您也不想使用writeValue()将原语写入Parcel.使用适当的方法.示例:

Also, you don't want to use writeValue() to write primitives to the Parcel. Use the appropriate methods. Example:

out.writeInt(id);    // int = 256
out.writeInt(len);   // int = 2, length of byte array
out.writeByteArray(data);  // byte array = { 17, 51 }

您必须始终将宗地上的write()方法与相同类型的read()方法配对.例如,如果使用writeValue()将某些内容写入Parcel,则必须使用readValue()进行读取.如果您知道该变量是int,则应使用writeInt()编写并使用readInt()读取.如果使用writeValue()编写对象,则对象的类型"也会写入Parcel中,以便readValue()知道它是什么类型的对象.这就是为什么您在Parcel中看到额外数据的原因.

You must always pair the write() methods with the same type of read() methods on the parcel. For example, if you use writeValue() to write something into the Parcel, you must read it using readValue(). If you know that the variable is an int, then you should write it using writeInt() and read it using readInt(). If you write it using writeValue() then the "type" of the object is also written to the Parcel so that readValue() will know what type of object it is. This is why you are seeing extra data in the Parcel.

这篇关于如何广播意图中的可包裹物体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆