首页 > 解决方案 > 避免使用 Glide 和 Proguard 缩小的虚拟方法 registerAnimationCallback

问题描述

我们有一个自定义库(com.example.mylib)被我们的应用程序(com.example.myapp)作为外部依赖项包含在内。我们的库反过来使用Glide GIF 处理库。此外,我们的库被 Proguard 缩小了。

在运行时,我们的应用程序因以下 logcat 崩溃:

2019-04-23 15:47:46.642 11066-11066/com.example.myapp E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.myapp, PID: 11066
    java.lang.NoSuchMethodError: No virtual method registerAnimationCallback(Landroid/support/graphics/drawable/Animatable2Compat$AnimationCallback;)V in class Lcom/bumptech/glide/load/resource/gif/GifDrawable; or its super classes (declaration of 'com.bumptech.glide.load.resource.gif.GifDrawable' appears in /data/app/com.example.myapp-C3jnO5_79zyarj8XR40khQ==/split_lib_dependencies_apk.apk)
        at com.example.mylib.MyComponent$1.onResourceReady(SourceFile:4)
        at com.example.mylib.MyComponent$1.onResourceReady(SourceFile:1)
        at com.bumptech.glide.request.SingleRequest.onResourceReady(SingleRequest.java:574)
        at com.bumptech.glide.request.SingleRequest.onResourceReady(SingleRequest.java:549)
        at com.bumptech.glide.load.engine.EngineJob.handleResultOnMainThread(EngineJob.java:218)
        at com.bumptech.glide.load.engine.EngineJob$MainThreadCallback.handleMessage(EngineJob.java:324)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

我无法弄清楚为什么GifDrawable.registerAnimationCallback(...)方法被混淆了。

我认为我们遵循了所有建议的 proguard/Glide 规则:

我可以在目录下看到自动生成的 Glide 文件build\。另外,检查下生成的 JAR 文件packaged-classes\,我看不到任何可疑的东西:只有我们的自定义公共组件保持清晰,其他自定义私有/匿名/等。组件被缩小。

即使在构建我们的库时它应该没有多大意义,我也保留了以下内容,但没有运气:

# our custom, anonymous RequestListeners
-keep class * implements com.bumptech.glide.request.RequestListener {
    public *;
}

# GifDrawable itself by Glide
-keep class com.bumptech.glide.load.resource.gif.GifDrawable {
    public *;
}

对于那些不习惯 Glide 或想知道什么是有趣的代码的人,这里是:

Glide.with(myContext)
    .asGif()
    .load(myResourceId)
    .listener(new RequestListener<GifDrawable>() {

        @Override
        public boolean onResourceReady(GifDrawable resource,
                                       Object model,
                                       Target<GifDrawable> target,
                                       DataSource dataSource,
                                       boolean isFirstResource) {
            myReadyGif = resource;
            resource.setLoopCount(1);
            resource.registerAnimationCallback(
                new Animatable2Compat.AnimationCallback() {
                    @Override
                    public void onAnimationEnd(Drawable drawable) {
                        super.onAnimationEnd(drawable);
                        // do something
                    }
                });
            return false;
        }

        //...
    })
    .into(myViewTarget);

作为registerAnimationCallbackGlide 库的一个相对较新的补充,我想知道这个问题是否与库本身有关。尚不确定这意味着什么,但前面的setLoopCount(...)方法调用不会导致任何问题。

标签: androidproguardandroid-glideandroid-proguard

解决方案


好的,当我们从应用程序中提取代码和配置以创建专用库模块时,这是我们对一个细节的完全复制/粘贴错误:

而 app build.gradle 包含 Glide 依赖项:

implementation 'com.github.bumptech.glide:glide:4.9.0'

当它被移植到图书馆时,它应该变成:

api 'com.github.bumptech.glide:glide:4.9.0'

反证是,在复制/粘贴错误仍然存​​在的情况下,将依赖项也重新添加到应用程序就足够了,运行时错误就消失了。


推荐阅读