HTML5如何传参启动本地APP?

99ANYc3cd6
预计阅读时长 35 分钟
位置: 首页 参数 正文
  1. HTML5 页面如何“告诉”系统要启动哪个 App
  2. App 如何“接收”并处理这些参数

下面我将分平台(iOS 和 Android)并结合通用方案来详细说明。

html5启动app传递参数
(图片来源网络,侵删)

核心原理

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启动app传递参数
(图片来源网络,侵删)

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+)

html5启动app传递参数
(图片来源网络,侵删)

SceneDelegate.swiftAppDelegate.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.javaProductDetailActivity.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,上面的链接可能会导致一个错误页面,为了提供更好的用户体验,必须有一个降级方案。

经典方案:延时跳转

  1. 用户点击链接后,先尝试通过 window.location 启动 App。
  2. 设置一个短暂的延时(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 接收 SceneDelegateAppDelegateopenURLContextsopenURL 方法中解析 在目标 Activity 的 onCreate 中从 Intent.getData() 获取并解析
降级方案 使用 JS 延时跳转,如果未打开则跳转 App Store 使用 JS 延时跳转,如果未打开则跳转应用宝 必须实现,是关键的最佳实践

通过以上步骤,你就可以构建一个健壮的 HTML5 页面,既能成功启动已安装的 App 并传递参数,也能在 App 未安装时优雅地引导用户去下载。

-- 展开阅读全文 --
头像
三星Level耳机拆解后有何玄机?
« 上一篇 今天
智能机器人由什么组成
下一篇 » 今天

相关文章

取消
微信二维码
支付宝二维码

最近发表

标签列表

目录[+]