Uni Links
一个Flutter插件项目,用于处理App/深层链接(Android)和
通用链接和自定义URL方案(iOS)。
这些链接本质上是浏览器式的链接,可以激活您的应用,并且可能
包含您用于加载应用特定部分或
在网站(或其他应用)上继续特定用户活动的信息。
App Links和Universal Links是普通的https链接,因此,如果应用未安装
(或未正确设置),它们将在浏览器中加载,允许您
呈现网页以供进一步操作,例如安装应用。
请确保您已仔细阅读安装和使用指南,
特别是关于App/Universal Links(https方案)。
安装
要使用该插件,请将uni_links添加为
pubspec.yaml文件中的依赖项。.
0.5.0 主要变更
由于迁移到空安全,一些API已更改。这些更改
主要涉及函数变为getter,类型变为
显式可空。
示例包中的更改是如何升级到
此版本的良好示例。
Permission
Android和iOS需要在配置文件中声明链接的权限。
随时查看example目录中的示例应用,了解
深层链接(Android)和自定义URL方案(iOS)。
以下步骤不是Flutter特定的,而是平台特定的。您可能
可以在线找到更深入的指南,通过搜索Android上的App
Links或Deep Links;iOS上的Universal Links或Custom URL Schema。
对于 Android
Uni Links支持两种类型的Android链接:“App Links”和“Deep Links”。
- App Links仅适用于
https方案,并需要指定主机,以及
一个托管文件 –assetlinks.json。请查看以下指南链接。 - Deep Links可以具有任何自定义方案,并且不需要主机,也不需要
托管文件。缺点是任何应用程序都可以声明一个方案+主机组合,所以
请确保您的组合尽可能独特,例如HST0000001://host.com。
您需要在android/app/src/main/AndroidManifest.xml中声明至少一个意图过滤器。
<manifest ...>
<!-- ... other tags -->
<application ...>
<activity ...>
<!-- ... other tags -->
<!-- Deep Links -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with YOUR_SCHEME://YOUR_HOST -->
<data
android:scheme="[YOUR_SCHEME]"
android:host="[YOUR_HOST]" />
</intent-filter>
<!-- App Links -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with https://YOUR_HOST -->
<data
android:scheme="https"
android:host="[YOUR_HOST]" />
</intent-filter>
</activity>
</application>
</manifest>
对于深度链接,android:host 属性是可选的。
为了进一步提高特异性,您可以添加android:pathPrefix属性。
<!-- Accepts URIs that begin with YOUR_SCHEME://YOUR_HOST/NAME/NAME... -->
<!-- Accepts URIs that begin with https://YOUR_HOST/NAME/NAME... -->
<!-- note that the leading "/" is required for pathPrefix -->
<data
android:scheme="[YOUR_SCHEME_OR_HTTPS]"
android:host="[YOUR_HOST]"
android:pathPrefix="/[NAME][/NAME...]" />
更多信息请阅读
终极指南.
请密切注意指南中关于必需的/.well-known/assetlinks.json
文件的
App Links
部分。
Android开发者文档也是有关
Deep Links和App Links.
对于 iOS
的绝佳信息来源。
- iOS中有两种链接:“Universal Links”和“Custom URL schemes”。
Universal Links仅适用于https方案,并需要指定主机、
entitlements(权限)和一个托管文件 –apple-app-site-association。请查看以下指南链接。 - Custom URL schemes可以有…任何自定义方案,并且没有主机
特异性、权限或托管文件。缺点是任何应用
都可以声明任何方案,所以请确保您的方案尽可能独特,
例如hst0000001或myIncrediblyAwesomeScheme。
您需要声明至少一个。
—
对于Universal Links,您需要添加或创建
com.apple.developer.associated-domains entitlement(权限),可以通过Xcode
(见下文)进行操作,或通过编辑(或创建并添加到Xcode)ios/Runner/Runner.entitlements文件。
部分。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- ... other keys -->
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:[YOUR_HOST]</string>
</array>
<!-- ... other keys -->
</dict>
</plist>
这允许您的应用从https://YOUR_HOST链接启动。
在Xcode中创建entitlements文件:
- 通过双击
ios/Runner.xcworkspace文件打开Xcode。 - 转到项目导航器(Cmd+1),然后选择顶部的
Runner根项。 - 选择
Runner目标,然后选择Signing & Capabilities(签名和功能)选项卡。 - 点击
+ Capability(加号)按钮添加新功能。 - 键入“associated domains”并选择该项。
- 双击Domains列表中的第一项,并将其从
webcredentials:example.com更改为:applinks:+ 您的主机(例如:my-fancy-domain.com)。 - 一个名为
Runner.entitlements的文件将被创建并添加到项目中。 - 完成。 这是截图。
更多信息,请阅读Apple的
Universal Links.
—
对于自定义 URL 方案,您需要在
指南,以及ios/Runner/Info.plist(或通过Xcode的目标信息编辑器,
在 URL Types 下)进行声明
<?xml ...>
<!-- ... other tags -->
<plist>
<dict>
<!-- ... other tags -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>[ANY_URL_NAME]</string>
<key>CFBundleURLSchemes</key>
<array>
<string>[YOUR_SCHEME]</string>
</array>
</dict>
</array>
<!-- ... other tags -->
</dict>
</plist>
这使得您的应用程序可以通过 您的 SCHEME://ANYTHING 链接启动。
有关更多信息,请阅读Apple关于
Inter-App Communication.
的指南)。我**强烈**推荐观看Apple WWDC 2015, session 509 – Seamless Linking to Your App,以了解Universal Links的工作原理(以及如何设置)。
用法
您的应用将通过两种方式接收链接:从冷启动和从后台唤醒。
更多信息请参阅示例用法中的
更多关于App启动链接的信息.
注意:getInitialLink/getInitialUri应在应用程序生命周期中**仅处理一次**,因为它在应用程序的整个生命周期中不应更改。
在应用程序生命周期中,它不打算更改。
您的应用程序的生命周期。
初始链接(字符串)
如果存在,则返回启动应用程序的链接。
您应该在应用程序生命周期的早期处理它,并且只处理一次。
您可以根据需要多次读取该值,但只能处理一次。
import 'dart:async';
import 'dart:io';
import 'package:uni_links/uni_links.dart';
import 'package:flutter/services.dart' show PlatformException;
// ...
Future<void> initUniLinks() async {
// Platform messages may fail, so we use a try/catch PlatformException.
try {
final initialLink = await getInitialLink();
// Parse the link and warn the user, if it is not correct,
// but keep in mind it could be `null`.
} on PlatformException {
// Handle exception by warning the user their action did not succeed
// return?
}
}
// ...
初始链接(Uri)
与getInitialLink相同,但已转换为Uri。
注意:您应该在应用程序生命周期的早期处理此链接,并**仅处理**一次。
处理一次。
// Uri parsing may fail, so we use a try/catch FormatException.
try {
final initialUri = await getInitialUri();
// Use the uri and warn the user, if it is not correct,
// but keep in mind it could be `null`.
} on FormatException {
// Handle exception by warning the user their action did not succeed
// return?
}
// ... other exception handling like PlatformException
可以通过使用Uri.parse(initialLink)来实现相同的功能,这也是这个
便捷方法所做的。
更改事件(字符串)
通常,您会检查getInitialLink并监听更改。
import 'dart:async';
import 'dart:io';
import 'package:uni_links/uni_links.dart';
// ...
StreamSubscription _sub;
Future<void> initUniLinks() async {
// ... check initialLink
// Attach a listener to the stream
_sub = linkStream.listen((String? link) {
// Parse the link and warn the user, if it is not correct
}, onError: (err) {
// Handle exception by warning the user their action did not succeed
});
// NOTE: Don't forget to call _sub.cancel() in dispose()
}
// ...
更改事件(Uri)
与linkStream相同,但已转换为发出Uri对象。
通常,您会检查getInitialUri并监听更改。
import 'dart:async';
import 'dart:io';
import 'package:uni_links/uni_links.dart';
// ...
StreamSubscription _sub;
Future<void> initUniLinks() async {
// ... check initialUri
// Attach a listener to the stream
_sub = uriLinkStream.listen((Uri? uri) {
// Use the uri and warn the user, if it is not correct
}, onError: (err) {
// Handle exception by warning the user their action did not succeed
});
// NOTE: Don't forget to call _sub.cancel() in dispose()
}
// ...
更多关于App启动链接的信息
如果应用程序已被终止(或者更准确地说,未在后台运行),并且操作系统
必须重新启动它——这是一个冷启动。在这种情况下,getInitialLink将
包含启动您应用程序的链接,而Stream在那时将不会产生链接。
在那时。
或者——如果应用程序正在后台运行,并且操作系统必须将其
带到前台,则Stream将是产生链接的那个,而
getInitialLink将是null,或者启动
应用程序的初始链接。
由于这两种情况——您应该始终检查
初始链接(或URI),并订阅链接(或URI)的Stream。
调用链接的工具
如果您注册了一个模式,例如unilink,您可以使用这些CLI工具。
Android
您可以在Android Studio中完成以下任务。
假设您已安装Android Studio(并附带SDK平台工具)。
adb shell 'am start -W -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "unilinks://host/path/subpath"'
adb shell 'am start -W -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "unilinks://example.com/path/portion/?uid=123&token=abc"'
adb shell 'am start -W -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "unilinks://example.com/?arr%5b%5d=123&arr%5b%5d=abc&addr=1%20Nowhere%20Rd&addr=Rand%20City%F0%9F%98%82"'
adb shell 'am start -W -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "unilinks://@@malformed.invalid.url/path?"'
如果您没有adb
在您的路径中,但设置了$ANDROID_HOME环境变量,则使用
"$ANDROID_HOME"/platform-tools/adb ....
注意:或者,您可以直接进入adb shell并执行
am命令。
注意:我使用单引号,因为shell命令后面跟着的是将在
模拟器(或设备)上运行的内容,而shell元字符,例如问号
(?)和与号(&),通常对您的shell有不同的含义。
adb shell与唯一可用的设备(或模拟器)通信,所以如果您
有多个设备,您必须通过指定它来指定您想在哪个设备上运行
shell。
- 唯一USB连接的设备 –
adb -d shell '...' - 唯一模拟的设备 –
adb -e shell '...'
您可以使用adb devices列出当前可用的设备(类似地,
flutter devices也能完成相同的工作)。
iOS
假设您已经安装了Xcode。
/usr/bin/xcrun simctl openurl booted "unilinks://host/path/subpath"
/usr/bin/xcrun simctl openurl booted "unilinks://example.com/path/portion/?uid=123&token=abc"
/usr/bin/xcrun simctl openurl booted "unilinks://example.com/?arr%5b%5d=123&arr%5b%5d=abc&addr=1%20Nowhere%20Rd&addr=Rand%20City%F0%9F%98%82"
/usr/bin/xcrun simctl openurl booted "unilinks://@@malformed.invalid.url/path?"
如果您在路径中安装了xcrun(或simctl),您可以直接调用它。
booted标志假定一个已启动的模拟器(您可以通过
open -a Simulator启动它)并且有一个已启动的设备。您可以通过
指定其UUID(可在xcrun simctl list或flutter devices中找到)来定位特定设备,
替换booted标志。
App Links 或 Universal Links
这些类型的链接使用https作为方案,因此您可以通过
将unilinks替换为https来使用上述示例。
贡献
有关编辑插件代码的帮助,请参阅
文档.
此插件使用联合插件架构。新实现必须将uni_links_platform_interface包添加到其pubspec.yaml,扩展UniLinksPlatform类,并正确注册它。
有关联合插件的更多信息,请参阅提案文档、Flutter插件文档以及Harry Terkelsen的Medium文章,描述了该架构。
许可证
BSD 2条款