从 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" />