Parcelable 写序列化对象遇到IOException [QUICKBLOX DIALOG]
Parcelable encountered IOException writing serializable object [QUICKBLOX DIALOG]
自 4 月 15 日以来,我在 quickblox 中遇到了一个问题,当时 Quickblox 将 android 的 SDK 更新为 2.5.2。
我注意到的问题是,如果我为对话框填充了 customData 参数,那么它会抛出下面提到的 IOExeption。否则没问题。
没有问题的对话框。
QBDialog{id=xxxx, created_at=2016-19-04 11:36:54,
last_msg_user_id=xxxx, occupants_ids=[xxxx, xxxx, last_message=hey,
last_message_date_sent=1461046124, type=PRIVATE, name=xxxx,
room_jid=null, user_id=xxxx, photo=null, unread_message_count=0,
customData=null}
导致崩溃的对话框。
QBDialog{id=xxxx, created_at=2016-19-04 12:01:00,
last_msg_user_id=xxxx, occupants_ids=[xxxx, xxxx], last_message=hello,
last_message_date_sent=1461047494, type=PRIVATE, name=xxxx,
room_jid=null, user_id=xxxx, photo=null, unread_message_count=1,
customData=QBBaseCustomObject{className='DialogueRelationState',
fields={isFriends=true, location_field=null}}}
将上述对话框传递给 Activity_chat class
的代码段
Bundle bundle = new Bundle();
bundle.getString(selectedDialog.toString());
bundle.putSerializable(Activity_Chat.EXTRA_DIALOG, selectedDialog);
Activity_Chat.start(DrawActivity_Chatlist.this, bundle);// error points here
接收启动方法Activity
public static void start(Context context, Bundle bundle) {
Intent intent = new Intent(context, Activity_Chat.class);
intent.putExtras(bundle);
context.startActivity(intent); //error points here
}
错误日志:
Fatal Exception: java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.quickblox.chat.model.QBDialog)
at android.os.Parcel.writeSerializable(Parcel.java:1323)
at android.os.Parcel.writeValue(Parcel.java:1271)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:618)
at android.os.Bundle.writeToParcel(Bundle.java:1692)
at android.os.Parcel.writeBundle(Parcel.java:643)
at android.content.Intent.writeToParcel(Intent.java:7152)
at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2663)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1419)
at android.app.Activity.startActivityForResult(Activity.java:3532)
at android.app.Activity.startActivityForResult(Activity.java:3458)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:784)
at android.app.Activity.startActivity(Activity.java:3780)
at android.app.Activity.startActivity(Activity.java:3748)
at com.social.fitspur.activities.Activity_Chat.start(Activity_Chat.java:100)
at com.social.fitspur.activities.DrawActivity_Chatlist.onItemClick(DrawActivity_Chatlist.java:198)
at android.widget.AdapterView.performItemClick(AdapterView.java:299)
at android.widget.AbsListView.performItemClick(AbsListView.java:1162)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:2953)
at android.widget.AbsListView.run(AbsListView.java:3708)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:149)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(NativeStart.java)
Caused by java.io.NotSerializableException: org.json.JSONObject
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1366)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1673)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1519)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1483)
at java.util.HashMap.writeObject(HashMap.java:995)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:515)
at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1055)
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1406)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1673)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1519)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:981)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368)
at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1076)
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1406)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1673)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1519)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:981)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368)
at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1076)
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1406)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1673)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1519)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1483)
at android.os.Parcel.writeSerializable(Parcel.java:1318)
at android.os.Parcel.writeValue(Parcel.java:1271)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:618)
at android.os.Bundle.writeToParcel(Bundle.java:1692)
at android.os.Parcel.writeBundle(Parcel.java:643)
at android.content.Intent.writeToParcel(Intent.java:7152)
at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2663)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1419)
at android.app.Activity.startActivityForResult(Activity.java:3532)
at android.app.Activity.startActivityForResult(Activity.java:3458)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:784)
at android.app.Activity.startActivity(Activity.java:3780)
at android.app.Activity.startActivity(Activity.java:3748)
at com.social.fitspur.activities.Activity_Chat.start(Activity_Chat.java:100)
at com.social.fitspur.activities.DrawActivity_Chatlist.onItemClick(DrawActivity_Chatlist.java:198)
at android.widget.AdapterView.performItemClick(AdapterView.java:299)
at android.widget.AbsListView.performItemClick(AbsListView.java:1162)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:2953)
at android.widget.AbsListView.run(AbsListView.java:3708)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:149)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(NativeStart.java)
据我了解,它在对话框中遇到了 JSON 不可序列化的内容,因此出现了错误。
注意:这在 4 月 15 日之前工作正常,我也没有对我的自定义 class 进行任何更改
我试过将SDK版本从v2.5升级到v2.5.2,但是没有用。
QuickBlox 最近添加了一个 location_field,它返回一个 jsonObject 但期望是字符串。最后在获取对话框时添加此行就成功了。
for (QBDialog dialog : dialogs) {
QBDialogCustomData customData = dialog.getCustomData();
usersIDs.addAll(dialog.getOccupants());
if (customData == null) {
continue;
}
HashMap<String, Object> fields = customData.getFields();
if (!fields.isEmpty()) {
fields.put("location_field", null);
}
}
我的解决方案是排除简单的日期格式:
public static void setGroupDialog(QBDialog qbDialog) {
GsonBuilder builder = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getName().equals("sdf");
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
});
String json = builder.create().toJson(qbDialog);
getAuthPreferences(YOUR_APP_CONTEXT).edit()
.putString(PREF_GROUP_DIALOG, json).commit();
}
我遇到了同样的问题。相反,现在我的整个项目都受到这个问题的影响。因此,目前我正在使用这种技术,但它并不好,但我们可以使用,后来当他们更新 SDK 时,我们可以在几秒钟内恢复我们的更改。我所有依赖于 QBDialog 的 classes 现在都崩溃了。所以现在我要与您分享我的 class 代码块之一。可能对你有帮助。
崩溃代码:
public class ChattingActivity extends ... {
public static final void start(Context context, QBDialog qbDialog)
{
Intent intent = new Intent(context,ChattingActivity.class);
intent.putExtra(Intent.EXTRA_STREAM, qbDialog);
context.startActivity(intent); // Crash when try to start
}
}
稳定代码:
public class ChattingActivity extends ... {
private static QBDialog QB_DIALOG;
public static final void start(Context context, QBDialog qbDialog)
{
Intent intent = new Intent(context,ChattingActivity.class);
// intent.putExtra(Intent.EXTRA_STREAM, qbDialog);
ChattingActivity.QB_DIALOG = qbDialog;
context.startActivity(intent); // Crash when try to start
}
// Important: Should do null in OnDestroy.
@Override
protected void onDestroy() {
super.onDestroy();
QB_DIALOG = null;
}
}
自 4 月 15 日以来,我在 quickblox 中遇到了一个问题,当时 Quickblox 将 android 的 SDK 更新为 2.5.2。 我注意到的问题是,如果我为对话框填充了 customData 参数,那么它会抛出下面提到的 IOExeption。否则没问题。
没有问题的对话框。
QBDialog{id=xxxx, created_at=2016-19-04 11:36:54, last_msg_user_id=xxxx, occupants_ids=[xxxx, xxxx, last_message=hey, last_message_date_sent=1461046124, type=PRIVATE, name=xxxx, room_jid=null, user_id=xxxx, photo=null, unread_message_count=0, customData=null}
导致崩溃的对话框。
QBDialog{id=xxxx, created_at=2016-19-04 12:01:00, last_msg_user_id=xxxx, occupants_ids=[xxxx, xxxx], last_message=hello, last_message_date_sent=1461047494, type=PRIVATE, name=xxxx, room_jid=null, user_id=xxxx, photo=null, unread_message_count=1, customData=QBBaseCustomObject{className='DialogueRelationState', fields={isFriends=true, location_field=null}}}
将上述对话框传递给 Activity_chat class
的代码段Bundle bundle = new Bundle();
bundle.getString(selectedDialog.toString());
bundle.putSerializable(Activity_Chat.EXTRA_DIALOG, selectedDialog);
Activity_Chat.start(DrawActivity_Chatlist.this, bundle);// error points here
接收启动方法Activity
public static void start(Context context, Bundle bundle) {
Intent intent = new Intent(context, Activity_Chat.class);
intent.putExtras(bundle);
context.startActivity(intent); //error points here
}
错误日志:
Fatal Exception: java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.quickblox.chat.model.QBDialog)
at android.os.Parcel.writeSerializable(Parcel.java:1323)
at android.os.Parcel.writeValue(Parcel.java:1271)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:618)
at android.os.Bundle.writeToParcel(Bundle.java:1692)
at android.os.Parcel.writeBundle(Parcel.java:643)
at android.content.Intent.writeToParcel(Intent.java:7152)
at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2663)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1419)
at android.app.Activity.startActivityForResult(Activity.java:3532)
at android.app.Activity.startActivityForResult(Activity.java:3458)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:784)
at android.app.Activity.startActivity(Activity.java:3780)
at android.app.Activity.startActivity(Activity.java:3748)
at com.social.fitspur.activities.Activity_Chat.start(Activity_Chat.java:100)
at com.social.fitspur.activities.DrawActivity_Chatlist.onItemClick(DrawActivity_Chatlist.java:198)
at android.widget.AdapterView.performItemClick(AdapterView.java:299)
at android.widget.AbsListView.performItemClick(AbsListView.java:1162)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:2953)
at android.widget.AbsListView.run(AbsListView.java:3708)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:149)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(NativeStart.java)
Caused by java.io.NotSerializableException: org.json.JSONObject
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1366)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1673)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1519)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1483)
at java.util.HashMap.writeObject(HashMap.java:995)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:515)
at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1055)
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1406)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1673)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1519)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:981)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368)
at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1076)
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1406)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1673)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1519)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:981)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368)
at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1076)
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1406)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1673)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1519)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1483)
at android.os.Parcel.writeSerializable(Parcel.java:1318)
at android.os.Parcel.writeValue(Parcel.java:1271)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:618)
at android.os.Bundle.writeToParcel(Bundle.java:1692)
at android.os.Parcel.writeBundle(Parcel.java:643)
at android.content.Intent.writeToParcel(Intent.java:7152)
at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2663)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1419)
at android.app.Activity.startActivityForResult(Activity.java:3532)
at android.app.Activity.startActivityForResult(Activity.java:3458)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:784)
at android.app.Activity.startActivity(Activity.java:3780)
at android.app.Activity.startActivity(Activity.java:3748)
at com.social.fitspur.activities.Activity_Chat.start(Activity_Chat.java:100)
at com.social.fitspur.activities.DrawActivity_Chatlist.onItemClick(DrawActivity_Chatlist.java:198)
at android.widget.AdapterView.performItemClick(AdapterView.java:299)
at android.widget.AbsListView.performItemClick(AbsListView.java:1162)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:2953)
at android.widget.AbsListView.run(AbsListView.java:3708)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:149)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(NativeStart.java)
据我了解,它在对话框中遇到了 JSON 不可序列化的内容,因此出现了错误。
注意:这在 4 月 15 日之前工作正常,我也没有对我的自定义 class 进行任何更改
我试过将SDK版本从v2.5升级到v2.5.2,但是没有用。
QuickBlox 最近添加了一个 location_field,它返回一个 jsonObject 但期望是字符串。最后在获取对话框时添加此行就成功了。
for (QBDialog dialog : dialogs) {
QBDialogCustomData customData = dialog.getCustomData();
usersIDs.addAll(dialog.getOccupants());
if (customData == null) {
continue;
}
HashMap<String, Object> fields = customData.getFields();
if (!fields.isEmpty()) {
fields.put("location_field", null);
}
}
我的解决方案是排除简单的日期格式:
public static void setGroupDialog(QBDialog qbDialog) {
GsonBuilder builder = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getName().equals("sdf");
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
});
String json = builder.create().toJson(qbDialog);
getAuthPreferences(YOUR_APP_CONTEXT).edit()
.putString(PREF_GROUP_DIALOG, json).commit();
}
我遇到了同样的问题。相反,现在我的整个项目都受到这个问题的影响。因此,目前我正在使用这种技术,但它并不好,但我们可以使用,后来当他们更新 SDK 时,我们可以在几秒钟内恢复我们的更改。我所有依赖于 QBDialog 的 classes 现在都崩溃了。所以现在我要与您分享我的 class 代码块之一。可能对你有帮助。
崩溃代码:
public class ChattingActivity extends ... {
public static final void start(Context context, QBDialog qbDialog)
{
Intent intent = new Intent(context,ChattingActivity.class);
intent.putExtra(Intent.EXTRA_STREAM, qbDialog);
context.startActivity(intent); // Crash when try to start
}
}
稳定代码:
public class ChattingActivity extends ... {
private static QBDialog QB_DIALOG;
public static final void start(Context context, QBDialog qbDialog)
{
Intent intent = new Intent(context,ChattingActivity.class);
// intent.putExtra(Intent.EXTRA_STREAM, qbDialog);
ChattingActivity.QB_DIALOG = qbDialog;
context.startActivity(intent); // Crash when try to start
}
// Important: Should do null in OnDestroy.
@Override
protected void onDestroy() {
super.onDestroy();
QB_DIALOG = null;
}
}