最近在使用flutter开发APP,flutter实现了一套代码同时生成Android和iOS两个平台的APP,可以实现零基础快速上手APP开发,缩短开发周期。但flutter仍处于较快增长期,版本迭代速度快,文档资料相对较少,这里将开发中遇到的一些问题整理下来,备忘+分享。
flutter版本:1.12.13+hotfix.5
这里使用fluwx插件实现微信中分享,版本号1.2.1+1。
在pubspec.yaml中增加依赖
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
#other dependencies
fluwx: ^1.2.1+1
如果需要微信回调,需要配置WXEntryActivity和WXPayEntryActivity,如果不使用回调,则不需要特殊配置。详见官方doc
如官方文档所示,需要配置ios的URLSchema, LSApplicationQueriesSchemes or universal link
ios/Runner/Info.plist
CFBundleURLTypes
CFBundleTypeRole
Editor
CFBundleURLName
your url name
CFBundleURLSchemes
your scheme
CFBundleTypeRole
Editor
CFBundleURLName
weixin
CFBundleURLSchemes
you wechat appid
LSApplicationQueriesSchemes
wechat
weixin
weixinULAPI
其中CFBundleURLTypes的第一项是为了能够从url跳回APP所设置
ios/Runner/Runner.entitlements
com.apple.developer.associated-domains
webcredentials:your universal link
这里的universal link要与微信开放平台上的设置保持一致。
注册微信sdk,如果用于ios,必须指定universalLink
import 'package:fluwx/fluwx.dart' as fluwx;
@override
void initState() {
fluwx.registerWxApi(
appId: your wechat appid,
doOnAndroid: true,
doOnIOS: true,
universalLink: your universal link
);
}
分享,以图文链接到好友为例
fluwx.shareToWeChat(
fluwx.WeChatShareWebPageModel(
title: your title,
description: your description(can split by \n),
webPage: 'https://example.com/app/jump.html?pageName=xx&id=xx',
thumbnail: 'https://example.com/images/share_weixin.png',
scene: fluwx.WeChatScene.SESSION
)
).then((data) {
print (data);
});
至此,可实现从APP分享到微信,下一步将从微信点击分享后的链接,唤起APP并直接打开指定页面。
从APP分享出去只是产品宣传的第一步,下一步需要接收到的用户通过点击链接卡片可以打开我们的APP的某个指定页面。当然,用户点击分享链接后,可以打开产品的小程序or网页版,以更好的提升体验,这里仅以跳转APP为例。
很多文档提到改写Activity类来实现跳转链接参数的解析,从而进一步跳转到指定页面,但随着flutter的升级,kotlin的Activity相关API有明显变化,由于笔者并未做过Android开发,所以放弃了硬写的方案,这里使用uni_links来实现参数的解析。
uni_links: ^0.2.0
android/app/src/main/AndroidManifest.xml
在上面微信配置中已加入相关配置(这里没有使用HTTPS scheme,如果使用的话,还需要一些额外配置,详见uni_link的文档)
uni_link的官方example已经非常详尽,照着来就可以实现,如下是我的实现
在main.dart中实现
class MyAppState extends State with WidgetsBindingObserver {
StreamSubscription _sub;
String _latestLink = 'Unknown';
Uri _latestUri;
// This widget is the root of your application.
@override
void initState() {
super.initState();
initPlatformState();
}
@override
void dispose() {
if (_sub != null) _sub.cancel();
super.dispose();
}
Future initPlatformState() async {
_sub = getLinksStream().listen((String link) {
if (!mounted) return;
setState(() {
_latestLink = link ?? "Unknown";
_latestUri = null;
try {
if (link != null) _latestUri = Uri.parse(link);
} on FormatException {}
});
}, onError: (err) {
if (!mounted) return;
setState(() {
_latestLink = 'Failed to get latest link: $err.';
_latestUri = null;
});
});
getLinksStream().listen((String link) {
print('got link: $link');
}, onError: (err) {
print('got err: $err');
});
String initialLink;
Uri initialUri;
try {
initialLink = await getInitialLink();
print('initial link: $initialLink');
if (initialLink != null) initialUri = Uri.parse(initialLink);
} on PlatformException {
initialLink = 'Failed to get initial link.';
initialUri = null;
} on FormatException {
initialLink = 'Failed to parse the initial link as Uri.';
initialUri = null;
}
if (!mounted) return;
setState(() {
_latestLink = initialLink;
_latestUri = initialUri;
});
}
@override
Widget build(BuildContext context) {
final queryParams = _latestUri?.queryParametersAll?.entries?.toList();
// print (queryParams);
// print (queryParams?.length);
Widget homeWidget = new SplashPage();
String pageType;
String taskID;
if (queryParams != null) {
for (var param in queryParams) {
if (param.key == 'pageName') {
pageType = param.value.length > 0 ? param.value[0] : null;
}
if (param.key == 'taskid') {
taskID = param.value.length > 0 ? param.value[0] : null;
}
}
}
print (pageType);
if (pageType == 'report') {
homeWidget = new ReportPage(taskID: taskID,);
}
return MaterialApp(
routes: {
Config.routeMain: (context) => MyHomePage()
},
debugShowCheckedModeBanner: false,
title: 'your title',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: homeWidget
);
}
}
这里写了一个简单的中转页面
Your Title
点击打开APP
中转页面设置了自动跳转和点击跳转,由于微信浏览器对scheme link的限制,ios和Android都需要点击右上角的‘浏览器中打开’。ios(iPhone xr,13.3)在Safari中打开后会自动弹出对话框,Android(华为)在系统浏览器和chrome会自动弹出对话框,qq浏览器需要点击页面超链接才会弹出对话框。
注:目前仍存在一个问题,如果APP处于后台打开状态,从链接打开后,只是唤起APP,并不会跳转到指定页面,通过打印日志,build函数中解析链接参数的逻辑解析正确,目前这个问题还未进一步解决。