Android模拟器6.0版本进入系统时,桌面应用com.android.launcher3会发生随机Crash。
W/System.err( 1611): java.lang.IllegalArgumentException: Wrong state class, expecting View State but received class android.appwidget.AppWidgetHostView$ParcelableSparseArray instead. This usually happens when two views of different type have the same id in the same hierarchy. This view’s id is id/0x3. Make sure other views do not use the same id. W/System.err( 1611): at android.view.View.onRestoreInstanceState(View.java:13772) W/System.err( 1611): at android.widget.TextView.onRestoreInstanceState(TextView.java:3784) W/System.err( 1611): at android.view.View.dispatchRestoreInstanceState(View.java:13748) W/System.err( 1611): at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2894) W/System.err( 1611): at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2894) W/System.err( 1611): at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2894) W/System.err( 1611): at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2894) W/System.err( 1611): at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2894) W/System.err( 1611): at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2894) W/System.err( 1611): at android.view.View.restoreHierarchyState(View.java:13726) W/System.err( 1611): at com.android.internal.policy.impl.PhoneWindow.restoreHierarchyState(PhoneWindow.java:2009) W/System.err( 1611): at android.app.Activity.onRestoreInstanceState(Activity.java:1074) W/System.err( 1611): at com.android.launcher3.Launcher.onRestoreInstanceState(Launcher.java:2013)
在网上找到如下解决方法:
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java:
public void onRestoreInstanceState(Bundle state) {
// Wrap the code block will throw runtinme exception in try / catch block
// ----------------------------------------------------------------------
//super.onRestoreInstanceState(state);
//for (int page: mSynchronouslyBoundPages) {
// mWorkspace.restoreInstanceStateForChild(page);
//}
try {
super.onRestoreInstanceState(state);
for (int page: mSynchronouslyBoundPages) {
mWorkspace.restoreInstanceStateForChild(page);
}
} catch (Exception e) {
Log.e(TAG, "Exception in onRestoreInstanceState():");
e.printStackTrace();
}
}
编译后替换掉镜像中的文件:
/system/priv-app/Launcher3/Launcher3.apk /system/priv-app/Launcher3/oat/x86/Launcher3.odex
重启后报了另外一个错误:
java.lang.RuntimeException: Unable to get provider com.android.launcher3.LauncherProvider: java.lang.ClassNotFoundException: Didn’t find class “com.android.launcher3.LauncherProvider” on path: DexPathList[[zip file “/system/priv-app/Launcher3/Launcher3.apk”],nativeLibraryDirectories=[/system/priv-app/Launcher3/lib/x86, /vendor/lib, /system/lib]] at android.app.ActivityThread.installProvider(ActivityThread.java:5156) at android.app.ActivityThread.installContentProviders(ActivityThread.java:4748) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4688) at android.app.ActivityThread.-wrap1(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: java.lang.ClassNotFoundException: Didn’t find class “com.android.launcher3.LauncherProvider” on path: DexPathList[[zip file “/system/priv-app/Launcher3/Launcher3.apk”],nativeLibraryDirectories=[/system/priv-app/Launcher3/lib/x86, /vendor/lib, /system/lib]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at java.lang.ClassLoader.loadClass(ClassLoader.java:511) at java.lang.ClassLoader.loadClass(ClassLoader.java:469) at android.app.ActivityThread.installProvider(ActivityThread.java:5141) … 10 more Suppressed: java.io.IOException: No original dex files found for dex location /system/priv-app/Launcher3/Launcher3.apk at dalvik.system.DexFile.openDexFileNative(Native Method) at dalvik.system.DexFile.openDexFile(DexFile.java:295) at dalvik.system.DexFile.(DexFile.java:80) at dalvik.system.DexFile.(DexFile.java:59) at dalvik.system.DexPathList.loadDexFile(DexPathList.java:279) at dalvik.system.DexPathList.makePathElements(DexPathList.java:248) at dalvik.system.DexPathList.(DexPathList.java:120) at dalvik.system.BaseDexClassLoader.(BaseDexClassLoader.java:48) at dalvik.system.PathClassLoader.(PathClassLoader.java:65) at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:58) at android.app.LoadedApk.getClassLoader(LoadedApk.java:376) at android.app.LoadedApk.makeApplication(LoadedApk.java:568) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4680) … 8 more
猜测是因为编译时用的art库版本与模拟器中不一致,导致生成的oat文件不匹配。解决方法是把dex文件拷贝到模拟器里,然后使用dex2oat编译下。
编译出来的dex文件(Launcher3.apk中不包含dex文件)路径是:
out/target/common/obj/APPS/Launcher3_intermediates/classes.dex
使用如下命令可以在/data/local/tmp目录下生成Launcher3.odex文件,/data/local/tmp/Launcher3.dex是要输入的dex文件路径。
5.0中执行的命令
> dex2oat --runtime-arg -Xms64m --runtime-arg -Xmx512m --dex-file=/data/local/tmp/Launcher3.dex --dex-location=/system/priv-app/Launcher3/Launcher3.apk --oat-file=/data/local/tmp/Launcher3.odex --android-root=/system --instruction-set=x86 --instruction-set-features=default --include-patch-information --runtime-arg -Xnorelocate --no-include-debug-symbols
6.0中执行的命令
> dex2oat --runtime-arg -Xms64m --runtime-arg -Xmx512m --dex-file=/data/local/tmp/Launcher3.dex --dex-location=/system/priv-app/Launcher3/Launcher3.apk --oat-file=/data/local/tmp/Launcher3.odex --android-root=/system --instruction-set=x86 --instruction-set-variant=x86 --instruction-set-features=default --include-patch-information --runtime-arg -Xnorelocate --no-generate-debug-info --abort-on-hard-verifier-error
另外一种解决方法是: 修改
build/target/board/generic_x86/BoardConfig.mk
文件,注释掉:
WITH_DEXPREOPT ?= true
这样,编译后的apk中就会包含dex文件,在模拟器第一次开机时会自动进行dexopt操作。