Flutter构建版本APK收到NoSuchMethodException错误

时间:2020-05-09 15:37:42

标签: java android flutter

升级Flutter SDK时遇到问题。我曾经使用 1.9.x (下面没有问题)。现在,我升级到 v1.12.13 + hotfix.9 1.17.0 来重现此问题(我只尝试了这两个版本),问题如下:< / p>

现在,我使用 v1.17.0 SDK创建一个插件,然后在该插件中使用反射调用方法。代码如下:

Flutterplugin17Plugin.java

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    if (call.method.equals("personName")) { // Reflection call method
      person.execute(call.method);
      result.success("success");
    }
  }

Person类如下:

Person.java

public class Person {
    private static final String TAG = "Person";

    // This method will be called by reflection
    public void personName() {
        Log.e(TAG, "personName: call personName method....");
    }

    public void execute(String methodName) {
        try {
            Method method = Person.class.getDeclaredMethod(methodName);
            method.invoke(Person.this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Flutter的部分代码如下

flutterplugin17.dart

static Future<void> callMethod() async{
  await _channel.invokeMethod("personName");
}

// The method is called when the button is clicked
await Flutterplugin17.callMethod();

然后,如果直接运行(单击调试按钮以在Android Studio中运行),则可以,可以正确调用反射方法。

使用Android Studio打包Release APK(发行版)也没问题。

构建->生成签名包或APK

但是,当我使用Flutter命令打包APK(发行版)时,目前无法调用插件中的反射方法。 adb logcat如下:

打包命令:flutter build apk --release

error.png

在某些情况下也会出现上述问题。当在插件中使用另一个库并且对该库进行混淆时,如果调用该混淆库中的方法,这一次将发生上述错误。

颤抖的医生:

doctor.jpg

我不知道为什么在使用flutter命令打包发行版APK时会出现此问题,

github存储库:https://github.com/liusilong/flutter_plugin_17


我使用以下三种方式打包apk,然后在android studio中打开这些apk进行比较:

  1. Flutter版本为 1.17 ,与A​​ndroid Studio打包在一起(构建->生成签名包或APK),dex文件的解析如下:

image.png

  1. flutter版本为 1.17 ,与Flutter命令一起打包(flutter build apk --release),dex文件的解析如下:

image.png

  1. flutter版本为 1.9.1 + hotfix.6 ,与Flutter命令打包在一起(flutter build apk --release),dex文件的解析如下:

image.png

2 个答案:

答案 0 :(得分:0)

我知道问题出在哪里。我使用的是Android Studio3.6,documentation说,使用Android Studio 3.4或Android Gradle插件3.4.0及更高版本时,R8是默认编译器

有两种解决方法:

proguard-rules.pro 文件添加到project/app/proguard-rules.pro

第一个解决方案(不使用R8):

  1. project/gradle.properties文件中,将此属性android.enableR8设置为false,如下所示:
org.gradle.jvmargs=-Xmx1536M
android.enableR8=false
android.useAndroidX=true
android.enableJetifier=true
  1. project/app/proguard-rules.pro文件中,自定义代码以保留:
-keep class com.lsl.flutterplugin17.* {*;}
  1. project/app/build.gradle文件中,添加如下代码:
android {
   ...

    buildTypes {
        release {
            ...
            // add new line
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        }
    }
   ...
}

使用flutter命令flutter build apk --release进行打包,对dex文件的解析如下:

image.png

第二种解决方案(使用R8):

1。在project / app / proguard-rules.pro文件中,添加如下代码:

-dontobfuscate
-dontshrink
  1. project/app/build.gradle文件中,添加如下代码:
android {
   ...

    buildTypes {
        release {
            ...
            // add new line
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        }
    }
   ...
}

使用flutter命令flutter build apk --release进行打包,对dex文件的解析如下:

image.png

答案 1 :(得分:-1)

也许您需要接受android许可证才能构建发行版APK?