FlutterActivity MethodChannel 和 FlutterView

Posted

技术标签:

【中文标题】FlutterActivity MethodChannel 和 FlutterView【英文标题】:FlutterActivity MethodChannel and FlutterView 【发布时间】:2020-04-06 23:04:43 【问题描述】:

所以我大约 4 个月前写了一个 Flutter 应用程序。现在我想做一个小改动,但是我不能再编译应用程序了,因为 GeneratedPluginRegistrant.registerWith(this) 不再起作用了,我没有更改 Kotlin 代码,只更改了 Dart 代码。

“GeneratedPluginRegistrant.registerWith(this)”中的“this”向我显示了这个错误:

Type mismatch.    
Required: FlutterEngine!    
Found: MainActivity

MainActivity 类:

import android.os.Bundle
import io.flutter.app.FlutterActivity
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.view.FlutterMain

class MainActivity : FlutterActivity() 

  override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)

    GeneratedPluginRegistrant.registerWith(this) // here is the error: Type mismatch. Required: FlutterEngine! Found: MainActivity

    MethodChannel(flutterView, CHANNEL).setMethodCallHandler  call, result ->
      if (call.method == "helloFromNativeCode") 
        val greetings = helloFromNativeCode()
        result.success(greetings)
      
    
  

  private fun helloFromNativeCode(): String 
    return "Hello from Native Android Code"
  

  companion object 
    private const val CHANNEL = "flutter.native/helper"
  


如果是使用:

import io.flutter.embedding.android.FlutterActivity

而不是

import io.flutter.app.FlutterActivity

我可以使用

override fun configureFlutterEngine(flutterEngine: FlutterEngine) 
        GeneratedPluginRegistrant.registerWith(flutterEngine);
    

但有问题:

MethodChannel(flutterView, CHANNEL).setMethodCallHandler  call, result ->
      if (call.method == "helloFromNativeCode") 
        val greetings = helloFromNativeCode()
        result.success(greetings)
      
    

因为我在 flutterView 上遇到错误:

Unresolved reference: flutterView

代码如下所示:

import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.view.FlutterMain

class MainActivity : FlutterActivity() 
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) 
        GeneratedPluginRegistrant.registerWith(flutterEngine);
    

  override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)

    MethodChannel(flutterView, CHANNEL).setMethodCallHandler  call, result -> // here is the error
      if (call.method == "helloFromNativeCode") 
        val greetings = helloFromNativeCode()
        result.success(greetings)
      
    
  

  private fun helloFromNativeCode(): String 
    return "Hello from Native Android Code"
  

  companion object 
    private const val CHANNEL = "flutter.native/helper"
  

我希望有人可以帮助我。

【问题讨论】:

我遇到了同样的问题。看起来这在最新的 Flutter 中被打破了,因为他们正在切换到 io.flutter.embedding.android.FlutterActivity 【参考方案1】:

使用flutterEngine.getDartExecutor()代替flutterView。

【讨论】:

【参考方案2】:

我花了几天时间试图弄清楚如何将 Flutter UI 添加到我现有的 Android 应用程序中。最大的挑战是让 MethodChannel 与从 MainActivity 调用的 FlutterActivity 一起工作。我知道这与这里提出的问题有点不同,但是当我搜索“Android FlutterActivity MethodChannel”时,返回了这篇文章。在浏览了很多关于如何做到这一点的资源之后,我终于在这里找到了我的解决方案: https://github.com/flutter/samples/tree/master/add_to_app/android_using_plugin/app/src/main/java/dev/flutter/example/androidusingplugin

最初,在 Android Studio 中,打开现有应用程序后,我依次点击 File、New、New Module、Flutter Module。我收到一个错误,必须执行手动步骤。

我的目标是在 MainActivity - onCreate 中启动 FlutterActivity(在 flutter_module 中打开 main.dart),然后利用尽可能多的原生 Flutter 代码开发 Flutter“屏幕”,并使用 MethodChannel 进行有限的平台调用。在开发替代 Flutter 代码时,我将继续评论现有的 Android 代码。

这是最终对我有用的方法:

../App_Project/Android/Existing_Android_App/settings.gradle

include ':app'
setBinding(new Binding([gradle: this]))
evaluate(new File(settingsDir.parentFile, '../flutter_module/.android/include_flutter.groovy'))
include ':flutter_module’
project(':flutter_module’).projectDir = new File('../../flutter_module’)
rootProject.name=‘existing_android_app’

../App_Project/Android/Existing_Android_App/app/build.gradle

dependencies 
…
    implementation project(':flutter')

../App_Project/Android/Existing_Android_App/app/src/main/AndroidManifest.xml

<activity
    android:name="io.flutter.embedding.android.FlutterActivity"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
    android:hardwareAccelerated="true"
    android:windowSoftInputMode="adjustResize" />

