Flutter开发者进阶:接入安卓原生页面
前言
在 Flutter APP
的开发过程中,有时不仅需要使用 Flutter
提供的组件,还需要使用原生的组件。
例如在对接外部 SDK
时,如果自己重新实现 SDK
的逻辑,无疑是本末倒置。
在这种情况下有两种方式可以使用:
-
将
Flutter
项目转为Flutter Module
,打包为aar
,在原生项目中引用,使用原生的方式调用Flutter
,这无疑增加了很多原生开发的工作。 -
将
SDK
引入到Flutter
中,作为一个Flutter Plugin
,建立方法通道(method channel
),调用原生的方法或者页面。
本篇文章将讨论第二种方法。
将一个带有页面的原生安卓 SDK
接入 Flutter
中使用。
话不多说,直接开始。
创建Flutter Plugin
在Flutter项目的根目录执行:
shell
flutter create --template=plugin --platforms=android my_flutter_plugin
这个会创建一个插件工程,里面已经配置好了 Flutter Plugin
的基本结构,包括 build.gradle
文件, AndroidManifest.xml
文件, pubspec.yaml
文件等。
插件工程大致的目录结构如下:
shell
my_flutter_plugin
|- android
| |- src
| | |- main
| | | |- java
| | | | |- com
| | | | | |- example
| | | | | |- my_flutter_plugin
| | | | | | |- MyFlutterPlugin.java
| | | | |- AndroidManifest.xml
| | | |- res
| | | | |- values
| | | | | |- strings.xml
| | | | |- layout
| | | | | |- main.xml
| | | | |- mipmap
| | | |- build.gradle
迁入SDK
将SDK的代码文件迁入到android/src/main/java/com/example/my_flutter_plugin
目录下。
包括包内的代码,注意修改包名。
融合 build.gradle
文件,尤其是 dependencies
部分。
修改 AndroidManifest.xml
,清除其中的权限部分,写入到 Flutter
生成的 Android
部分里面去
将要使用的页面 Activity
注册到这里。
修改插件代码
修改MyFlutterPlugin.java
文件,如下示例:
java
// 省略 import
// 注意这个 ActivityAware ,这是调起页面的关键,否则拿不到上下文
public class MyFlutterPlugin implements FlutterPlugin, MethodCallHandler,ActivityAware{
private static final String TAG = "MyFlutterPlugin";
private MethodChannel channel;
private Activity activity;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), Tag);
channel.setMethodCallHandler(this);
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (call.method.equals("openNativePage")) {
if (activity != null) {
Intent intent = new Intent(activity, MainActivity.class);
activity.startActivity(intent);
result.success("Native page opened");
} else {
result.error("ACTIVITY_NOT_AVAILABLE", "Activity is not available", null);
}
} else {
result.notImplemented();
}
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
}
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
activity = binding.getActivity();
}
@Override
public void onDetachedFromActivityForConfigChanges() {
activity = null;
}
@Override
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
activity = binding.getActivity();
}
@Override
public void onDetachedFromActivity() {
activity = null;
}
}
注册插件
在 Flutter
项目的 pubspec.yaml
文件中,添加如下代码:
yaml
dependencies:
flutter:
sdk: flutter
my_flutter_plugin:
path: ./my_flutter_plugin
重新安装依赖
shell
flutter clean
flutter pub get
在 Flutter 中调用
dart
await MethodChannel("MyFlutterPlugin").invokeMethod("openNativePage");
运行 Flutter
shell
flutter run
现在你可以在你的 Flutter
项目中看到原生页面的调起
总结
Flutter
接入原生页面,主要通过 Flutter Plugin
的方式,通过 MethodChannel
调用原生的页面。
一般按照步骤都会调用成功,但是不排除一些特殊的情况
例如:
其它插件对 SDK
版本的要求不一致,导致启动失败,根据报错修改 SDK
版本即可。
一直报错
shell
Unhandled Exception: MissingPluginException(No implementation found for method getPlatformVersion on channel xxx)
这个一般是通道名称不一致,或者调用页面时没有实现ActivityAware
接口,导致上下文为空。