Как передать вещный объект с намерением?

Я новичок в Java / Android и пытаюсь разработать приложение для Android, которое взаимодействует с адаптером USB CAN Bus. Я получаю сообщения от адаптера в виде строки через мой класс CANBusController, и я создал пакетный класс CANMessage, который преобразует полученную строку в форму, которую я могу использовать (int Id, int Length, byte[] data). Сейчас я пытаюсь отобразить сообщение, которое я получил. У меня есть фрагмент, CANBusControlFragment, который объявляет BroadcastReceiver. Когда сообщение получено, я создаю свое сообщение CANMessage, помещаю его и его строку в пакет, помещаю пакет в намерение и использую sendBroadcast(намерение):

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 в комплект, мое приложение будет аварийно завершено в методе onReceived BroadcastReceiver с исключением Null Pointer, когда я пытаюсь получить getString или getParcelable. Если я не включу CANMessage, то приложение будет работать нормально. Я полагаю, что CANMessage правильно реализует Parcelable, так как я проверил его, выполнив все те же шаги, за исключением широковещательной рассылки сообщения: Build CANMessage, putParcelable в Bundle, поместите Bundle в Intent, вытащите Bundle из Intent, getParcelable из расслоение.

Я ценю любую помощь. Спасибо:)

РЕДАКТИРОВАТЬ - информация LogCat: Кажется, ошибка в моих методах посылки. Попытка readByteArray(byte[]) приводит к сбою приложения.

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)

Изменить - напишите ToParcel и Parcel в:

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 - Кажется, дополнительные данные добавляются в мою посылку, я не знаю, как.

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 }
}

1 ответ

Решение

Когда вы читаете байтовый массив, вам необходимо предварительно выделить байтовый массив (как минимум) правильного размера. Как это:

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

Кроме того, вы не хотите использовать writeValue() писать примитивы к Parcel, Используйте соответствующие методы. Пример:

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,

Другие вопросы по тегам