友盟反馈中发现的这样的问题,对下文没有考证,最终对2.3版本通过绕过Parserable 和 serializable方式解决的,留此只做备忘

来源:互联网 发布:日本tpp知乎 编辑:程序博客网 时间:2024/06/06 01:04
OVERVIEWSending a private serializable subclass as an Intent extra can crash many receivers.STEPS TO REPRODUCE1. Send a private serializable subclass as an Intent extra to a receiver that inspects the extras.  For example, try the following sample code:public class TestActivity extends Activity{/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS).putExtra("serializable", new CustomSerializable()));}private static final class CustomSerializable implements Serializable{private static final long serialVersionUID = 1L;}}RESULTSActual behavior: The receiver crashes as soon as it attempts to look at the Intent's extras with a RuntimeException.  This is the trace generated on the Honeycomb emulatorE/AndroidRuntime(  464): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.settings/com.android.settings.Settings$WifiSettingsActivity}: java.lang.RuntimeException: Parcelable encounteredClassNotFoundException reading a Serializable object (name = com.test.TestActivity$CustomSerializable)E/AndroidRuntime(  464): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1736)E/AndroidRuntime(  464): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1752)E/AndroidRuntime(  464): at android.app.ActivityThread.access$1500(ActivityThread.java:123)E/AndroidRuntime(  464): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:993)E/AndroidRuntime(  464): at android.os.Handler.dispatchMessage(Handler.java:99)E/AndroidRuntime(  464): at android.os.Looper.loop(Looper.java:126)E/AndroidRuntime(  464): at android.app.ActivityThread.main(ActivityThread.java:3997)E/AndroidRuntime(  464): at java.lang.reflect.Method.invokeNative(Native Method)E/AndroidRuntime(  464): at java.lang.reflect.Method.invoke(Method.java:491)E/AndroidRuntime(  464): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)E/AndroidRuntime(  464): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)E/AndroidRuntime(  464): at dalvik.system.NativeStart.main(Native Method)E/AndroidRuntime(  464): Caused by: java.lang.RuntimeException: Parcelable encounteredClassNotFoundException reading a Serializable object (name = com.fragment.test.FragmentTestActivity$CustomSerializable)E/AndroidRuntime(  464): at android.os.Parcel.readSerializable(Parcel.java:2026)E/AndroidRuntime(  464): at android.os.Parcel.readValue(Parcel.java:1897)E/AndroidRuntime(  464): at android.os.Parcel.readMapInternal(Parcel.java:2083)E/AndroidRuntime(  464): at android.os.Bundle.unparcel(Bundle.java:215)E/AndroidRuntime(  464): at android.os.Bundle.getBoolean(Bundle.java:787)E/AndroidRuntime(  464): at android.content.Intent.getBooleanExtra(Intent.java:3444)E/AndroidRuntime(  464): at android.preference.PreferenceActivity.onIsHidingHeaders(PreferenceActivity.java:665)E/AndroidRuntime(  464): at android.preference.PreferenceActivity.onCreate(PreferenceActivity.java:495)E/AndroidRuntime(  464): at com.android.settings.Settings.onCreate(Settings.java:66)E/AndroidRuntime(  464): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1048)E/AndroidRuntime(  464): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1700)E/AndroidRuntime(  464): ... 11 moreE/AndroidRuntime(  464): Caused by: java.lang.ClassNotFoundException: com.fragment.test.FragmentTestActivity$CustomSerializableE/AndroidRuntime(  464): at java.lang.Class.classForName(Native Method)E/AndroidRuntime(  464): at java.lang.Class.forName(Class.java:234)E/AndroidRuntime(  464): at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:2392)E/AndroidRuntime(  464): at java.io.ObjectInputStream.readNewClassDesc(ObjectInputStream.java:1742)E/AndroidRuntime(  464): at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:755)E/AndroidRuntime(  464): at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:1888)E/AndroidRuntime(  464): at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:859)E/AndroidRuntime(  464): at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2090)E/AndroidRuntime(  464): at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2045)E/AndroidRuntime(  464): at android.os.Parcel.readSerializable(Parcel.java:2020)E/AndroidRuntime(  464): ... 21 moreE/AndroidRuntime(  464): Caused by: java.lang.NoClassDefFoundError: com.fragment.test.FragmentTestActivity$CustomSerializableE/AndroidRuntime(  464): ... 31 moreE/AndroidRuntime(  464): Caused by: java.lang.ClassNotFoundException: com.fragment.test.FragmentTestActivity$CustomSerializable in loader dalvik.system.PathClassLoader[/system/app/Settings.apk]E/AndroidRuntime(  464): at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:251)E/AndroidRuntime(  464): at java.lang.ClassLoader.loadClass(ClassLoader.java:548)E/AndroidRuntime(  464): at java.lang.ClassLoader.loadClass(ClassLoader.java:508)E/AndroidRuntime(  464): ... 31 moreExpected behavior: The expected behavior requires additional design discussion.  At a minimum, the exception should be a ClassNotFoundException rather than a runtime exception.  This would allow all receivers to more easily catch this issue.  However requiring all receivers to implement such try-catch boilerplate might be non-obvious, and perhaps consideration should be given to other solutions.  For example, the extra could simply be suppressed (and logged as a error) similar to how accessing a extras as the wrong type is currently handled (e.g. store a string, try to retrieve a boolean, gets treated as if the boolean simply doesn't exist).WORKAROUNDWhen reading the extras, the following can be done to prevent the receiver from crashing/* * This is a hack to work around a custom serializable classloader attack. This check must come before any of the Intent * extras are examined. */try{final Bundle extras = intent.getExtras();if (extras != null){// if a custom serializable subclass exists, this will throw an exceptionextras.containsKey(null);}}catch (final Exception e){Log.e("Test", "Custom serializable attack detected; do not send private Serializable subclasses to this receiver", e); //$NON-NLS-1$return;}NOTESThis issue reproduces on Droid, Nexus One, Nexus S, etc. running Android 2.2, 2.3.3, and 2.3.2 respectively.  It also reproduces on the Honeycomb emulator.
0 0