java - Flutter build release APK 报 NoSuchMethodException 错误
问题描述
升级 Flutter SDK 时遇到问题。我以前用的是1.9.x(下面没有问题)。现在我升级到v1.12.13 + hotfix.9或者1.17.0来重现这个问题(我只试过这两个版本),问题如下:
现在我使用v1.17.0 SDK创建插件,然后在插件中使用反射调用方法。代码如下:
@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 类如下:
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的部分代码如下
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
也有出现上述问题的情况。当一个插件中使用了另一个库,并且对这个库进行了混淆,这个时候如果调用这个混淆库中的方法就会出现上述错误。
颤振医生:
不知道为什么在使用flutter命令打包release APK的时候会出现这个问题,谢谢。
github仓库:https://github.com/liusilong/flutter_plugin_17
我使用以下三种方式打包apk,然后在android studio中打开这些apk进行对比:
- flutter 版本为1.17,用 Android studio 打包(Build -> Generate Signed Bundle or APK),dex文件解析如下:
- flutter 版本为1.17,打包了 Flutter 命令(flutter build apk --release),dex文件解析如下:
- Flutter版本为1.9.1+hotfix.6,打包了 Flutter 命令(flutter build apk --release),dex文件解析如下:
解决方案
我知道问题是什么。我使用的是 Android Studio3.6,文档说当您使用 Android Studio 3.4 或 Android Gradle 插件 3.4.0 及更高版本时,R8 是默认编译器
解决方法有两种:</p>
将proguard-rules.pro文件添加到
project/app/proguard-rules.pro
第一个解决方案(不使用 R8):
- 在
project/gradle.properties
文件中,将此属性设置android.enableR8
为false
,如下:</li>
org.gradle.jvmargs=-Xmx1536M
android.enableR8=false
android.useAndroidX=true
android.enableJetifier=true
- 在
project/app/proguard-rules.pro
文件中,自定义要保留的代码:
-keep class com.lsl.flutterplugin17.* {*;}
- 在
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>
第二种解决方案(使用 R8):
1.在project/app/proguard-rules.pro文件中,添加如下代码:
-dontobfuscate
-dontshrink
- 在
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>
推荐阅读
- vim - Neovim 中的 COC 弹出样式
- javascript - 更新购物车和结帐中的滚动(Woocommerce + Locomotive Scroll)
- node.js - nodeJS 请求库:使用代理键而不是 URL 发出 POST 请求
- python - Python套接字 - 我如何连接到另一台电脑
- javascript - 当输入到不同的文本框中时,程序会以不同的方式处理相同的字符串
- import - Angular 8 - 自定义发布的模块在导入更高的角度版本时出错
- node.js - 如何访问部署在heroku上的mern应用程序中的环境值以进行反应?
- swift - 合并不同大小的视频和图像
- postgresql - 使用 quarkus 反应式 pg 客户端时如何设置获取大小
- random - 有没有一种方法可以根据 Secured Random 结果对 Web 服务器编程语言进行逆向工程?