Flutter建立JsBridge用于webview与h5通信

项目背景

随着项目的不断完善,需要做一些运营活动,通常是H5页面,在app中打开这些H5页面就需要引入WebView,有时候H5需要客户端提供一些内部的接口,这时候我们就需要建立JSBridge用于客户端与H5之间的通讯。

使用

1、安装webview_flutter

 webview_flutter: ^0.3.16
  1. 在android中添加网络权限,目录android/app/src/main/AndroidManifest.xml

3、 ios中在ios/Runner/Info.plist中添加

io.flutter.embedded_views_preview
YES*

4、建立JSBridge

  1. 需要与H5开发约定协议,建立Model
/// WebView与h5进行通信
class JsBridge {
  String method; // 方法名
  Map data; // 传递数据
  Function success; // 执行成功回调
  Function error; // 执行失败回调

  JsBridge(this.method, this.data, this.success, this.error);

  /// jsonEncode方法中会调用实体类的这个方法。如果实体类中没有这个方法,会报错。
  Map toJson() {
    Map map = new Map();
    map["method"] = this.method;
    map["data"] = this.data;
    map["success"] = this.success;
    map["error"] = this.error;
    return map;
  }
  /// jsonDecode(jsonStr)方法返回的是Map类型,需要这里将map转换成实体类
  static JsBridge fromMap(Map map) {
    JsBridge jsonModel =  new JsBridge(map['method'], map['data'], map['success'], map['error']);
    return jsonModel;
  }

  @override
  String toString() {
    return "JsBridge: {method: $method, data: $data, success: $success, error: $error}";
  }
}
  1. 对接收到的h5方法,进行内部处理,这里举个简单的例子,客户端向h5提供了打开微信App的接口openWeChatApp
import 'dart:convert';
import 'package:fluwx/fluwx.dart' as fluwx;

import '../models/JsBridge.dart';
import '../utils/toast.dart';

class JsBridgeUtil {
  /// 将json字符串转化成对象
  static JsBridge parseJson(String jsonStr) {
    JsBridge jsBridgeModel = JsBridge.fromMap(jsonDecode(jsonStr));
    return jsBridgeModel;
  }

  /// 向H5开发接口调用
  static executeMethod(context, JsBridge jsBridge) async{
    if (jsBridge.method == 'openWeChatApp') {
      /// 先检测是否已安装微信
      bool _isWechatInstalled = await fluwx.isWeChatInstalled();
      if (!_isWechatInstalled) {
        toast.show(context, '您没有安装微信');
        jsBridge.error?.call();
        return;
      }
      fluwx.openWeChatApp();
      jsBridge.success?.call();
    }
  }
}
  1. 建立可复用的Webview组件
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:webview_flutter/webview_flutter.dart';

import '../configs/config.dart';
import '../utils/adapter.dart';
import '../utils/privacyProtocolDialog.dart';
import '../utils/JsBridgeUtil.dart';
import '../widgets/AppIcon.dart';
import '../models/appState.dart';
import '../models/userState.dart';

/// WebView页面
class Webview extends StatefulWidget {
  final String url;
  final String title;
  WebViewController webViewController; // 添加一个controller
  final PrivacyProtocolDialog privacyProtocolDialog;

  Webview({Key key, this.url, this.title = '', this.privacyProtocolDialog})
      : super(key: key);

  @override
  WebViewState createState() => WebViewState();
}

class WebViewState extends State {
  bool isPhone = Adapter.isPhone();
  JavascriptChannel _JsBridge(BuildContext context) => JavascriptChannel(
      name: 'FoxApp', // 与h5 端的一致 不然收不到消息
      onMessageReceived: (JavascriptMessage msg) async{
        String jsonStr = msg.message;
        JsBridgeUtil.executeMethod(JsBridgeUtil.parseJson(jsonStr));
      });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: isPhone ? Colors.white : Color(Config.foxColors.bg),
      appBar: AppBar(
        backgroundColor: isPhone ? null : Color(Config.foxColors.bg),
        leading: AppIcon(Config.foxImages.backGreyUrl,
            callback: (){
              Navigator.of(context).pop(true);
              if (widget.privacyProtocolDialog != null) { // 解决切换页面时弹框显示异常问题
                privacyProtocolDialog.show(context);
              }
            }),
        title: Text(widget.title),
        centerTitle: true,
        elevation: 0,
      ),
      body: StoreConnector(
          converter: (store) => store.state.userState,
          builder: (context, userState) {
            return WebView(
              initialUrl: widget.url,
              userAgent:"Mozilla/5.0 foxApp", // h5 可以通过navigator.userAgent判断当前环境
              javascriptMode: JavascriptMode.unrestricted, // 启用 js交互,默认不启用JavascriptMode.disabled
              javascriptChannels: [
                _JsBridge(context) // 与h5 通信
              ].toSet(),
            );
          }),

    );
  }
}
  1. h5页面中引入,并调用JsBridge



    
    
    
    Document



coming baby!



  1. flutter 调用h5方法
// flutter 
webViewController.evaluateJavascript("sayHello('hello world')")

// h5 
function sayHello(msg){
   console.log(msg)
}

以上实现了一个简易版的JsBridge,webview_flutter是官网插件,功能非常强大,JS与Flutter交互只是常用的功能,还提供了页面加载、路由、手势等功能,感兴趣的同学可以去更详细的了解。

你可能感兴趣的:(Flutter建立JsBridge用于webview与h5通信)