使用flutter开发移动应用
2019-11-18 本文已影响0人
pilisiyang
项目背景
项目需要从钉钉微应用跳转 WPS 直接打开 word 文档,但是 WPS 只提供了 StartActivity 方式携带参数跳转应用,deeplink 只能打开应用,而钉钉微应用只支持 deeplink ,所以需要搭建一个中间跳转的app工具。
Flutter
Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。
flutter使用dart语言,是将来谷歌新操作系统 Fuchsia 的主要构建方式,组件使用响应式框架构建,使用组件构建 UI ,组件可以改变状态,提供热加载,最大的特点是同时在iOS和Android系统中开发应用,支持混合开发。
获取 deeplink 路径
在flutter应用中导入 uni_links 包,接收deeplink:
在 pubspec.yaml 文件 dependencies 下增加 uni_links: ^0.1.4 ,记得执行 flutter packages get
class FirstPageState extends State<FirstPage> {
@override
void initState() {
...
getInitialUri().then((Uri url) {
print('URL received: $url');
if (url != null && url.scheme == 'gsoft') {
map.addAll(url.queryParameters);
}
});
...
super.initState();
}
...
}
执行 getInitialUri 方法可以拿到 deeplink 的路径,获取传递的参数。
通过 StartActivity 方式启动WPS
flutter应用与原生之间交互需要通过插件模式:
定义 plugin,两边 plugin 名需要一致
flutter端:
class FirstPageState extends State<FirstPage> {
...
const demoPlugin = const MethodChannel('wps.plugin');
demoPlugin.invokeMethod('interaction', map);
...
}
android端:
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "wps.plugin";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 跳转wps
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
if (call.method.equals("interaction")) {
String fileUrl = call.argument("fileUrl");
Bundle bundle = new Bundle();
//打开文档参数-打开模式
Object openMode = call.argument("OpenMode");
if (openMode != null) {
bundle.putString(WpsModel.OPEN_MODE, String.valueOf(openMode));
}
//打开文档参数-打开直接进入编辑模式
Object editMode = call.argument("EditMode");
if (editMode != null) {
bundle.putBoolean("Edit Mode", Boolean.valueOf(editMode.toString()));
}
//文档记录-删除使用记录
Object clearTrace = call.argument("ClearTrace");
if (clearTrace != null) {
bundle.putBoolean("ClearTrace", Boolean.valueOf(clearTrace.toString()));
}
//文档初始化参数-自动跳转
Object autoJump = call.argument("AutoJump");
if (autoJump != null) {
bundle.putBoolean("AutoJump", Boolean.valueOf(autoJump.toString()));
}
//修订相关参数-打开文档是否显示修订批注面板
Object showReviewingPaneRightDefault = call.argument("ShowReviewingPaneRightDefault");
if (showReviewingPaneRightDefault != null) {
bundle.putBoolean("ShowReviewingPaneRightDefault", Boolean.valueOf(showReviewingPaneRightDefault.toString()));
}
//修订相关参数-修订模式打开文档
Object enterReviseMode = call.argument("EnterReviseMode");
if (enterReviseMode != null) {
bundle.putBoolean("EnterReviseMode", Boolean.valueOf(enterReviseMode.toString()));
}
//水印相关参数-设置水印文字内容
Object waterMaskText = call.argument("WaterMaskText");
if (waterMaskText != null) {
bundle.putString("WaterMaskText", String.valueOf(waterMaskText));
}
//批注-批注的作者
Object userName = call.argument("UserName");
if (userName != null) {
bundle.putString("UserName", String.valueOf(userName));
}
//文件保存时发送广播
bundle.putBoolean("SendSaveBroad", true);
Intent intent = new Intent();
File file = new File(fileUrl);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider", file);
intent.setData(contentUri);
intent.putExtras(bundle);
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setClassName(WpsModel.PackageName.PRO, WpsModel.ClassName.NORMAL);
MainActivity.this.startActivity(intent);
result.success("success");
} else {
result.notImplemented();
}
}
});
GeneratedPluginRegistrant.registerWith(this);
}
}
WPS保存文件操作后广播
原生安卓端接收 WPS 广播后,传递给 flutter 处理。
android端:
...
private static final String SAVED_CHANNEL = "saved.wps.plugin";
...
//接收wps广播
new EventChannel(getFlutterView(), SAVED_CHANNEL)
.setStreamHandler(new EventChannel.StreamHandler() {
private BroadcastReceiver savedReceiver;
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
savedReceiver = createSavedReceiver(eventSink);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("cn.wps.moffice.broadcast.AfterSaved");
registerReceiver(savedReceiver, intentFilter);
}
@Override
public void onCancel(Object o) {
unregisterReceiver(savedReceiver);
savedReceiver = null;
}
});
...
private BroadcastReceiver createSavedReceiver(final EventChannel.EventSink events) {
return new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getBooleanExtra(SAVE_AS, false)) {
events.success(intent.getStringExtra("CurrentPath"));
}
}
};
}
flutter端:
static const fromAndroidPlugin = const EventChannel('saved.wps.plugin');
...
void _fromAndroidPlugin() {
fromAndroidPlugin
.receiveBroadcastStream()
.listen(_onFromAndroidEvent, onError: _onFromAndroidError);
}
void _onFromAndroidEvent(Object event) {
print("文件修改保存路径:" + event);
}
void _onFromAndroidError(Object error) {
print(error);
}
...