android:scheme="package",Flutter-Webview组件处理Scheme协议

项目背景

之前我介绍过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中添加

NSAppTransportSecurity

NSAllowsArbitraryLoads

NSAllowsArbitraryLoadsInWebContent

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 {

bool isPhone = Adapter.isPhone();

final flutterWebViewPlugin = FlutterWebviewPlugin();

final Set jsChannels = [

JavascriptChannel(

name: userAgent,

onMessageReceived: (JavascriptMessage msg) {

String jsonStr = msg.message;

JsBridgeUtil.executeMethod(JsBridgeUtil.parseJson(jsonStr));

}),

].toSet();

// On urlChanged stream

StreamSubscription _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}';

}

}

}

});

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值