【问题标题】: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) 中做到这一点?

【问题讨论】:

    标签: flutter flutter-plugin flutter-platform-channel


    【解决方案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 吗?我想打开新活动。
      • 在我的情况下 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 将为空。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      相关资源
      最近更新 更多