在颤振插件中获取活动参考

Posted

技术标签:

【中文标题】在颤振插件中获取活动参考【英文标题】:Get activity reference in flutter plugin 【发布时间】:2020-05-10 06:38:23 【问题描述】:

我在创建flutter插件时,插件类默认有两个方法:

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.startActivityForResult()。 可以使用registrar.activity() 获得对registerWith(registrar: Registrar) 中活动的引用。如何在方法onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) 中做到这一点?

【问题讨论】:

【参考方案1】:

通过实现 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() 

【讨论】:

【参考方案2】:

注意:

您可以通过实现 ActivityAware 接口来获取对活动的引用但是如果您在 onAttachToEngine() 方法中 setMethodCallHandler(...) 将永远不会调用 onAttachToActivity() 并且您将永远无法访问活动

看看下面的例子

什么不起作用: 在下面的例子中,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



【讨论】:

@Alexufo。看看这个库pub.dev/packages/android_long_task 你知道我可以在哪里附加 startActivityForResult 吗?我想打开新活动。 我找到了解决方案bitbucket.org/prathap_kumar/mvbarcodescan/raw/… 在我的情况下 onAttachedToEngine 这个代码工作 MethodChannel channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), channelName); channel.setMethodCallHandler(this); 而在 onAttachedToActivity 我使用 activity = activityPluginBinding.getActivity(); activityPluginBinding.addActivityResultListener(this);【参考方案3】:

找到解决方案here。 实现ActivityAware,其方法之一是

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

【讨论】:

@Neeraj,我尝试了上述解决方案,但令人惊讶的是,在方法调用中,活动为空。我在 AttachedToActivity 回调中分配了活动,并且在立即 onMethodCall 之后,this.activity 为空。有什么建议吗? 阅读更多the documentation @Satya Attili 我也有同样的问题。你找到解决办法了吗? 您在什么条件下尝试@SatyaAttili?如果您在 Service 或静态广播接收器中使用后台消息处理程序,则尚未创建 Activity,因此从未调用过 onAttachedToActivity。所以this.activity 将为空。

以上是关于在颤振插件中获取活动参考的主要内容,如果未能解决你的问题,请参考以下文章

无法解析颤振/飞镖中的文件

flutter-web:通过 Location 插件获取 web 上的位置

颤振我无法从地理定位器获取地址

颤振和Linux

Flutter 健康插件“未授予授权”

Flutter 健康插件“未授予授权”