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

How *Exactly* to Access Flutter Assets From Within Android Java *Plugin* Platform Code?

我们想要定义一个 Flutter 资产,它可以从同一插件中的 Android 平台代码访问。这方面的文档据称是 here.

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

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

  assets:
    - assets/sound.wav

这指向位于 [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);
  }
}

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

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

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

我在这里错过了什么????

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

private MethodChannel channel;

private FlutterPluginBinding binding;

onAttachedToEngine中设置:

channel.setMethodCallHandler(this);
binding = flutterPluginBinding;

并在onDetached

中清除
channel.setMethodCallHandler(null);
binding = null;

然后像这样使用它(为此,我向名为 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());
        }

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

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

  assets:
    - assets/foo.bin

您可能对 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