Как передать вещный объект с намерением?
Я новичок в 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
,