- HTML5 页面如何“告诉”系统要启动哪个 App。
- App 如何“接收”并处理这些参数。
下面我将分平台(iOS 和 Android)并结合通用方案来详细说明。

核心原理
HTML5 页面本身不能直接“启动” App,它只能通过一个链接,请求系统去打开一个特定的 URL Scheme(iOS/Android)或 Intent URL(Android),这个链接的格式是 协议名://参数,操作系统会检查已安装的 App,看哪个 App 注册了处理这个协议,然后启动它并传递参数。
iOS 平台实现
在 iOS 中,我们使用 URL Scheme。
定义 URL Scheme
在你的 iOS App 项目中(例如使用 Swift 或 Objective-C),你需要配置一个 URL Scheme,这通常在 Info.plist 文件中完成。
- 打开
Info.plist。 - 添加一个
URL types键(类型为 Array)。 - 在
URL types数组中添加一个Item 0(类型为 Dictionary)。 - 在
Item 0中添加一个URL Schemes键(类型为 Array)。 - 在
URL Schemes数组中添加你的自定义 Scheme,myawesomeapp。
配置好后,你的 App 就能响应 myawesomeapp:// 开头的链接了。

HTML5 页面中的链接
在 HTML 中,你只需要创建一个普通的 <a> 标签,其 href 属性设置为你的 URL Scheme。
<!-- 基础链接 --> <a href="myawesomeapp://">打开我的 App</a> <!-- 传递参数 --> <!-- 参数通过 '?' 和 '&' 连接,格式类似 URL 查询字符串 --> <a href="myawesomeapp://product?id=123&name=超级手机">查看商品详情</a> <!-- 传递更复杂的参数(如 JSON) --> <a href="myawesomeapp://user/profile?data=%7B%22userId%22%3A%221001%22%2C%22username%22%3A%22John%22%7D"> 查看用户资料 </a>
注意:如果参数包含特殊字符(如 , , ),需要进行 URL 编码,上面的 data 参数就是经过编码的 JSON 字符串 {"userId":"1001","username":"John"},你可以使用 JavaScript 的 encodeURIComponent() 函数来处理。
iOS App 接收参数
当 App 被链接启动时,系统会将 URL 传递给 App 的代理方法,你需要在这个方法中解析 URL 并提取参数。
Swift (iOS 9+)

