Evil Mouth's Blog

MlKitException Failed to load deprecated vision dynamite module

April 17, 2023

记一次 mlkit 错误分析

前景

项目接入mlkit-barcode功能,考虑到国产大部分手机不支持google play services,遂使用模型捆绑包的依赖方式接入sdk

implementation 'com.google.mlkit:barcode-scanning:17.1.0'

该引入方式会将barcode的识别模型一起打包到apk里,虽然包体积会大一些,但起码所有手机都能用

另一种引入方式需要依赖google play services,会动态下载识别模型

问题

demo工程试接了下,国产手机运行正常,遂接入到项目工程,但运行报错

Invalid GmsCore APK, remote loading disabled.

Error preloading model resource
com.google.mlkit.common.MlKitException: Failed to load deprecated vision dynamite module.

Caused by: com.google.android.gms.dynamite.DynamiteModule$LoadingException: No acceptable module com.google.android.gms.vision.dynamite found. Local version is 0 and remote version is 0.

下载模型失败?我不是用的捆绑包吗?怎么还去下载模型?

分析

再重新看日志,发现没找到模型的版本都是0

Local version is 0 and remote version is 0.

在之前还有一句日志

DynamiteModule           W  Local module descriptor class for com.google.mlkit.dynamite.barcode not found.

找不到本地的模型,进DynamiteModule看看是怎么找的

context = context.getApplicationContext();
ClassLoader context1 = context.getClassLoader();
var2 = new StringBuilder();
var2.append("com.google.android.gms.dynamite.descriptors.");
var2.append(moduleId);
var2.append(".ModuleDescriptor");
Class context2 = context1.loadClass(var2.toString());
var15 = context2.getDeclaredField("MODULE_ID");
context3 = context2.getDeclaredField("MODULE_VERSION");
var3 = Objects.equal(var15.get((Object)null), moduleId);

发现DynamiteModule会用反射去取ModuleDescriptor下的MODULE_IDMODULE_VERSION两个常量值来获取模型版本

@DynamiteApi
@RetainForClient
public class ModuleDescriptor {
    @RetainForClient
    @NonNull
    public static final String MODULE_ID = "com.google.android.gms.measurement.dynamite";
    @RetainForClient
    public static final int MODULE_VERSION = 70;

    public ModuleDescriptor() {
    }
}

找不到说明反射失败了,说明这个类没打包进apk或其它问题,反编译下apk发现两个常量没了,难怪找不到

原因

这么一想,项目接了个常量内联的插件,插件没检测出来误伤把这两个常量干掉了,导致加载本地模型失败

— Evil Mouth