美文网首页Flutter学习
Flutter-Webview组件处理Scheme协议

Flutter-Webview组件处理Scheme协议

作者: 小小的开发人员 | 来源:发表于2020-03-05 15:59 被阅读0次

项目背景

之前我介绍过Flutter建立JsBridge用于webview与h5通信,有时候h5页面中需要唤醒其他应用的功能,通过约定的Scheme协议,比如weixin://,这时候就需要我们的Webview组件处理,否则就会出现net:ERR_UNKNOWN_URL-SCHEME的页面报错。

插件变更

上篇介绍Webview使用的文章,我用的是官方插件 webview_flutter,实际应用的时候,出现了个难以解决的bug,在华为mate30、android10环境下,h5的input元素调取手机系统键盘会失败,据我们测试,目前只发现在该手机型号、安卓系统下出现该问题,而华为客户占比很重,是必须要解决的,github上有类似的closed issue,推荐使用flutter_webview_plugin,所以就更改了webview插件,这两个插件评分都很高,提供的api类似,使用方法也相似,组件改造工作量很小。

组件改造

1、安装webview_flutter

 flutter_webview_plugin: ^0.3.10+1

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

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSAllowsArbitraryLoadsInWebContent</key>
    <true/>
</dict>

3、改造WebView组件

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import 'package:url_launcher/url_launcher.dart';

import '../configs/config.dart';
import '../utils/adapter.dart';
import '../utils/JsBridgeUtil.dart';
import '../widgets/AppIcon.dart';
import '../widgets/FixedSizeText.dart';

/// 与h5 端的一致 不然收不到消息
const String userAgent = 'FoxApp';

/// WebView页面
class Webview extends StatefulWidget {
  final String url;
  final String title;
  final VoidCallback backCallback;

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

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

class WebviewState extends State<Webview> {
  bool isPhone = Adapter.isPhone();
  final flutterWebViewPlugin = FlutterWebviewPlugin();

  final Set<JavascriptChannel> jsChannels = [
    JavascriptChannel(
        name: userAgent,
        onMessageReceived: (JavascriptMessage msg) {
          String jsonStr = msg.message;
          JsBridgeUtil.executeMethod(JsBridgeUtil.parseJson(jsonStr));
        }),
  ].toSet();

  // On urlChanged stream
  StreamSubscription<String> _onUrlChanged;

  @override
  void initState() {
    super.initState();
    flutterWebViewPlugin.close();

    // Add a listener to on url changed
    _onUrlChanged =
        flutterWebViewPlugin.onUrlChanged.listen((String url) async {
      if (url.contains('weixin:') || url.contains('alipay:')) {
        await flutterWebViewPlugin.stopLoading();
        await flutterWebViewPlugin.goBack();
        if (await canLaunch(url)) {
          await launch(url);
        } else {
          throw 'Could not launch $url';
        }
      }
    });
  }

  @override
  void dispose() {
    _onUrlChanged.cancel();
    flutterWebViewPlugin.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: isPhone ? Colors.white : Color(Config.foxColors.bg),
      body: WebviewScaffold(
        appBar: AppBar(
          backgroundColor: isPhone ? null : Color(Config.foxColors.bg),
          leading: AppIcon(Config.foxImages.backGreyUrl, callback: () {
            flutterWebViewPlugin.close();
            Navigator.of(context).pop(true);
            widget.backCallback?.call();
          }),
          title: FixedSizeText(widget.title),
          centerTitle: true,
          elevation: 0,
        ),
        url: widget.url,
        userAgent: "Mozilla/5.0 $userAgent",
        // h5 可以通过navigator.userAgent判断当前环境
        javascriptChannels: jsChannels,
        mediaPlaybackRequiresUserGesture: false,
        withZoom: true,
        withLocalStorage: true,
        hidden: true,
      ),
    );
  }
}

测试同学提出了一个bug,跳转微信时,会偶现net:ERR_UNKNOWN_URL-SCHEME页面,这条issue也在讨论这个问题,https://github.com/fluttercommunity/flutter_webview_plugin/issues/43,本质是插件提供的功能不完善,没有提供拦截页面显示的方法,社区提出了一些解决方式。

/// 兼容android进入报错页
    _onStateChanged = flutterWebViewPlugin.onStateChanged
        .listen((WebViewStateChanged state) async {
      if (mounted) {
        if (state.url.startsWith('weixin:') &&
            state.type == WebViewState.abortLoad) {
          if (await canLaunch(state.url)) {
            await launch(state.url);
          } else {
            throw 'Could not launch ${state.url}';
          }
        }
      }
    });

相关文章

  • Flutter-Webview组件处理Scheme协议

    项目背景 之前我介绍过Flutter建立JsBridge用于webview与h5通信,有时候h5页面中需要唤醒其他...

  • (二)HTTP URI

    Author: Xu FC URL URL 组件Scheme: scheme:协议缩写的小写,比如 http/ft...

  • Android 系统路由Scheme跳转

    scheme在Android中是一种页面跳转的协议。通过定义自己的scheme可以非常方便的实现页面跳转,适合组件...

  • Android Scheme URL 使用方法

    URL Scheme 介绍 URL Scheme是一种页面内跳转协议,通过定义自己的URL Scheme协议,可以...

  • Android组件化开发之路(二)URL Scheme使用

    什么是 URL Scheme? android中的scheme是一种页面内跳转协议,通过定义自己的scheme协议...

  • scheme调起App及传参的问题汇总

    协议格式 首先咱们看看scheme的协议格式: scheme://host:8080/path?query1=1...

  • Scheme协议

    Scheme是一种页面内跳转协议,通过自定义Scheme协议,可以跳转到app中的任何页面 服务器可以定制化跳转a...

  • scheme协议

    先说下DeepLink(深度链接) DeepLink,又称深度链接、调起链接,是一套链接服务,用户点击链接可以跳转...

  • Aroute之进阶使用

    通过Scheme跳转 Scheme是界面跳转协议,类似URL地址,通过url可以打开某个网站,而通过Scheme可...

  • 笔记-H5页面调起app实现

    h5页面调起app实现,通过scheme协议或者link协议调起; 步骤一:app清单文件设置scheme ,如果...

网友评论

    本文标题:Flutter-Webview组件处理Scheme协议

    本文链接:https://www.haomeiwen.com/subject/fybtchtx.html