Flutter 引用AAR包導(dǎo)致的NoSuchMethodError: No static method create()Lvideo/pano/EglBase

背景

Flutter-Android混合開(kāi)發(fā),遠(yuǎn)程引用了jcenter上的第三方aar包。這個(gè)第三方aar包內(nèi)部又依賴了jar包,jar包里有個(gè)接口類EglBase,里面有個(gè)靜態(tài)方法create:

public interface EglBase {
    static EglBase create(@Nullable EglBase.Context sharedContext, int[] configAttributes) {
        return (EglBase)(!EglBase14.isEGL14Supported() || sharedContext != null && !(sharedContext instanceof video.pano.EglBase14.Context) ? new EglBase10((video.pano.EglBase10.Context)sharedContext, configAttributes) : new EglBase14((video.pano.EglBase14.Context)sharedContext, configAttributes));
    }
}

運(yùn)行的時(shí)候,提示:

W/System.err( 6150): Caused by: java.lang.NoSuchMethodError: No static method create()Lvideo/pano/EglBase; in class Lvideo/pano/EglBase; or its super classes (declaration of 'video.pano.EglBase' appears in /data/app/xxx-c7mnoReovPKpIyPmc2_R4g==/base.apk)

另外:
1.在純android工程里,使用遠(yuǎn)程依賴該第三方aar/本地依賴都運(yùn)行正常;
2.將該aar包從jcenter上下載后,放在flutter-android工程的libs目錄下,gradle本地依賴使用,運(yùn)行正常。

分析

對(duì)比運(yùn)行正常(本地依賴aar)和運(yùn)行崩潰(jcenter遠(yuǎn)程依賴)的apk解壓后的EglBase.class文件:

運(yùn)行正常.png

運(yùn)行crash.png

可以發(fā)現(xiàn),運(yùn)行異常的EglBase.class文件里多了報(bào)錯(cuò)的靜態(tài)方法(為什么反而是多了這兩個(gè)靜態(tài)方法?沒(méi)搞明白)。
說(shuō)明Flutter-Android工程在遠(yuǎn)程依賴第三方庫(kù)和本地直接依賴第三方庫(kù)兩種情況下打包apk的方式是有區(qū)別的。
在一篇文章里 https://github.com/xamarin/xamarin-android/issues/4574 ,有提到類似錯(cuò)誤的原因:
The problem is caused by "desugaring", which "moves things around." In particular, if you run dexdump classes.dex on the classes.dex contained within the .apk, the only create method with a "type" of ()Lorg/webrtc/EglBase; is declared in Lorg/webrtc/EglBase$-CC;:

$ $HOME/android-toolchain/sdk/build-tools/29.0.2/dexdump classes.dex
…
Class #1481            -
  Class descriptor  : 'Lorg/webrtc/EglBase$-CC;'
  Access flags      : 0x1011 (PUBLIC FINAL SYNTHETIC)
  Superclass        : 'Ljava/lang/Object;'
  Interfaces        -
  Static fields     -
  Instance fields   -
  Direct methods    -
    …
    #1              : (in Lorg/webrtc/EglBase$-CC;)
      name          : 'create'
      type          : '()Lorg/webrtc/EglBase;'
      access        : 0x0009 (PUBLIC STATIC)
      code          -
      registers     : 2
      ins           : 0
      outs          : 2
      insns size    : 8 16-bit code units
      catches       : (none)
      positions     : 
        0x0000 line=170
      locals        : 

EglBase$-CC is not a class present within the original classes.jar. Equally important, our code is looking for the create method on org/webrtc/EglBase, not org/webrtc/EglBase$-CC;, and while org/webrtc/EglBase exists in classes.dex, it does not contain the static create method.

This is why the Java.Lang.NoSuchMethodError is thrown.

Disabling desugar allow the app to run, but requires -- as you note in step (2) -- that the Minimum Android version to API Level be 24 or higher. 26 in this case, actually, to avoid a different build error:

D8 : error : Invoke-customs are only supported starting with Android O (--min-api 26)


I'm not entirely sure how to address this on our end. We could skip binding static interface methods/etc. unless building against Mono.Android.dll v7.0, which would avoid the NoSuchMethodException… by removing the method entirely. (This isn't a "fix.") I'm also not sure it would actually work, because all Mono.Android.dlls have an assembly version of 0.0.0.0, so we'd have to "somehow" ensure that the v7.0 bit makes it into the NuGet package? (I don't understand how that process works.)

The only other fix I can think of is to IL-rewrite the binding assembly to replace appropriate instances of Lorg/webrtc/EglBase; with Lorg/webrtc/EglBase$-CC;, which could be done but could be "brittle".

這里就不再翻譯了,大意是desuagaring 脫糖處理會(huì)把原本在EglBase里的靜態(tài)方法挪到EglBase$-CC這個(gè)class文件,導(dǎo)致在EglBase里找不到原本屬于他的方法。不過(guò)這貌似也解釋不通?這塊知識(shí)比較匱乏,目前我也只能探索到這一步了。

解決方案

在 gradle.properties 中添加

android.enableDexingArtifactTransform.desugaring=false

這個(gè)解決方案,我前前后后斷斷續(xù)續(xù)找了兩星期,百度google無(wú)果,最后是在Bing上搜索到的。
造成上述bug的原因,應(yīng)該是跟Android Studio 3.0+ 新Dex編譯器D8 Desugar R8有關(guān),后續(xù)有機(jī)會(huì)繼續(xù)研究。
https://blog.csdn.net/jamin0107/article/details/81123154

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 新一代編譯 toolchain Jack & Jill 簡(jiǎn)介 2016 年 3 月 10 日, G...
    heiheiwanne閱讀 1,291評(píng)論 0 3
  • 目前Android studio 2.4預(yù)覽版不再需要使用jack 工具鏈了 這件事要從一次報(bào)錯(cuò)開(kāi)始 如果僅僅是想...
    CalvinNing閱讀 844評(píng)論 0 1
  • 原文發(fā)表于http://taobaofed.org/blog/2016/05/05/new-compiler-fo...
    leonliu2閱讀 1,110評(píng)論 1 1
  • 一、瘦身優(yōu)化及 Apk 分析方案介紹 1.1 瘦身優(yōu)勢(shì) 我們首先來(lái)介紹下,為什么我們需要做 APK 的瘦身優(yōu)化? ...
    凱玲之戀閱讀 966評(píng)論 0 0
  • 推薦指數(shù): 6.0 書(shū)籍主旨關(guān)鍵詞:特權(quán)、焦點(diǎn)、注意力、語(yǔ)言聯(lián)想、情景聯(lián)想 觀點(diǎn): 1.統(tǒng)計(jì)學(xué)現(xiàn)在叫數(shù)據(jù)分析,社會(huì)...
    Jenaral閱讀 5,967評(píng)論 0 5

友情鏈接更多精彩內(nèi)容