1. iOS
1.1 Deep Link
-
作用
:Deep Link 允许应用响应特定的链接,直接打开应用内的某个特定内容或页面。这意味着用户可以通过点击一个链接,直接跳转到应用内部的某个具体位置,而不是每次都从应用的首页开始。 -
配置
:开发者需要在应用内配置URL schemes
,并处理传入的URL来决定打开应用时显示哪个界面。 -
限制
:Deep Link 主要限制在应用已安装的情况下有效。如果应用未安装,用户点击链接会发生什么,完全取决于开发者的处理逻辑(例如,可以跳转到App Store)。
1.2 Universal Link
-
作用
:Universal Link 是一种更先进的链接方式,不仅支持深链接到应用内部的特定内容,还能在应用未安装时打开网页链接。这提供了更为流畅的用户体验,因为它可以智能地决定是打开网页还是应用内容。 -
配置
:开发者需要在自己的服务器上配置一个文件(apple-app-site-association 或 AASA 文件
),并在应用的Info.plist中声明对应的域名。这样,iOS系统可以验证链接是否应该打开应用,并自动处理。 -
优势
:Universal Link 支持的场景更广泛,提供了更好的用户体验。如果应用已安装
,它可以直接打开
应用内的相关内容;如果未安装
,链接会打开网页版内容
。此外,Universal Link 还支持搜索引擎索引,有利于提高内容的可发现性。
总的来说,Universal Link 是 Apple 推荐的链接方案,它在用户体验和技术实现上都比传统的 Deep Link 更加先进和完善。但在某些情况下,根据应用的需求和特定场景,开发者可能仍然需要使用 Deep Link。
1.3 代码获取外部链接带过来的参数
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
// 确认是不是由 Universal Link 触发的
if userActivity.activityType == NSUserActivityTypeBrowsingWeb, let url = userActivity.webpageURL {
// 解析 URL 来获取需要的参数
handleUniversalLink(url: url)
}
return true
}
func handleUniversalLink(url: URL) {
// 这里是解析 URL 和查询参数的逻辑
// 例如,你可以使用 URLComponents 类来解析 URL
let components = URLComponents(url: url, resolvingAgainstBaseURL: true)
if let queryItems = components?.queryItems {
for item in queryItems {
print("\(item.name) = \(item.value ?? "")")
// 根据参数名称处理相应的逻辑
}
}
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
// 确认是不是由 Universal Link 触发的
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
NSURL *url = userActivity.webpageURL;
// 解析 URL 来获取需要的参数
[self handleUniversalLink:url];
}
return YES;
}
- (void)handleUniversalLink:(NSURL *)url {
// 解析 URL 和查询参数的逻辑
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:YES];
NSArray *queryItems = components.queryItems;
for (NSURLQueryItem *item in queryItems) {
NSLog(@"%@ = %@", item.name, item.value);
// 根据参数名称处理相应的逻辑
}
}
2.Android
2.1 Intent Filters
-
作用
:Intent Filters 类似于 iOS 中的 Deep Link。它们允许 Android 应用响应外部的意图(Intent),如从网页中打开应用的特定页面。通过在应用的 manifest 文件中声明 Intent Filters,开发者可以指定应用可以处理的 URL。 -
配置
:开发者需要在 AndroidManifest.xml 文件中为相应的 Activity 配置 Intent Filter,包括指定要匹配的动作(Action)、数据(Data)和类别(Category)。 -
限制
:就像 Deep Link,如果应用未安装,点击链接将不会有任何作用,除非开发者在网页上提供了额外的逻辑来引导用户下载应用。
2.2 App Links
-
作用
:App Links 是 Android 对 Universal Links 的答案。它允许应用在用户设备上更为无缝地处理网页链接,实现在应用和网页之间的*跳转。当点击一个链接时,系统会智能地判断是打开浏览器还是直接打开应用内的对应内容,即使应用未安装,也能优雅地回退到网页视图。 -
配置
:为了使用 App Links,开发者需要在应用的 AndroidManifest.xml 中添加相应的 Intent Filter,并且必须在服务器上托管一个特定的 JSON 文件(assetlinks.json)
,用于验证应用是否有权处理网站的链接。 -
优势
:App Links 提供了更加直接和安全的方式来处理深度链接,包括在应用未安装时的情况,从而提供更好的用户体验。它也支持通过 HTTPS 进行验证,确保了链接的安全性。
总结来说,Android 的 App Links 和 Intent Filters 分别与 iOS 的 Universal Link 和 Deep Link 相当。App Links 提供了一个更为先进和流畅的用户体验,使得在应用和网页之间的跳转更加无缝,同时也增加了链接的安全性和可靠性。
2.3 代码获取外部链接带过来的参数
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取意图
Intent intent = getIntent();
String action = intent.getAction();
Uri data = intent.getData();
// 检查是否是由深度链接激活的
if (Intent.ACTION_VIEW.equals(action) && data != null) {
String channelId = data.getQueryParameter("channelId");
// 使用渠道ID做相应的处理
}
}
3.服务器根目录下的文件
3.1 iOS的apple-app-site-association文件
官网解释
{
"applinks": {
"details": [
{
"appIDs": [ "ABCDE12345.com.example.app", "ABCDE12345.com.example.app2" ],
"components": [
{
"#": "no_universal_links",
"exclude": true,
"comment": "Matches any URL with a fragment that equals no_universal_links and instructs the system not to open it as a universal link."
},
{
"/": "/buy/*",
"comment": "Matches any URL with a path that starts with /buy/."
},
{
"/": "/help/website/*",
"exclude": true,
"comment": "Matches any URL with a path that starts with /help/website/ and instructs the system not to open it as a universal link."
},
{
"/": "/help/*",
"?": { "articleNumber": "????" },
"comment": "Matches any URL with a path that starts with /help/ and that has a query item with name 'articleNumber' and a value of exactly four characters."
}
]
}
]
},
"webcredentials": {
"apps": [ "ABCDE12345.com.example.app" ]
},
"appclips": {
"apps": ["ABCED12345.com.example.MyApp.Clip"]
}
}
3.2 Android的assetlinks.json文件
官方文档,上传到服务器的路径是https://www.example.net/.well-known/assetlinks.json
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.app",
"sha256_cert_fingerprints":
["YOUR_APP_CERTIFICATE_SHA256_FINGERPRINT"]
}
}]
-
relation
: 定义了与目标的关系类型。对于深度链接,通常使用 “delegate_permission/common.handle_all_urls” 来表示应用有权限处理所有相关的 URL。 -
target
: 描述了目标应用的详情。 -
namespace
: 对于 Android 应用,这里总是 “android_app”。 -
package_name
: 应用的包名,比如 “com.example.app”。 -
sha256_cert_fingerprints
: 应用签名证书的 SHA-256 指纹数组。你需要将 “YOUR_APP_CERTIFICATE_SHA256_FINGERPRINT” 替换为你的应用签名证书的实际 SHA-256 指纹。
确保替换 package_name 和 sha256_cert_fingerprints 中的值为你的实际应用信息。你可以使用如下命令来获取应用签名证书的 SHA-256 指纹:
keytool -list -v -keystore your_keystore_path -alias your_alias_name