Skip to content

Commit 4f033b3

Browse files
Fixed: Add explicit serialVersionUID to Serializable classes like ReportInfo and TextIOInfo
Reading `ReportInfo` with `Bundle.getSerializable()` by `ReportActivity` is triggering exception when default algorithm is used for `serialVersionUID` in Termux:API plugin app when error notification created in `ResultReturner.returnData()` by `TermuxPluginUtils.sendPluginCommandErrorNotification()` is clicked. ``` java.lang.RuntimeException: Unable to start activity ComponentInfo{com.termux/com.termux.shared.activities.ReportActivity}: android.os.BadParcelableException: Parcelable encountered IOException reading a Serializable object (name = com.termux.shared.models.ReportInfo) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4280) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4467) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:222) at android.app.servertransaction.TransactionExecutor.executeNonLifecycleItem(TransactionExecutor.java:133) at android.app.servertransaction.TransactionExecutor.executeTransactionItems(TransactionExecutor.java:103) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:80) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2823) at android.os.Handler.dispatchMessage(Handler.java:110) at android.os.Looper.loopOnce(Looper.java:248) at android.os.Looper.loop(Looper.java:338) at android.app.ActivityThread.main(ActivityThread.java:9067) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932) Caused by: android.os.BadParcelableException: Parcelable encountered IOException reading a Serializable object (name = com.termux.shared.models.ReportInfo) at android.os.Parcel.readSerializableInternal(Parcel.java:5520) at android.os.Parcel.readValue(Parcel.java:5038) at android.os.Parcel.readValue(Parcel.java:4702) at android.os.Parcel.-$$Nest$mreadValue(Unknown Source:0) at android.os.Parcel$LazyValue.apply(Parcel.java:4811) at android.os.Parcel$LazyValue.apply(Parcel.java:4764) at android.os.BaseBundle.unwrapLazyValueFromMapLocked(BaseBundle.java:446) at android.os.BaseBundle.getValueAt(BaseBundle.java:426) at android.os.BaseBundle.getValue(BaseBundle.java:397) at android.os.BaseBundle.getValue(BaseBundle.java:380) at android.os.BaseBundle.getValue(BaseBundle.java:373) at android.os.BaseBundle.getSerializable(BaseBundle.java:1522) at android.os.Bundle.getSerializable(Bundle.java:1339) at com.termux.shared.activities.ReportActivity.updateUI(ReportActivity.java:140) at com.termux.shared.activities.ReportActivity.onCreate(ReportActivity.java:93) at android.app.Activity.performCreate(Activity.java:9155) at android.app.Activity.performCreate(Activity.java:9133) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1521) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4262) ... 13 more Caused by: java.io.InvalidClassException: com.termux.shared.models.ReportInfo; local class incompatible: stream classdesc serialVersionUID = -5165426368218339031, local class serialVersionUID = 1 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:652) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1743) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1624) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1902) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1442) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:430) at android.os.Parcel.readSerializableInternal(Parcel.java:5507) ... 31 more ``` If using release APK with obfuscation enabled, then following exception will be triggered. ``` java.lang.RuntimeException: Unable to start activity ComponentInfo{com.termux/com.termux.shared.activities.ReportActivity}: android.os.BadParcelableException: Parcelable encountered ClassNotFoundException reading a Serializable object (name = I0.a) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3864) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4006) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:111) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2462) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:240) at android.os.Looper.loop(Looper.java:351) at android.app.ActivityThread.main(ActivityThread.java:8377) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1013) Caused by: android.os.BadParcelableException: Parcelable encountered ClassNotFoundException reading a Serializable object (name = I0.a) at android.os.Parcel.readSerializableInternal(Parcel.java:5113) at android.os.Parcel.readValue(Parcel.java:4655) at android.os.Parcel.readValue(Parcel.java:4363) at android.os.Parcel.-$$Nest$mreadValue(Unknown Source:0) at android.os.Parcel$LazyValue.apply(Parcel.java:4461) at android.os.Parcel$LazyValue.apply(Parcel.java:4420) at android.os.BaseBundle.getValueAt(BaseBundle.java:394) at android.os.BaseBundle.getValue(BaseBundle.java:374) at android.os.BaseBundle.getValue(BaseBundle.java:357) at android.os.BaseBundle.getValue(BaseBundle.java:350) at android.os.BaseBundle.getSerializable(BaseBundle.java:1451) at android.os.Bundle.getSerializable(Bundle.java:1144) at com.termux.shared.activities.ReportActivity.updateUI(ReportActivity.java:136) at com.termux.shared.activities.ReportActivity.onCreate(ReportActivity.java:89) at android.app.Activity.performCreate(Activity.java:8397) at android.app.Activity.performCreate(Activity.java:8370) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1403) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3837) ... 12 more Caused by: java.lang.ClassNotFoundException: I0.a at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:536) at android.os.Parcel$2.resolveClass(Parcel.java:5090) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1733) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1624) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1902) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1442) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:430) at android.os.Parcel.readSerializableInternal(Parcel.java:5096) ... 29 more Caused by: java.lang.ClassNotFoundException: I0.a ... 38 more ``` Related issue termux/termux-api#762
1 parent fda17af commit 4f033b3

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

