从 Flutter 调用 Java 代码抛出未处理的异常:MissingPluginException(未找到方法的实现...)
Calling Java code from Flutter throws Unhandled Exception: MissingPluginException(No implementation found for method...)
我正在开发一个必须调用 java 函数的 flutter 项目。所以,我这样定义 MainActivity.java:
package com.manager.nlp;
import android.os.Bundle;
import android.content.Intent;
import android.os.PowerManager;
import android.os.Build.VERSION;
import androidx.annotation.NonNull;
import android.content.IntentFilter;
import android.content.ContextWrapper;
import android.os.Build.VERSION_CODES;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "analisisSintactico";
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler((call, result) -> {
if (call.method.equals("method")) {
result.success("value1");
} else {
result.success("value2");
}
});
}
}
我从 dart 的主文件中调用它:
(我会跳过不重要的部分,比如其他小部件之类的)
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:flutter/services.dart';
class PaginaHome extends StatefulWidget {
const PaginaHome({Key key}) : super(key: key);
@override
_PaginaHomeState createState() => _PaginaHomeState();
}
class _PaginaHomeState extends State<PaginaHome> {
static const cajaNegra = const MethodChannel('analisisSintactico');
@override
Widget build(BuildContext context) {
return Scaffold(
body: new Column(children: <Widget>[
IconButton(
onPressed: () {
invocarAJava();
}
...
)
...
)
}
Future<void> invocarAJava() async {
String valor = await cajaNegra.invokeMethod('method');
print(valor);
}
}
然后,当单击该图标按钮时,出现此错误:
E/flutter ( 9060): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)]
Unhandled Exception: MissingPluginException(No implementation found
for method method on channel analisisSintactico) E/flutter ( 9060): #0
MethodChannel._invokeMethod
(package:flutter/src/services/platform_channel.dart:156:7) E/flutter (
9060): E/flutter ( 9060): #1
_PaginaHomeState.invocarAJava (package:holamundo/main.dart:146:20) E/flutter ( 9060):
如果我 运行 "flutter doctor -v" 它说一切都是正确的
我还尝试执行 flutter clean 然后 flutter 运行,从调试 android 模拟器中删除了 de apk。它仍然显示相同的错误。
我知道正在评估文件,因为如果我写了一些愚蠢的东西,它会检测到错误。但是,不知何故,它无法识别它正在调用的方法。还尝试为通道和方法使用其他名称。
最后,这是我的 build.gradle:
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
apply plugin: 'com.google.gms.google-services'
android {
compileSdkVersion 30
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
main.java.srcDirs += 'src/main/java'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.holamundo"
minSdkVersion 21
targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
如果有人知道是什么问题导致我无法调用我的 java 代码,我很乐意接受任何建议。谢谢。
1-我正在写 kotlin 方面,但我认为问题是一样的。将您的方法作为插件方法移动到另一个 java 文件,如下所示:
class AnalisisSintacticoPlugin(
private val registrar: Registrar
) : MethodCallHandler,
PluginRegistry.ActivityResultListener {
private lateinit var _result: MethodChannel.Result
private lateinit var channel: MethodChannel
companion object {
@JvmStatic
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(),"analisisSintactico")
val plugin = FlutterScreenRecordingPlugin(registrar)
channel.setMethodCallHandler(plugin)
registrar.addActivityResultListener(plugin)
}
}
override fun onMethodCall(call: MethodCall, result: Result) {
if (call.method == "method") {
result.success("value1")
} else {
result.success("value2")
}
}
}
2- 在您的 MainActivity 中注册它:
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
val shimPluginRegistry = ShimPluginRegistry(flutterEngine)
com.manager.nlp.AnalisisSintacticoPlugin.registerWith(shimPluginRegistry.registrarFor("com.manager.nlp.AnalisisSintacticoPlugin"))
GeneratedPluginRegistrant.registerWith(flutterEngine)
}
}
编辑 1: 对于 java 方:
1- 在与 MainActivity 相同的文件夹中创建一个名为 AnalisisSintacticoPlugin 的文件。然后传递这个代码:
package com.manager.nlp;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
public class AnalisisSintacticoPlugin implements FlutterPlugin, MethodCallHandler {
private MethodChannel channel;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "analisisSintactico");
channel.setMethodCallHandler(this);
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (call.method.equals("method")) {
result.success("value1");
} else {
result.success("value2");
}
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
}
}
2- 在 MainActivity 中添加您的插件:
package com.manager.nlp;
import androidx.annotation.NonNull;
import org.jetbrains.annotations.NotNull;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
@Override
public void configureFlutterEngine(@NonNull @NotNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
flutterEngine.getPlugins().add(new com.manager.nlp.AnalisisSintacticoPlugin());
}
}
3- 如果不是,请将 AndroidManifest.xml 中的 activity 名称更改为“.MainActivity”
<activity
android:name=".MainActivity"
4- 确保 AndroidManifest.xml 中的元数据与此完全相同:
<meta-data
android:name="flutterEmbedding"
android:value="2" />
我正在开发一个必须调用 java 函数的 flutter 项目。所以,我这样定义 MainActivity.java:
package com.manager.nlp;
import android.os.Bundle;
import android.content.Intent;
import android.os.PowerManager;
import android.os.Build.VERSION;
import androidx.annotation.NonNull;
import android.content.IntentFilter;
import android.content.ContextWrapper;
import android.os.Build.VERSION_CODES;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "analisisSintactico";
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler((call, result) -> {
if (call.method.equals("method")) {
result.success("value1");
} else {
result.success("value2");
}
});
}
}
我从 dart 的主文件中调用它:
(我会跳过不重要的部分,比如其他小部件之类的)
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:flutter/services.dart';
class PaginaHome extends StatefulWidget {
const PaginaHome({Key key}) : super(key: key);
@override
_PaginaHomeState createState() => _PaginaHomeState();
}
class _PaginaHomeState extends State<PaginaHome> {
static const cajaNegra = const MethodChannel('analisisSintactico');
@override
Widget build(BuildContext context) {
return Scaffold(
body: new Column(children: <Widget>[
IconButton(
onPressed: () {
invocarAJava();
}
...
)
...
)
}
Future<void> invocarAJava() async {
String valor = await cajaNegra.invokeMethod('method');
print(valor);
}
}
然后,当单击该图标按钮时,出现此错误:
E/flutter ( 9060): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: MissingPluginException(No implementation found for method method on channel analisisSintactico) E/flutter ( 9060): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:156:7) E/flutter ( 9060): E/flutter ( 9060): #1
_PaginaHomeState.invocarAJava (package:holamundo/main.dart:146:20) E/flutter ( 9060):
如果我 运行 "flutter doctor -v" 它说一切都是正确的
我还尝试执行 flutter clean 然后 flutter 运行,从调试 android 模拟器中删除了 de apk。它仍然显示相同的错误。
我知道正在评估文件,因为如果我写了一些愚蠢的东西,它会检测到错误。但是,不知何故,它无法识别它正在调用的方法。还尝试为通道和方法使用其他名称。
最后,这是我的 build.gradle:
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
apply plugin: 'com.google.gms.google-services'
android {
compileSdkVersion 30
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
main.java.srcDirs += 'src/main/java'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.holamundo"
minSdkVersion 21
targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
如果有人知道是什么问题导致我无法调用我的 java 代码,我很乐意接受任何建议。谢谢。
1-我正在写 kotlin 方面,但我认为问题是一样的。将您的方法作为插件方法移动到另一个 java 文件,如下所示:
class AnalisisSintacticoPlugin(
private val registrar: Registrar
) : MethodCallHandler,
PluginRegistry.ActivityResultListener {
private lateinit var _result: MethodChannel.Result
private lateinit var channel: MethodChannel
companion object {
@JvmStatic
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(),"analisisSintactico")
val plugin = FlutterScreenRecordingPlugin(registrar)
channel.setMethodCallHandler(plugin)
registrar.addActivityResultListener(plugin)
}
}
override fun onMethodCall(call: MethodCall, result: Result) {
if (call.method == "method") {
result.success("value1")
} else {
result.success("value2")
}
}
}
2- 在您的 MainActivity 中注册它:
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
val shimPluginRegistry = ShimPluginRegistry(flutterEngine)
com.manager.nlp.AnalisisSintacticoPlugin.registerWith(shimPluginRegistry.registrarFor("com.manager.nlp.AnalisisSintacticoPlugin"))
GeneratedPluginRegistrant.registerWith(flutterEngine)
}
}
编辑 1: 对于 java 方:
1- 在与 MainActivity 相同的文件夹中创建一个名为 AnalisisSintacticoPlugin 的文件。然后传递这个代码:
package com.manager.nlp;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
public class AnalisisSintacticoPlugin implements FlutterPlugin, MethodCallHandler {
private MethodChannel channel;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "analisisSintactico");
channel.setMethodCallHandler(this);
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (call.method.equals("method")) {
result.success("value1");
} else {
result.success("value2");
}
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
}
}
2- 在 MainActivity 中添加您的插件:
package com.manager.nlp;
import androidx.annotation.NonNull;
import org.jetbrains.annotations.NotNull;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
@Override
public void configureFlutterEngine(@NonNull @NotNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
flutterEngine.getPlugins().add(new com.manager.nlp.AnalisisSintacticoPlugin());
}
}
3- 如果不是,请将 AndroidManifest.xml 中的 activity 名称更改为“.MainActivity”
<activity
android:name=".MainActivity"
4- 确保 AndroidManifest.xml 中的元数据与此完全相同:
<meta-data
android:name="flutterEmbedding"
android:value="2" />