首页 > 解决方案 > Flutter build release APK 报 NoSuchMethodException 错误

问题描述

升级 Flutter SDK 时遇到问题。我以前用的是1.9.x(下面没有问题)。现在我升级到v1.12.13 + hotfix.9或者1.17.0来重现这个问题(我只试过这两个版本),问题如下:

现在我使用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 类如下:

人.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中点击调试按钮运行)就OK了,反射方法就可以正确调用了。

使用Android Studio打包Release APK(发布)也是没问题的。

构建 -> 生成签名包或 APK

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

打包命令:flutter build apk --release

错误.png

也有出现上述问题的情况。当一个插件中使用了另一个库,并且对这个库进行了混淆,这个时候如果调用这个混淆库中的方法就会出现上述错误。

颤振医生:

医生.jpg

不知道为什么在使用flutter命令打包release APK的时候会出现这个问题,谢谢。

github仓库:https://github.com/liusilong/flutter_plugin_17


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

  1. flutter 版本为1.17,用 Android studio 打包(Build -> Generate Signed Bundle or APK),dex文件解析如下:

图像.png

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

图像.png

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

图像.png

标签: javaandroidflutter

解决方案


我知道问题是什么。我使用的是 Android Studio3.6,文档当您使用 Android Studio 3.4 或 Android Gradle 插件 3.4.0 及更高版本时,R8 是默认编译器

解决方法有两种:</p>

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

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

  1. project/gradle.properties文件中,将此属性设置android.enableR8false,如下:</li>
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文件解析如下:</p>

图像.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文件解析如下:</p>

图像.png


推荐阅读