解决Android4.4.4报错:requires com.huawei.android.launcher.permission.WRITE_SETTINGS:

引言

项目之前对于机型测试过一次,但是没有对 Android 4.X 版本进行测试,这周有同事在用这款手机,出现的问题是:点击桌面图标提示“XXX已停止运行”。

问题排查

通过下面的 Log 信息

reading com.huawei.android.launcher.LauncherProvider from pid=721,uid=10079 requires com.huawei.android.launcher.permission.WRITE_SETTINGS: uid 10079 does not have com.huawei.android.launcher.permission.WRITE_SETTINGS

发现问题:
没有声明这个权限:

<uses-permission android:name="com.huawei.android.launcher.permission.WRITE_SETTINGS"/>

这里需要注意区分该权限和原生系统的权限

<uses-permission android:name="android.permission.WRITE_SETTINGS" />

此时,编译通过,运行又会报下面这个错:

java.lang.RuntimeException: Unable to get provider com.google.firebase.provider.FirebaseInitProvider: java.lang.ClassNotFoundException: Didn't find class "com.google.firebase.provider.FirebaseInitProvider" on path: DexPathList[[zip file "/data/app/com.xxx-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.xxx-2, /vendor/lib, /system/lib, /data/datalib]]
                                                                     at android.app.ActivityThread.installProvider(ActivityThread.java:5087)
                                                                     at android.app.ActivityThread.installContentProviders(ActivityThread.java:4673)
                                                                     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4613)
                                                                     at android.app.ActivityThread.access$1800(ActivityThread.java:141)
                                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1298)
                                                                     at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                     at android.os.Looper.loop(Looper.java:136)
                                                                     at android.app.ActivityThread.main(ActivityThread.java:5336)
                                                                     at java.lang.reflect.Method.invokeNative(Native Method)
                                                                     at java.lang.reflect.Method.invoke(Method.java:515)
                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:871)
                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)
                                                                     at dalvik.system.NativeStart.main(Native Method)
                                                                  Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.firebase.provider.FirebaseInitProvider" on path: DexPathList[[zip file "/data/app/com.xxx-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.xxx-2, /vendor/lib, /system/lib, /data/datalib]]
                                                                     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 android.app.ActivityThread.installProvider(ActivityThread.java:5072)
                                                                     at android.app.ActivityThread.installContentProviders(ActivityThread.java:4673) 
                                                                     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4613) 
                                                                     at android.app.ActivityThread.access$1800(ActivityThread.java:141) 
                                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1298) 
                                                                     at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                     at android.os.Looper.loop(Looper.java:136) 
                                                                     at android.app.ActivityThread.main(ActivityThread.java:5336) 
                                                                     at java.lang.reflect.Method.invokeNative(Native Method) 
                                                                     at java.lang.reflect.Method.invoke(Method.java:515) 
                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:871) 
                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687) 
                                                                     at dalvik.system.NativeStart.main(Native Method) 

很明显这两次的错误信息不一样,但是这次的是什么原因引起的呢?这有需要进一步排查了。

分析

虽然第一个权限问题找到了解决方案,但却不是根本原因。因为项目已经在 Android5.X,Android6.X,Android7.X,Android 8.0 和 Android8.1 上没有出现这个问题。那么肯定就是有什么东西在 Android5.0 的时候是一个分界线,所以才会导致这个问题出现,因为我在 Android4.4 的模拟器上测试也是同样的问题,所以并不是机型问题。

进一步排查

发现项目中使用了下面这个东西

multiDexEnabled true

这个我们都知道起作用(方法数 64K 限制),下面看重点(原因)

Android 5.0 之前版本的 Dalvik 可执行文件不支持分包

Android 5.0之前的版本使用 Dalvik 来执行应用代码。默认情况下,Dalvik 限制应用的每个 APK 只能使用单个 classes.dex 字节码文件

而Android 5.0 及更高版本的 Dalvik 可执行文件支持分包

Android 5.0及更高版本使用名为 ART 的运行时,后者原生支持从 APK 文件加载多个 DEX 文件。ART 在应用安装时执行预编译,扫描 classesN.dex 文件,并将它们编译成单个 .oat 文件,供 Android 设备执行。

问题所在

因为使用了突破方法数限制功能,所以项目的 Application 中需要做初始化,但是经检查,并未做如下初始化工作,因此结合上面的知识点,才会在 Android4.X 出现此错误。

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(base);
}

总结

  • 开始的权限问题只是表象,根本原因是后面的缺少配置问题
  • 之所以出现这样的情况,是因为 Dalvik 可执行文件是否支持分包有一个版本分界线问题
  • 二次开发别人写过的项目,要使用颠覆性的想象来解决想不到的意外。

你可能感兴趣的:(Android之旅)