PersistableBundle引发的血案

来源:互联网 发布:挪威的森林知乎评论 编辑:程序博客网 时间:2024/04/30 14:26

旁白

木丁所在公司的App上线了,突然收到在Android5.0以下的手机 上报了crash。木丁下意识到,应该是的没有去做5.0以下的兼容。看到上报日志,发现怎么是EventBus引起的呢? 先来看下现场

案发现场

Caused by: java.lang.ClassNotFoundException: Didn't find class "android.os.PersistableBundle" on path: DexPathList[[dex file "dalvik.system.DexFile@42a0f260", dex file "dalvik.system.DexFile@42a0eed0", dex file "dalvik.system.DexFile@42a0eb48", dex file "dalvik.system.DexFile@42a0e7c0", zip file "/data/app/com.xxxx.xxxx-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.xxxx.xxxx-1, /vendor/lib, /system/lib]]    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)    at java.lang.ClassLoader.loadClass(ClassLoader.java:497)    at java.lang.ClassLoader.loadClass(ClassLoader.java:457)    at java.lang.Class.getDeclaredMethods(Native Method)    at java.lang.Class.getDeclaredMethods(Class.java:656)    at cn.jpush.im.android.eventbus.SubscriberMethodFinder.findSubscriberMethods(SubscriberMethodFinder.java)    at cn.jpush.im.android.eventbus.EventBus.register(EventBus.java)    at cn.jpush.im.android.eventbus.EventBus.register(EventBus.java)    at cn.jpush.im.android.api.JMessageClient.registerEventReceiver(JMessageClient.java)    at cn.jpush.im.android.api.JMessageClient.registerEventReceiver(JMessageClient.java)    at com.xxxx.xxxx.home.activity.xxxxx.initView(MainActivity.java)    at com.xxxx.xxxx.framework.base.BaseActivity.onCreate(BaseActivity.java)    at com.xxxx.xxxx.home.activity.xxxxx.onCreate(Native Method)    at android.app.Activity.performCreate(Activity.java:5386)    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1096)    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162)

瞅一眼,一看就是EventBus 的锅 ,赶紧找他们,拉横幅,发传单,去他们github楼下闹事!

来到Eventbus github中搜索关键字后,却是有发现, 早有人来这里闹事了。
Android 4.4 register error:NoClassDefFoundError
java.lang.NoClassDefFoundError for android/os/PersistableBundle during registering activity on Bus

第一个是上报问题的,原因以及方法也没有给出多少。
第二个还是很有参考价值的, 跟着木丁一起摸瓜吧!

顺藤摸瓜

java.lang.NoClassDefFoundError for android/os/PersistableBundle during registering activity on Bus
这篇中,有不少的讨论,值得关注的是。

I don't think it has anythink to do with Otto.android.os.PersistableBundle is a class introduced in Lollipop for a new mechanism of "resurecting" apps after i.e. system restart. See [Activity.onCreate(Bundle, PersistableBundle)](http://developer.android.com/reference/android/app/Activity.html#onCreate%28android.os.Bundle, android.os.PersistableBundle%29).I saw this error comming from RoboGuice library when injecting an Activity, but unfortunately I did not find the proper cause yet...

以及其中的,这个回复:

CorentinPacaud commented on 4 Mar 2015The StackOverflow topic : http://stackoverflow.com/questions/28857860/classnotfoundexception-didnt-find-class-android-os-persistablebundle-otto-an[RESOLVED]

真相大白

按照他们提供的的思路,以及解决方法, 原因明了了。
5.0的时候Android针对Activity.java有新的内容,重载了onCreate方法

void onCreate(Bundle savedInstanceState)void onCreate(Bundle savedInstanceState, PersistableBundle persistentState)

void onCreate (Bundle savedInstanceState, PersistableBundle persistentState)
Same as onCreate(android.os.Bundle) but called for those activities created with the attribute persistableMode set to persistAcrossReboots.

对应的 onSaveInstanceState 也有2个方法

void onSaveInstanceState (Bundle outState)void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)

针对这个 PersistableBundle 是什么鬼,我们稍微看下API文档。

PersistableBundle: if the activity is being re-initialized after previously being shut down or powered off then this Bundle contains the data it most recently supplied to outPersistentState in onSaveInstanceState(Bundle). Note: Otherwise it is null.

注意,这里应该有个瑕疵, outPersistentState in onSaveInstanceState(Bundle) 结合上下文,这里的onSaveInstanceState(Bundle) 指的是 onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState), google 里面也有懒得写这么仔细的家伙!

直接原因

Android5.0加入了类 PersistableBundle 用于保存异常状况下Activity中的数据(简单点说), AS开发的时候也是推荐使用, 导致我们的开发人员忽略了 onCreate(Bundle savedInstanceState)
4.4 上根本就没有这个类, 导致出现了ClassNotFound异常。

如何解决

针对这个问题2个解决方法, 你要是不使用persistableMode属性,你自己的Activity只需要重载onCreate(Bundle)方法,这样是传统的写法。 要是你想尝试使用这个属性, 简单,2个重载方法都加入!
后续,尝试写一篇关于persistableMode 分析的文章,使用demo演示讨论这个问题。

防微杜渐

在AS2.3+上开发,稍微不注意,选择Activity.onCreate的时候,需要注意。如果需要兼容5.0以下的系统,需要重载2个onCreate 方法, 对应的使用2个重载的 onSaveInstanceState;

原创粉丝点击