> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.onesignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 深度链接

> 设置深度链接，通过通用链接、应用链接或自定义 URI 方案，将用户从推送通知、电子邮件和应用内消息引导至 Android 或 iOS 应用中的特定页面。

## 概览

深度链接在用户点击链接时将其引导至应用中的特定页面——无论链接来自电子邮件、SMS、网站、推送通知还是应用内消息。如果未安装应用程序，操作系统可以将用户重定向至应用商店或备用网页。

本指南涵盖：

* **深度链接类型**及各类型的适用场景
* Android 和 iOS 的**平台设置**
* 使用 OneSignal SDK 在应用中**处理深度链接**
* 推送、电子邮件和应用内消息的**渠道特定行为**

<Info>
  有关常规 URL 和链接配置（启动 URL、UTM 参数、动态 URL、链接跟踪），请参阅 [URL、链接和深度链接](./links)。
</Info>

***

## 前提条件

设置深度链接前，您需要：

* 已配置应用的 [OneSignal 账户](https://dashboard.onesignal.com)
* 已在移动应用中安装 [OneSignal SDK](./mobile-sdk-setup)
* 您控制的域名，通过 **HTTPS** 托管，用于通用链接或应用链接
* 访问应用源代码和构建配置的权限（iOS 使用 Xcode，Android 使用 Android Studio）

***

## 深度链接类型

深度链接有三种常见机制，各自的行为取决于应用是否已安装。

| 类型             | 平台            | 格式                            | 应用未安装时           |
| -------------- | ------------- | ----------------------------- | ---------------- |
| **通用链接**       | iOS 9+        | `https://yourdomain.com/path` | 在 Safari 中打开 URL |
| **应用链接**       | Android 6.0+  | `https://yourdomain.com/path` | 在浏览器中打开 URL      |
| **自定义 URI 方案** | iOS 和 Android | `myapp://path`                | 静默失败或显示错误        |

**建议：** 使用通用链接（iOS）和应用链接（Android）以获得最可靠的体验。它们使用标准 `https://` URL，可跨渠道（推送、电子邮件、SMS）使用，并在应用未安装时提供备用行为。自定义 URI 方案（`myapp://`）设置更简单，但不提供备用行为，且在某些场景下可能无法使用（例如，电子邮件客户端）。

<Warning>
  通用链接和应用链接需要在您的域名上托管验证文件。没有此文件，操作系统会将链接视为普通网页 URL。
</Warning>

***

## Android 设置（应用链接）

使用 Android Studio 的 [App Links Assistant](https://developer.android.com/training/app-links) 生成所需配置。

### 配置 intent 过滤器

向应处理深度链接的 Activity 添加 intent 过滤器：

```xml theme={null}
<activity android:name=".DeepLinkActivity" android:exported="true">
  <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" />
    <data android:scheme="https" android:host="yourdomain.com" />
  </intent-filter>
</activity>
```

### 处理传入 intent

```java theme={null}
Intent appLinkIntent = getIntent();
String appLinkAction = appLinkIntent.getAction();
Uri appLinkData = appLinkIntent.getData();
```

### 托管 Digital Asset Links 文件

使用 Android Studio 的 App Links Assistant 生成 `assetlinks.json` 文件，并将其托管在：

```
https://yourdomain.com/.well-known/assetlinks.json
```

有关完整文件格式和验证步骤，请参阅 Google 的 [Verify App Links](https://developer.android.com/training/app-links/verify-android-applinks) 文档。

***

## iOS 设置（通用链接）

Apple [通用链接](https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app)在用户点击匹配的 `https://` URL 时打开您的应用。对于确保已安装应用的简单用例，您也可以使用 [URL 方案](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app)。

### 启用 Associated Domains

1. 在 Xcode 中，选择您的 target → **Signing & Capabilities** → 添加 **Associated Domains**
2. 添加您的域名：`applinks:yourdomain.com`

### 在应用中处理通用链接

<CodeGroup>
  ```swift Swift theme={null}
  func application(_ application: UIApplication,
                   continue userActivity: NSUserActivity,
                   restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
          let url = userActivity.webpageURL else {
      return false
    }
    // Route to the correct screen based on the URL path
    return true
  }
  ```

  ```objectivec Objective-C theme={null}
  - (BOOL)application:(UIApplication *)application
      continueUserActivity:(NSUserActivity *)userActivity
      restorationHandler:(void (^)(NSArray *))restorationHandler {
    if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
      NSURL *url = userActivity.webpageURL;
      // Route to the correct screen based on the URL path
      return YES;
    }
    return NO;
  }
  ```
</CodeGroup>

### 托管 Apple App Site Association 文件

创建 `apple-app-site-association`（AASA）文件并将其托管在：

```
https://yourdomain.com/.well-known/apple-app-site-association
```

将 `TEAMID` 替换为您的 Apple Team ID，将 `com.example.app` 替换为您的 bundle identifier：

```json theme={null}
{
  "applinks": {
    "apps": [],
    "details": [{
      "appID": "TEAMID.com.example.app",
      "paths": ["/path/*", "/another-path"]
    }]
  }
}
```

有关完整规范，请参阅 Apple 的[支持关联域](https://developer.apple.com/documentation/xcode/supporting-associated-domains)文档。

### iOS 启动 URL 行为

OneSignal 的 iOS SDK 使用 `openURL` 处理启动 URL（`url` 属性）。这会导致链接先在浏览器中打开，然后重定向回应用——可能带来较差的用户体验。

要避免此问题，请使用以下方法之一：

1. 在 API 载荷中**使用 `data` 替代 `url`**，并在您的[推送通知点击监听器](./mobile-sdk-reference#addclicklistener-push)中处理深度链接
2. 通过在 `Info.plist` 中添加布尔值 `YES` 的 `OneSignal_suppress_launch_urls` 来**抑制启动 URL**，然后在点击监听器中处理所有导航

<Tip>
  推荐方法 1（使用 `data` + 点击监听器），因为它让您无需依赖操作系统解析 URL 即可完全控制导航。
</Tip>

***

## 使用 OneSignal SDK 处理深度链接

从 OneSignal 消息处理深度链接最可靠的方式是使用 SDK 的点击监听器，而不是依赖操作系统级别的链接解析。这让您可以完全控制应用中的导航。

### 推送通知点击监听器

使用 `addClickListener` 拦截通知点击，并根据深度链接 URL 或附加数据路由用户：

<CodeGroup>
  ```kotlin Kotlin theme={null}
  OneSignal.Notifications.addClickListener { event ->
    val url = event.notification.launchURL
    val data = event.notification.additionalData
    // Route to the correct screen based on url or data
  }
  ```

  ```swift Swift theme={null}
  class AppDelegate: UIResponder, UIApplicationDelegate, OSNotificationClickListener {
    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
      OneSignal.Notifications.addClickListener(self)
      return true
    }

    func onClick(event: OSNotificationClickEvent) {
      let url = event.notification.launchURL
      let data = event.notification.additionalData
      // Route to the correct screen based on url or data
    }
  }
  ```

  ```javascript React Native theme={null}
  OneSignal.Notifications.addEventListener('click', (event) => {
    const url = event.notification.launchURL;
    const data = event.notification.additionalData;
    // Route to the correct screen based on url or data
  });
  ```

  ```dart Flutter theme={null}
  OneSignal.Notifications.addClickListener((event) {
    final url = event.notification.launchUrl;
    final data = event.notification.additionalData;
    // Route to the correct screen based on url or data
  });
  ```

  ```csharp Unity (C#) theme={null}
  OneSignal.Notifications.Clicked += (sender, e) => {
    var url = e.Notification.LaunchURL;
    var data = e.Notification.AdditionalData;
    // Route to the correct screen based on url or data
  };
  ```
</CodeGroup>

有关包含 Java、Objective-C 和 Cordova/Ionic 的完整 API 参考，请参阅 [`addClickListener()` 推送](./mobile-sdk-reference#addclicklistener-push)。

### 应用内消息点击监听器

使用应用内消息点击监听器处理来自应用内消息按钮和操作的深度链接：

<CodeGroup>
  ```kotlin Kotlin theme={null}
  OneSignal.InAppMessages.addClickListener { event ->
    val actionId = event.result.actionId
    // Route based on the action ID (your deep link URI)
  }
  ```

  ```swift Swift theme={null}
  func onClick(event: OSInAppMessageClickEvent) {
    let actionId = event.result.actionId
    // Route based on the action ID (your deep link URI)
  }
  ```

  ```javascript React Native theme={null}
  OneSignal.InAppMessages.addEventListener('click', (event) => {
    const actionId = event.result.actionId;
    // Route based on the action ID (your deep link URI)
  });
  ```

  ```dart Flutter theme={null}
  OneSignal.InAppMessages.addClickListener((event) {
    final actionId = event.result.actionId;
    // Route based on the action ID (your deep link URI)
  });
  ```
</CodeGroup>

有关完整 API 参考，请参阅 [`addClickListener()` 应用内](./mobile-sdk-reference#addclicklistener-in-app)。

***

## 推送通知

通过以下两种方式之一包含深度链接：

| 方法           | API 属性                   | 行为                                   |
| ------------ | ------------------------ | ------------------------------------ |
| **启动 URL**   | `url`（或仅限移动端的 `app_url`） | 操作系统直接打开 URL。在 iOS 上，除非抑制，否则会先打开浏览器。 |
| **附加数据**（推荐） | `data`                   | URL 传递至您的点击监听器，您完全控制导航。              |

### 平台行为

* **Android**：通过应用链接直接打开匹配的 Activity
* **iOS**：打开 Safari，然后打开应用（除非您[抑制启动 URL](#ios-启动-url-行为)并在点击监听器中处理导航）

有关 `url`、`web_url` 和 `app_url` 定向的详细信息，请参阅 [URL、链接和深度链接](./links)。

***

## 电子邮件

默认情况下，OneSignal 会重写电子邮件链接以进行点击跟踪。这会更改 URL，从而破坏深度链接，因为操作系统不再将域名识别为与您的应用关联域匹配。

### 在电子邮件中启用深度链接

要保留深度链接，请使用以下方法之一禁用点击跟踪：

* **仪表板**：在电子邮件编辑器中取消勾选 **Track link clicks**
* **API**：设置 `disable_email_click_tracking: true`
* **单链接**：在锚标记中添加 `disable-tracking=true` 属性（`<a href="https://yourdomain.com/path" disable-tracking=true>…</a>`），禁用单个链接的跟踪，同时为其他链接保持启用状态

<Frame caption="电子邮件编辑器中已禁用 Track link clicks。">
  <img src="https://mintcdn.com/onesignal/jBdBk5XvQR5eKOks/images/docs/787e21d-Screenshot_2024-05-29_at_2.21.43_PM.png?fit=max&auto=format&n=jBdBk5XvQR5eKOks&q=85&s=f7e1079f4860ecf34fd95375a4332573" alt="OneSignal 电子邮件编辑器中 Track link clicks 复选框未勾选" width="1756" height="492" data-path="images/docs/787e21d-Screenshot_2024-05-29_at_2.21.43_PM.png" />
</Frame>

<Warning>
  禁用点击跟踪意味着您将失去[电子邮件报告](./email-message-reports)中的点击指标。考虑对非深度链接 URL 使用单链接跟踪排除以保留分析数据。
</Warning>

### 电子邮件深度链接行为

| 场景                          | 结果                 |
| --------------------------- | ------------------ |
| iOS + Safari + 通用链接 + 跟踪已禁用 | 直接打开应用             |
| iOS + Safari + 通用链接 + 跟踪已启用 | 打开 Safari，提示打开应用   |
| iOS + 非 Safari 邮件客户端 + 通用链接 | 应用未安装时打开 App Store |
| Android + 应用链接 + 跟踪已禁用      | 直接打开应用             |
| Android + 应用链接 + 跟踪已启用      | 先打开浏览器，然后打开应用      |

***

## 应用内消息

应用内消息中的深度链接使用点击监听器模式。您在消息编辑器中设置自定义操作标识符，然后在应用代码中处理它。

### 拖放编辑器

1. 添加按钮或可点击元素
2. 将点击操作设置为 [Custom Action ID](./iam-click-actions#custom-action-id)
3. 将您的深度链接 URI 输入为 **Action Name**（例如，`https://yourdomain.com/promo` 或 `myapp://promo`）

### HTML 编辑器

在应用内 JS 库中使用 [`openUrl`](./in-app-message-api#click-name) 方法从自定义 HTML 触发深度链接。

### 处理点击

使用[应用内消息点击监听器](#应用内消息点击监听器)拦截操作并在您的应用中引导用户。

***

## 测试深度链接

### Android

使用 `adb` 在不发送通知的情况下测试应用链接：

```bash theme={null}
adb shell am start -a android.intent.action.VIEW \
  -d "https://yourdomain.com/path" \
  com.your.package
```

验证您的 `assetlinks.json` 是否可访问：

```bash theme={null}
curl -I https://yourdomain.com/.well-known/assetlinks.json
```

### iOS

使用 Apple 的[关联域验证工具](https://search.developer.apple.com/appsearch-validation-tool/)验证您的 AASA 文件。您也可以通过以下方式测试通用链接：

1. 将链接粘贴到备忘录应用中
2. 长按链接确认"在 \[App] 中打开"选项出现
3. 点击链接验证其是否打开您的应用

<Note>
  通用链接在直接输入 Safari 地址栏时不起作用——必须从其他应用（备忘录、邮件、信息等）中点击。
</Note>

### OneSignal 测试消息

1. 从 OneSignal 仪表板发送测试推送，将深度链接 URL 作为启动 URL 或放入附加数据中
2. 验证通知是否在应用中打开正确的页面
3. 检查您的点击监听器日志，确认已接收到 URL 或数据

***

## 故障排除

### iOS 深度链接打开 Safari 而非应用

这是最常见的问题。可能原因：

* **AASA 文件未正确托管** — 验证其位于 `https://yourdomain.com/.well-known/apple-app-site-association`，`Content-Type: application/json` 且无重定向
* **未配置 Associated Domains** — 检查 Xcode → **Signing & Capabilities** → **Associated Domains** 是否包含 `applinks:yourdomain.com`
* **启动 URL 行为** — OneSignal 的 iOS SDK 对 `url` 属性使用 `openURL`，会触发浏览器优先行为。改用 `data` + 点击监听器或[抑制启动 URL](#ios-启动-url-行为)
* **在 Safari 中测试** — 通用链接不会从 Safari 地址栏激活，请从备忘录、邮件或其他应用测试。

### Android 深度链接打开浏览器

* **缺少 `autoVerify`** — 确保您的 intent 过滤器包含 `android:autoVerify="true"`
* **未找到 `assetlinks.json`** — 验证文件位于 `https://yourdomain.com/.well-known/assetlinks.json` 且返回 HTTP 200
* **SHA256 指纹不匹配** — `assetlinks.json` 中的指纹必须与应用的签名证书匹配。调试版和发布版使用不同的证书。

### 深度链接在推送中有效但在电子邮件中无效

电子邮件点击跟踪会重写 URL，破坏域名验证。对包含深度链接的电子邮件[禁用点击跟踪](#在电子邮件中启用深度链接)。

### 收到深度链接但应用未导航

* 验证您的点击监听器在应用生命周期早期注册（例如，在 `Application.onCreate()` 或 `AppDelegate.didFinishLaunchingWithOptions` 中）
* 检查 URL 或 action ID 是否与您的路由逻辑期望的相符
* 在 iOS 上，确认您没有在未抑制启动 URL 的情况下依赖 `url`——浏览器可能在监听器触发前消耗链接

***

## 常见问题

### 如果未安装应用会发生什么？

使用通用链接（iOS）时，URL 在 Safari 中作为普通网页打开。使用应用链接（Android）时，URL 在默认浏览器中打开。在这两种情况下，您可以将网页配置为重定向至相应的应用商店。自定义 URI 方案（`myapp://`）在未安装应用时会静默失败或显示错误。

### 深度链接应使用启动 URL 还是附加数据？

移动深度链接推荐使用附加数据（`data`），因为它通过点击监听器让您完全控制导航。启动 URL（`url`）更简单，但在 iOS 上存在限制（浏览器重定向），且不允许自定义路由逻辑。

### 我可以用用户数据个性化深度链接吗？

可以。使用带有 Liquid 语法的[动态 URL](./links#dynamic-urls) 将用户属性、标签或自定义数据注入深度链接 URL。例如：`https://yourdomain.com/profile/{{subscription.external_id}}`。

### 我可以使用自定义 URI 方案的深度链接吗？

可以。将您的自定义方案（例如 `myapp://screen`）设置为启动 URL 或附加数据值。自定义方案适用于推送和应用内消息，但在电子邮件客户端中可能不起作用。如果未安装应用，它们也不提供备用方案。

### 深度链接是否适用于 OneSignal Journeys？

可以。在 Journey 中配置消息步骤时，将启动 URL 或附加数据设置为您的深度链接。其行为与独立推送或应用内消息相同。

***

<Columns cols={2}>
  <Card title="URL、链接和深度链接" icon="link" href="./links">
    启动 URL、UTM 参数、动态 URL 和链接跟踪配置。
  </Card>

  <Card title="移动 SDK 参考" icon="code" href="./mobile-sdk-reference">
    点击监听器和通知事件处理的完整 API 参考。
  </Card>

  <Card title="应用内点击操作" icon="hand-pointer" href="./iam-click-actions">
    配置应用内消息按钮和元素的点击操作。
  </Card>

  <Card title="移动推送设置" icon="mobile" href="./mobile-push-setup">
    Android 和 iOS 的平台专用推送通知设置。
  </Card>
</Columns>
