如何*准确地*从 Android Java *插件* 平台代码中访问 Flutter 资源?

Boo*_*unz 5 java android assets flutter flutter-plugin

我们想要定义一个可以从同一插件中的 Android 平台代码访问的 Flutter 资源。据称该文档位于此处

请注意,我们不是在讨论 flutter 应用程序中的自定义平台代码——我们是从插件作者的角度讨论 flutter 插件代码。

因此,按照文档,我们从位于 [your_plugin_root_dir]\pubspec.yaml 的插件的 pubspec.yaml 文件开始,然后添加资产定义:

  assets:
    - assets/sound.wav
Run Code Online (Sandbox Code Playgroud)

这指向 [your_plugin_root_dir]\assets\sound.wav 中的现有文件

到目前为止一切都很好,但是我们遇到了一个问题:

当您在 Android studio 中创建新的 Flutter Plugin项目时,该插件的 Android Java 文件如下所示:

public class PluginTestPlugin implements FlutterPlugin, MethodCallHandler {
  /// 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 MethodChannel channel;

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "plugin_test");
    channel.setMethodCallHandler(this);
  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    } else {
      result.notImplemented();
    }
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  }
}
Run Code Online (Sandbox Code Playgroud)

为了从该代码中访问您的资产,文档建议添加以下代码:

AssetManager assetManager = registrar.context().getAssets();
String key = registrar.lookupKeyForAsset("assets/sound.wav");
AssetFileDescriptor fd = assetManager.openFd(key);
Run Code Online (Sandbox Code Playgroud)

但由于该代码中不存在“注册器”实例,并且文档没有描述它是如何创建或如何访问它的,所以我迷失了。

我在这里缺少什么???

Ric*_*eap 7

在方法通道旁边添加另一个字段,以保持绑定;

private MethodChannel channel;

private FlutterPluginBinding binding;
Run Code Online (Sandbox Code Playgroud)

onAttachedToEngine设置中:

channel.setMethodCallHandler(this);
binding = flutterPluginBinding;
Run Code Online (Sandbox Code Playgroud)

并清除它onDetached

channel.setMethodCallHandler(null);
binding = null;
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它(为此,我向名为 的插件(不是示例应用程序)添加了一个资产assets/foo.bin,我的插件名称是plugin1

        String assetPath = binding
                .getFlutterAssets()
                .getAssetFilePathBySubpath("assets/foo.bin", "plugin1");
        try {
            InputStream is = binding.getApplicationContext().getAssets().open(assetPath);
            // todo - read the asset into memory or whatever
            is.close();
        } catch (IOException e) {
            Log.e("plugin1", e.getMessage());
        }
Run Code Online (Sandbox Code Playgroud)

插件项目的 pubspec.yaml 需要额外的行来打包资产,如下所示,位于该plugin部分之后:

  plugin:
    platforms:
      android:
        package: io.swhh.plugin1
        pluginClass: Plugin1Plugin
      ios:
        pluginClass: Plugin1Plugin

  assets:
    - assets/foo.bin
Run Code Online (Sandbox Code Playgroud)

您可能对 iOS 中的同等功能感兴趣(请原谅缺少错误处理)

  let key = FlutterDartProject.lookupKey(forAsset: "assets/foo.bin", fromPackage: "plugin1")
  let path = Bundle.main.path(forResource: key, ofType: nil, inDirectory: nil)
  let url = URL(fileURLWithPath: path!)
  // use url to load the resource
Run Code Online (Sandbox Code Playgroud)