在 SceneDelegate.swift 或 AppDelegate.swift 中:
import UIKit
// iOS 13+ 使用 SceneDelegate
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else { return }
// 1. 检查 URL Scheme 是否匹配
if url.scheme == "myawesomeapp" {
// 2. 解析路径和参数
let host = url.host // 获取 host,"product" 或 "user/profile"
let queryItems = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems
var params: [String: String] = [:]
queryItems?.forEach { item in
params[item.name] = item.value
}
print("App 启动,Host: \(host), 参数: \(params)")
// 3. 根据参数执行相应操作
if host == "product" {
let productId = params["id"]
print("准备展示商品 ID: \(productId ?? "无")")
// ... 跳转到商品详情页
} else if host == "user/profile" {
let userData = params["data"]
print("准备展示用户数据: \(userData ?? "无")")
// ... 解析 JSON 并跳转到用户页
}
}
}
}
Objective-C
// 在 AppDelegate.m 中
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
if ([[url scheme] isEqualToString:@"myawesomeapp"]) {
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
NSArray *queryItems = components.queryItems;
NSMutableDictionary *params = [NSMutableDictionary dictionary];
for (NSURLQueryItem *item in queryItems) {
params[item.name] = item.value;
}
NSLog(@"App 启动,Host: %@, 参数: %@", url.host, params);
// ... 根据参数执行操作
}
return YES;
}
Android 平台实现
在 Android 中,我们使用 Intent URLs,它比 iOS 的 URL Scheme 更强大,也更复杂一些。
配置 AndroidManifest.xml
在 App 的 AndroidManifest.xml 文件中,为需要接收 Intent 的 Activity 声明一个 <intent-filter>。
<activity android:name=".ProductDetailActivity">
<!-- 其他 intent-filter,如 LAUNCHER -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myawesomeapp" />
</intent-filter>
</activity>
<action android:name="android.intent.action.VIEW": 表示这个 Activity 可以处理“查看”动作。<category android:name="android.intent.category.BROWSABLE": 非常重要,表示这个 Activity 可以从浏览器或网页链接启动。<data android:scheme="myawesomeapp": 定义了 App 的 Scheme,与 iOS 类似。
HTML5 页面中的链接
HTML 部分与 iOS 完全相同,因为标准就是标准。
<a href="myawesomeapp://product?id=123&name=超级手机">查看商品详情</a>
Android App 接收参数
在对应的 Activity(这里是 ProductDetailActivity.java 或 ProductDetailActivity.kt)中,从 Intent 对象中获取数据。
Kotlin
import android.net.Uri
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_product_detail.*
class ProductDetailActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_product_detail)
// 从启动的 Intent 中获取数据
val intent = intent
val data: Uri? = intent?.data
if (data != null && data.scheme == "myawesomeapp") {
// 解析参数
val productId = data.getQueryParameter("id")
val productName = data.getQueryParameter("name")
// 使用参数
text_view.text = "商品ID: $productId\n商品名称: $productName"
Log.d("MyApp", "接收到参数: id=$productId, name=$productName")
}
}
}
Java
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.TextView;
public class ProductDetailActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_detail);
TextView textView = findViewById(R.id.text_view);
// 从启动的 Intent 中获取数据
Intent intent = getIntent();
Uri data = intent.getData();
if (data != null && "myawesomeapp".equals(data.getScheme())) {
// 解析参数
String productId = data.getQueryParameter("id");
String productName = data.getQueryParameter("name");
// 使用参数
textView.setText("商品ID: " + productId + "\n商品名称: " + productName);
Log.d("MyApp", "接收到参数: id=" + productId + ", name=" + productName);
}
}
}
通用方案与最佳实践
由于 iOS 和 Android 的实现方式不同,一个 HTML5 页面需要能够兼容两者。
使用 JavaScript 检测平台并构建正确的链接
你可以编写一个 JS 函数,根据设备类型生成不同的链接。
function openApp() {
const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
const android = /android/i.test(navigator.userAgent);
if (iOS) {
// iOS 的链接
window.location.href = "myawesomeapp://product?id=123";
} else if (android) {
// Android 的链接
window.location.href = "myawesomeapp://product?id=123";
} else {
// PC 端或其他设备,可以跳转到 App Store 或应用宝
alert("请在手机上访问以打开 App");
// window.location.href = "https://apps.apple.com/app/your-app-id";
}
}
// 在页面加载后尝试打开 App
window.onload = function() {
openApp();
};
降级方案:App 未安装怎么办?
如果用户没有安装你的 App,上面的链接可能会导致一个错误页面,为了提供更好的用户体验,必须有一个降级方案。
经典方案:延时跳转
- 用户点击链接后,先尝试通过
window.location启动 App。 - 设置一个短暂的延时(500ms),App 没有成功启动(即页面没有离开),则自动跳转到 App 下载页面(如 App Store 或应用宝)。
<a href="javascript:void(0);" id="openAppBtn" onclick="tryOpenApp()">打开我的 App</a>
<script>
function tryOpenApp() {
const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
const android = /android/i.test(navigator.userAgent);
let appUrl, downloadUrl;
if (iOS) {
appUrl = "myawesomeapp://product?id=123";
downloadUrl = "https://apps.apple.com/app/your-app-id"; // 替换成你的 App Store 链接
} else if (android) {
appUrl = "myawesomeapp://product?id=123";
downloadUrl = "https://sj.qq.com/myapp/detail.htm?apkName=com.your.package.name"; // 替换成你的应用宝链接
} else {
alert("请在手机上访问以打开 App");
return;
}
// 先尝试打开 App
window.location.href = appUrl;
// 设置一个定时器,500ms 后还在当前页面,说明 App 未安装
setTimeout(function() {
// 检查 location.href 是否改变,如果没有,则跳转下载页
if (window.location.href === appUrl) {
window.location.href = downloadUrl;
}
}, 500);
}
</script>
注意:这种方案不是 100% 可靠的,因为 App 启动可能需要比 500ms 更长的时间,但通常在用户体验和可靠性之间取得了不错的平衡。
| 步骤 | iOS (URL Scheme) | Android (Intent URL) | 通用方案 |
|---|---|---|---|
| App 配置 | 在 Info.plist 中注册 URL types |
在 AndroidManifest.xml 中为 Activity 添加 <intent-filter> |
无 |
| HTML 链接 | <a href="myapp://param"> |
<a href="myapp://param"> |
使用 JS 动态生成链接 |
| App 接收 | 在 SceneDelegate 或 AppDelegate 的 openURLContexts 或 openURL 方法中解析 |
在目标 Activity 的 onCreate 中从 Intent.getData() 获取并解析 |
无 |
| 降级方案 | 使用 JS 延时跳转,如果未打开则跳转 App Store | 使用 JS 延时跳转,如果未打开则跳转应用宝 | 必须实现,是关键的最佳实践 |
通过以上步骤,你就可以构建一个健壮的 HTML5 页面,既能成功启动已安装的 App 并传递参数,也能在 App 未安装时优雅地引导用户去下载。
