在 flutter 插件中获取 activity 引用

Get activity reference in flutter plugin

我在创建flutter插件的时候,插件里默认有两个方法class:

override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding)

fun registerWith(registrar: Registrar)

文件的评论说: It is encouraged to share logic between onAttachedToEngine and registerWith to keep them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called depending on the user's project. onAttachedToEngine or registerWith must both be defined in the same class.

现在,我需要从这里开始另一个 activity,activity.startActivityForResult()。 可以使用 registrar.activity()registerWith(registrar: Registrar) 中获取对 activity 的引用。我如何在方法 onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) 中执行此操作?

找到解决方案here
实施 ActivityAware 其方法之一是

 override fun onAttachedToActivity(binding: ActivityPluginBinding) {
    this.activity = binding.activity;
  }

注:

您可以通过实现 ActivityAware 接口获得对 activity 的引用 但是 如果您 setMethodCallHandler(...)onAttachToEngine() 方法中 onAttachToActivity() 将永远不会被调用,您永远无法访问 activity

看看下面的例子

什么不起作用: 在下面的例子中 onAttachToActivity() 永远不会被调用

class AndroidLongTaskPlugin : FlutterPlugin, ActivityAware {
  private var activity: FlutterActivity? = null

  

  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    //activity is null here 
    //also onAttachToActivity will never be called because we are calling setMethodHandler here
    channel = MethodChannel(binaryMessenger, CHANNEL_NAME)
    channel.setMethodCallHandler { call, result ->
        //our code
    }

  }

  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
    channel?.setMethodCallHandler(null)
  }

  override fun onAttachedToActivity(binding: ActivityPluginBinding) {
    activity = binding.activity as FlutterActivity
  }

  //rest of the methods
}

这是一个工作示例:

class MyPlugin : FlutterPlugin, ActivityAware {
  private var activity: FlutterActivity? = null
  private var binaryMessenger: BinaryMessenger? = null

  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    binaryMessenger = flutterPluginBinding.binaryMessenger
  }

  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
    Log.d("DART/NATIVE", "onDetachedFromEngine")
    channel?.setMethodCallHandler(null)
  }

  override fun onAttachedToActivity(binding: ActivityPluginBinding) {
    Log.d("DART/NATIVE", "onAttachedToActivity")
    activity = binding.activity as FlutterActivity
    //here we have access to activity
    //also make sure to setMethodCallHandler here
    channel.setMethodCallHandler { call, result ->
        //our code
    }
  }

  //rest of the methods
}


通过实现 ActivityAware 接口

https://www.codenong.com/jseb7df49fdfb1/

package com.example.fluttertoast

import android.app.Activity
import android.content.Context
import android.widget.Toast
import androidx.annotation.NonNull;

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
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
import io.flutter.plugin.common.PluginRegistry.Registrar

/** FluttertoastPlugin */
class FluttertoastPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
  private lateinit var channel : MethodChannel
  private lateinit var activity:Activity
  private lateinit var context: Context

  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    channel = MethodChannel(flutterPluginBinding.flutterEngine.dartExecutor, "fluttertoast")
    channel.setMethodCallHandler(this)
    this.context = flutterPluginBinding.applicationContext
  }

  companion object {
    @JvmStatic
    fun registerWith(registrar: Registrar) {
      val channel = MethodChannel(registrar.messenger(), "fluttertoast")
      channel.setMethodCallHandler(FluttertoastPlugin())
    }
  }

  override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
    if (call.method == "getPlatformVersion") {
      Toast.makeText(activity,"Hello!",Toast.LENGTH_SHORT).show()
      result.success("Android ${android.os.Build.VERSION.RELEASE}")
    } else {
      result.notImplemented()
    }
  }

  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
    channel.setMethodCallHandler(null)
  }
  override fun onDetachedFromActivity() {}
  override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
    onAttachedToActivity(binding)
  }
  override fun onAttachedToActivity(binding: ActivityPluginBinding) {
    this.activity = binding.activity
  }
  override fun onDetachedFromActivityForConfigChanges() {}
}

在我的例子中,alireza-easazade 的分辨率不起作用。我从 onAttachedToEngine 中删除了 MethodChannel 创建,但 ActivityAware 通知仍然没有出现。对我有用的是用 flutterPluginBinding.getFlutterEngine().getDartExecutor() 替换 flutterPluginBinding.getBinaryMessenger() 作为 MethodChannel 构造函数中的参数。一旦我这样做 onAttachedToActivityonAttachedToEngine.

之后立即被调用

这是我的工作示例:

public class MyPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {

  private ActivityPluginBinding _activityBinding;
  private FlutterPluginBinding _flutterBinding;
  private MethodChannel _channel;

  // FlutterPlugin  overrides

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    _flutterBinding = flutterPluginBinding;
    _channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "com.example.test/myplugin");
    _channel.setMethodCallHandler(this);
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    _channel.setMethodCallHandler(null);
    _channel = null;
    _flutterBinding = null;
  }

  // ActivityAware  overrides

  @Override
  public void onAttachedToActivity​(ActivityPluginBinding binding) {
    _activityBinding = binding;
  }

  @Override
  public void   onDetachedFromActivity() {
    _activityBinding = null;
  }

  @Override
  public void   onReattachedToActivityForConfigChanges​(ActivityPluginBinding binding) {
    _activityBinding = binding;
  }

  @Override
  public void   onDetachedFromActivityForConfigChanges() {
    _activityBinding = null;
  }

  // MethodCallHandler overrides
  
  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    // Handle calls
  }

  // Implementation

  public Context getApplicationContext() {
    return (_flutterBinding != null) ? _flutterBinding.getApplicationContext() : null;
  }

  public Activity getActivity() {
    return (_activityBinding != null) ? _activityBinding.getActivity() : null;
  }
}