如何在 Flutter 插件中获取 Activity 和 Context

Bla*_*nka 9 dart flutter

我的一个包需要访问Context,我从onAttachedToEngine->获取它flutterPluginBinding.getApplicationContext()到一个变量,但这会导致应用程序崩溃NullPointerException。原因是我想我在Context分配给变量之前尝试使用它。

访问 的正确方法是Context什么?

Activity如果我也想要,我怎么能得到呢?

Ana*_*afi 23

依赖于Create-Flutter-Plugin 中的flutter 文档,请按照以下步骤操作:

1- 导入 ActivityAware:

import io.flutter.embedding.engine.plugins.activity.ActivityAware
Run Code Online (Sandbox Code Playgroud)

2- 在您的班级中实施 ActivityAware:

public class ClassName: FlutterPlugin, MethodCallHandler, ActivityAware { 
Run Code Online (Sandbox Code Playgroud)

3- 定义lateinit变量以使用它的类:

private lateinit var context: Context
private lateinit var activity: Activity
Run Code Online (Sandbox Code Playgroud)

4- 添加这些功能:

override fun onDetachedFromActivity() {
    TODO("Not yet implemented")
}

override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
    TODO("Not yet implemented")
}

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

override fun onDetachedFromActivityForConfigChanges() {
    TODO("Not yet implemented")
}
Run Code Online (Sandbox Code Playgroud)

5- 在 onAttachedToEngine 函数中添加这一行:

context = flutterPluginBinding.applicationContext
Run Code Online (Sandbox Code Playgroud)

您可以查看此完整代码以获取更多理解:

package com.example.flutter_plugin_name

import android.app.Activity
import android.content.Context
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


public class FlutterPluginName: FlutterPlugin, MethodCallHandler, ActivityAware {
  /// The MethodChannel that will the communication between Flutter and native Android
  ///
  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
  /// when the Flutter Engine is detached from the Activity
  private lateinit var channel : MethodChannel

    private lateinit var context: Context
    private lateinit var activity: Activity

  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    channel = MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "flutter_plugin_name")
    channel.setMethodCallHandler(this);
    context = flutterPluginBinding.applicationContext
  }



  // This static function is optional and equivalent to onAttachedToEngine. It supports the old
  // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
  // plugin registration via this function while apps migrate to use the new Android APIs
  // post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
  //
  // 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.
  companion object {
    @JvmStatic
    fun registerWith(registrar: Registrar) {
      val channel = MethodChannel(registrar.messenger(), "flutter_plugin_name")
      channel.setMethodCallHandler(FlutterMapboxTurnByTurnPlugin())
    }
  }

  override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
    if (call.method == "getPlatformVersion") {
      result.success("Android ${android.os.Build.VERSION.RELEASE}")
    }

    else {
      result.notImplemented()
    }
  }

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

    override fun onDetachedFromActivity() {
        TODO("Not yet implemented")
    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
        TODO("Not yet implemented")
    }

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

    override fun onDetachedFromActivityForConfigChanges() {
        TODO("Not yet implemented")
    }
}
Run Code Online (Sandbox Code Playgroud)


Bla*_*nka 6

BatteryPlugin源码(既然是Flutter团队的,我觉得是正确的方法):

  private Context mContext; // Instance variable for context

  // ....

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    onAttach(flutterPluginBinding.getApplicationContext(),flutterPluginBinding.getBinaryMessenger());  // <- this is the line we need here, a new method call
    final MethodChannel channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "com.myplugin/my_plugin");
    channel.setMethodCallHandler(new MyPlugin());
  }

 //here is the implementation of that new method
 private void onAttachedToEngine(Context applicationContext, BinaryMessenger messenger) {
     this.mContext = applicationContext;
     methodChannel = new MethodChannel(messenger, "com.myplugin/my_plugin");
     methodChannel.setMethodCallHandler(this);
 }

 // ....
Run Code Online (Sandbox Code Playgroud)

以下是Flutter 团队的 Google 软件工程师推荐使用的方法Activity

在一个简单MethodChannel的匿名的MethodCallHandler

public class MyPlugin {
  public static void registerWith(Registrar registrar) {
    final MethodChannel channel = new MethodChannel(registrar.messenger(), "my_channel");
    final Activity activity = registrar.activity();
    channel.setMethodCallHandler(new MethodCallHandler() {
      @Override
      public void onMethodCall(MethodCall call, Result result) {
        // use activity here
      }
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

通过使用以下方法实现您的类MethodCallHandler

Registrar注册时提供activity()访问器。我们可以Activity通过实现我们的插件构造函数并将其存储在一个字段中以在onMethodCall方法中使用来使用它:

public class MyPlugin implements MethodCallHandler {
  private final Activity activity;

  public static void registerWith(Registrar registrar) {
    final MethodChannel channel = new MethodChannel(registrar.messenger(), "my_channel");
    channel.setMethodCallHandler(new MyPlugin(registrar.activity()));
  }

  private MyPlugin(Activity activity) {
    this.activity = activity;
  }

  @Override
  public void onMethodCall(MethodCall call, Result result) {
    // use activity here
  }
}
Run Code Online (Sandbox Code Playgroud)