termux-shared/src/main/java/com/termux/shared/models/ReportInfo.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.termux.shared.models;
22

3+
import androidx.annotation.Keep;
4+
35
import com.termux.shared.markdown.MarkdownUtils;
46
import com.termux.shared.termux.AndroidUtils;
57

@@ -10,6 +12,25 @@
1012
*/
1113
public class ReportInfo implements Serializable {
1214

15+
/**
16+
* Explicitly define `serialVersionUID` to prevent exceptions on deserialization.
17+
*
18+
* Like when calling `Bundle.getSerializable()` on Android.
19+
* `android.os.BadParcelableException: Parcelable encountered IOException reading a Serializable object` (name = <class_name>)
20+
* `java.io.InvalidClassException: <class_name>; local class incompatible`
21+
*
22+
* The `@Keep` annotation is necessary to prevent the field from being removed by proguard when
23+
* app is compiled, even if its kept during library compilation.
24+
*
25+
* **See Also:**
26+
* - https://docs.oracle.com/javase/8/docs/platform/serialization/spec/version.html#a6678
27+
* - https://docs.oracle.com/javase/8/docs/platform/serialization/spec/class.html#a4100
28+
*/
29+
@Keep
30+
private static final long serialVersionUID = 1L;
31+
32+
33+
1334
/** The user action that was being processed for which the report was generated. */
1435
public final String userAction;
1536
/** The internal app component that sent the report. */

termux-shared/src/main/java/com/termux/shared/models/TextIOInfo.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import android.graphics.Color;
44
import android.graphics.Typeface;
55

6+
import androidx.annotation.Keep;
67
import androidx.annotation.NonNull;
78

89
import com.termux.shared.activities.TextIOActivity;
@@ -19,6 +20,25 @@
1920
*/
2021
public class TextIOInfo implements Serializable {
2122

23+
/**
24+
* Explicitly define `serialVersionUID` to prevent exceptions on deserialization.
25+
*
26+
* Like when calling `Bundle.getSerializable()` on Android.
27+
* `android.os.BadParcelableException: Parcelable encountered IOException reading a Serializable object` (name = <class_name>)
28+
* `java.io.InvalidClassException: <class_name>; local class incompatible`
29+
*
30+
* The `@Keep` annotation is necessary to prevent the field from being removed by proguard when
31+
* app is compiled, even if its kept during library compilation.
32+
*
33+
* **See Also:**
34+
* - https://docs.oracle.com/javase/8/docs/platform/serialization/spec/version.html#a6678
35+
* - https://docs.oracle.com/javase/8/docs/platform/serialization/spec/class.html#a4100
36+
*/
37+
@Keep
38+
private static final long serialVersionUID = 1L;
39+
40+
41+
2242
public static final int GENERAL_DATA_SIZE_LIMIT_IN_BYTES = 1000;
2343
public static final int LABEL_SIZE_LIMIT_IN_BYTES = 4000;
2444
public static final int TEXT_SIZE_LIMIT_IN_BYTES = 100000 - GENERAL_DATA_SIZE_LIMIT_IN_BYTES - LABEL_SIZE_LIMIT_IN_BYTES; // < 100KB

0 commit comments

Comments
 (0)