• flutter实践


    项目背景

    项目需要从钉钉微应用跳转 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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class  extends State<FirstPage> {


    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端:

    1
    2
    3
    4
    5
    6
    class  extends State<FirstPage> {
    ...
    const demoPlugin = const MethodChannel('wps.plugin');
    demoPlugin.invokeMethod('interaction', map);
    ...
    }

    android端:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    public class MainActivity extends FlutterActivity {

    private static final String CHANNEL = "wps.plugin";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);


    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", 大专栏  flutter实践 - plsyan class="keyword">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端:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    ...
    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端:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    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);
    }
    ...

  • 相关阅读:
    HTML5
    js实现查找字符串中最多的字符的个数
    get和post的区别
    第十七篇 类的特殊成员
    第十八篇 面向对象修饰符
    MariaDB+Keepalived双主高可用配置MySQL-HA
    linux命令详解——crontab
    Java的内存泄漏
    jvm监控工具jconsole进行远程监控配置
    loadrunner执行场景时报Error -27040: Data Format Extension: Init: Internal error问题解决
  • 原文地址:https://www.cnblogs.com/lijianming180/p/12037766.html
Copyright © 2020-2023  润新知