java - Flutter构建发布APK报NoSuchMethodException错误

标签 java android flutter

我在升级Flutter SDK的时候遇到了问题。我以前用的是1.9.x(下面没有问题)。现在我升级到v1.12.13 + hotfix.91.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类如下:

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

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

Build -> Generate Signed Bundle or APK

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

Packaging commands : flutter build apk --release

error.png

还有一种情况会出现上面的问题。当一个插件中使用了另一个库,这个库被混淆了,此时如果调用这个混淆库中的方法,就会出现上面的错误。

flutter 医生:

doctor.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文件解析如下:

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

最佳答案

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

有两种解决方法:

add proguard-rules.pro file to project/app/proguard-rules.pro

第一种方案(不使用R8):

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

关于java - Flutter构建发布APK报NoSuchMethodException错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61699344/

相关文章:

java - Sonatype Nexus : How to use my Seagate personal cloud storage device as a repository for my maven artifacts?

android - 我可以将 debug.keystore 从一台电脑复制到另一台电脑吗?

android - 从普通 Activity 启动 FragmentActivity.. java.lang.NoClassDefFoundError

android - ClassyShark 仅显示方法签名

flutter - 如何完全删除 Dart ubuntu?

scroll - 在 flutter 中如何只滚动屏幕的下半部分

java - 使用 AppEngine 访问 CouchDB 等 NoSQL 数据库

java - jaxb:将属性绑定(bind)到元素

java - 如何配置 Gradle 以绕过 SSL 证书验证?

flutter/dart 如何检查firestore中是否存在文档?