../App_Project/Android/Existing_Android_App/app/src/main/java/com/existing_android_app/MainActivity.java

package com.existing_android_app;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;

public class MainActivity extends AppCompatActivity 

    final String ENGINE_ID = "1";

    @Override
    protected void onCreate(Bundle savedInstanceState) 

        super.onCreate(savedInstanceState);

        FlutterEngine flutterEngine = new FlutterEngine(this);
        flutterEngine.getDartExecutor().executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault());

        FlutterEngineCache.getInstance().put(ENGINE_ID, flutterEngine);

        MethodChannel channel = new MethodChannel(flutterEngine.getDartExecutor(), "com.existing_android_app/myMethodChannel");

        channel.setMethodCallHandler(
                new MethodChannel.MethodCallHandler() 
                    @Override
                    public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) 
                        String url = call.argument("url");
                        if (call.method.equals("openBrowser")) 
                            openBrowser(url);
                         
                          else 
                            result.notImplemented();
                        
                    
                );

        startActivity(FlutterActivity.withCachedEngine(ENGINE_ID).build(this));
    

    void openBrowser(String url) 

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse(url));

        this.startActivity(intent);
    

../App_Project/flutter_module/lib/home_page.dart

class AppHomePage extends StatefulWidget 
  @override
  _HomePageState createState() => _HomePageState();


class _HomePageState extends State<AppHomePage> 

  static const platform = const MethodChannel(‘com.existing_android_app/myMethodChannel’);

  Future<void> _openBrowser() async 
    try 
      final int result = await platform.invokeMethod('openBrowser', <String, String>  'url': "http://bing.com" );
    
    catch (e) 
      print('***** _openBrowser error: ' + e.toString());
    
  

  @override
  Widget build(BuildContext context) 
    return SafeArea(
      child: Scaffold(
        appBar: CustomAppBar(),
        body: Column(
          children: <Widget>[
            RaisedButton(
              label: Text('Search',
                style: TextStyle(fontSize: 18.0),
              ),
              onPressed: ()   _openBrowser(); ,
            ) // RaisedButton.icon
          ], // Widget
        ) // Column
      ) // Scaffold
    ); // SafeArea
  

【讨论】:

谢谢你!最后它的工作。我得到了 MissingPluginException 。这个答案有帮助,但在 github 上打开的问题没有任何帮助。 如何与您联系?请告诉我,你不和谐吗?还是其他? 你在救我的命,兄弟! 嘿,你也可以看看这里吗?这听起来是一个类似的问题,但我无法关联。 ***.com/questions/65780859/…【参考方案3】:

你应该使用

import io.flutter.embedding.android.FlutterActivity;

并在

中声明您的 patformChannel
     @Override
  public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) 
    GeneratedPluginRegistrant.registerWith(flutterEngine);
    new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
        .setMethodCallHandler(
          (call, result) -> 
            // Note: this method is invoked on the main thread.
            // TODO
          
        );
  

有关更多信息,您可以查看文档:https://flutter.dev/docs/development/platform-integration/platform-channels

【讨论】:

【参考方案4】:

你可以像这样使用方法通道和颤振引擎。

private val CHANNEL = "adb"

override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) 
    GeneratedPluginRegistrant.registerWith(flutterEngine)
    MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
            .setMethodCallHandler  call, result ->
                //You can use your custom function for example:
                if (call.method.equals("checkingadb")) 
                    checkingadb(call, result)
                 else 
                    result.notImplemented()
                
            


private fun checkingadb(call: MethodCall, result: MethodChannel.Result) 
    if (Settings.Secure.getInt(this.getContentResolver(), Settings.Secure.ADB_ENABLED, 0) === 1) 
        // debugging enabled
        result.success(1)
     else 
        // debugging is not enabled
        result.success(0)
    

【讨论】:

这是 2021 年末最简单的解决方案,适合我【参考方案5】:

要传递 Flutter Engine 值,我们可以使用 provideFlutterEngine(this) 方法。而对于flutterView,我们可以使用flutterEngine.dartExecutor。这是代码sn-p的url,之前已经回答过了 https://***.com/a/67698834/11887774.

【讨论】:

以上是关于FlutterActivity MethodChannel 和 FlutterView的主要内容,如果未能解决你的问题,请参考以下文章

Flutter Android FlutterActivity

Flutter实践深入分析之——FlutterActivity/Fragment原理流程分析

Flutter实践深入分析之——FlutterActivity/Fragment原理流程分析

无法访问“io.flutter.embedding.android.FlutterActivity”的超类型“android.arch.lifecycle.LifecycleOwner”

FlutterActivity MethodChannel 和 FlutterView

Flutter:带有 patform 通道的 Firebase 消息传递 - 重复的 FlutterActivity