adstage
行動 SDK深層連結

Unity

AdStage DeepLink 整合指南(Unity)

目錄

  1. 概述
  2. 專案設定
  3. Unity 專案設定
  4. Android 平台設定
  5. iOS 平台設定
  6. 建立深層連結
  7. 疑難排解

概述

AdStage DeepLink SDK for Unity 提供以下功能:

  • 即時深層連結:透過 URL Scheme、App Link/Universal Links 即時處理
  • 延遲深層連結:應用程式安裝後首次啟動時自動還原
  • 動態深層連結建立:透過伺服器 API 建立可追蹤的連結
  • 歸因追蹤:以 UTM 參數為基礎的行銷分析
  • 跨平台:Android/iOS 使用相同 API

支援的深層連結類型

  • URL Scheme: myapp://promo/summer
  • Android App Links: https://go.myapp.com/abc123
  • iOS Universal Links: https://go.myapp.com/abc123
  • 延遲深層連結:未安裝應用程式時 商店 → 安裝 → 啟動應用程式時還原

專案設定

1. 安裝套件

透過 Package Manager 安裝:

Window → Package Manager → + → Add package from git URL
https://github.com/nbase-io/NBase-SDK-Unity.git?path=/AdStageSDK-Package

或直接編輯 manifest.json:

{
  "dependencies": {
    "com.nbase.adstage": "https://github.com/nbase-io/NBase-SDK-Unity.git?path=/AdStageSDK-Package#3.0.0"
  }
}

2. 必要相依套件

安裝套件時會自動包含:

  • Newtonsoft.Json:JSON 序列化
  • Native 外掛:iOS/Android 橋接

Unity 專案設定

1. SDK 初始化

using AdStageSDK;
using UnityEngine;
 
public class AdStageInitializer : MonoBehaviour
{
    void Start()
    {
        // AdStage 初始化
        AdStage.Initialize(
            apiKey: "your-api-key-here"
        );
        
        // 註冊深層連結監聽器
        SetupDeepLinkListener();
        
        Debug.Log("✅ AdStage SDK 初始化完成");
    }
    
    private void SetupDeepLinkListener()
    {
        AdStage.SetDeepLinkListener(
            onDeepLink: (data) => {
                Debug.Log($"✅ 收到深層連結: {data.shortPath}");
                if (data.parameters != null && data.parameters.Count > 0)
                {
                    foreach (var param in data.parameters)
                    {
                        Debug.Log($"  - {param.Key}: {param.Value}");
                    }
                }
            },
            onError: (error) => {
                Debug.LogError($"❌ 深層連結失敗: {error}");
            }
        );
    }
}

Android 平台設定

1. AndroidManifest.xml 設定

建立 Assets/Plugins/Android/AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    
    <application
        android:allowBackup="true"
        android:icon="@drawable/app_icon"
        android:label="@string/app_name">
        
        <activity
            android:name="com.unity3d.player.UnityPlayerActivity"
            android:theme="@style/UnityThemeSelector"
            android:screenOrientation="fullSensor"
            android:launchMode="singleTask"
            android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density"
            android:exported="true">
            
            <!-- 預設啟動器 -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            
            <!-- URL Scheme 深層連結 -->
            <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="your_app_scheme" />
            </intent-filter>
        </activity>
        
    </application>
</manifest>

2. launchMode 重要事項

android:launchMode="singleTask"
  • ✅ singleTask:重複使用既有的 Activity(建議)
  • ⚠️ singleTop:僅在位於堆疊最上層時才重複使用
  • ❌ standard:每次都建立新執行個體(會產生深層連結重複)

iOS 平台設定

1. 在 Xcode 中設定 Info.plist

<!-- URL Scheme 設定 -->
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>com.example.myapp</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>your_ios_scheme</string>
        </array>
    </dict>
</array>

建立深層連結

public async void CreateDetailedDeepLink()
{
    try
    {
         var builder = new DeepLinkBuilder("Unity Test Link")
             .SetDescription("Unity SDK 測試")
             .SetCampaign("unity_test")
             .SetChannel("app_channel")
             .SetRedirectType(RedirectType.APP)
             .SetAndroidConfig("your.package.name","your_aos_scheme", "https://yourdomain.com")
             .SetIOSConfig("your.appstoreid", "your_ios_scheme", "https://yourdomain.com")
             .SetWebConfig("https://yourdomain.com")
             .AddParameter("user_id", "value")
             .AddParameter("test", "true");
        
         AdStage.CreateDeeplink(
             builder: builder,
             onSuccess: (shortUrl) =>
             {
                 InAppLog("✅ 深層連結建立成功!");
                 InAppLog($"  URL: {shortUrl}");
             },
             onError: (error) =>
             {
                 InAppLog($"❌ 深層連結建立失敗: {error}");
             }
         );
        
    }
    catch (System.Exception e)
    {
        Debug.LogError($"❌ 錯誤: {e.Message}");
    }
}

RedirectType 說明

public enum RedirectType
{
    STORE,  // 前往商店
    
    APP,    // 未安裝應用程式時 → 前往商店
            // 已安裝應用程式時 → 啟動應用程式(即時深層連結)
    
    WEB     // 一律前往網頁 URL
            // 與應用程式是否安裝無關
}

Android 深層連結流程:

使用者點擊深層連結 (myapp://abc123)
  ↓
Android System 建立 Intent
  ↓
UnityPlayerActivity 啟動/恢復
  ↓
AdStageLifecyclePlugin.onActivityCreated/Resumed()
  ↓
AdStageUnityWrapper.handleIntent(intent)
  ↓
AdStage.handleIntent(context, intent)
  ↓
DeeplinkHandler.handleIntent()
  ├─ 擷取 URI: myapp://abc123
  ├─ 解析 shortPath: abc123
  ├─ 呼叫 API: GET /deeplinks/abc123
  └─ DeeplinkListener.onDeeplinkReceived()
       ↓
UnitySendMessage("AdStageCallbackReceiver", "OnDeepLinkReceived", json)
  ↓
AdStageCallbackReceiver.OnDeepLinkReceived(json)
  ↓
呼叫使用者回呼

iOS 深層連結流程:

使用者點擊深層連結 (myapp://abc123)
  ↓
iOS System 傳遞 URL
  ↓
AdStageUnityAppController.application:openURL: 或
AdStageUnityAppController.application:continueUserActivity:
  ↓
AdStageUnityBridge.AdStageIOS_HandleDeepLink(url)
  ↓
AdStageManager.shared.handleDeepLink(url)
  ↓
DeepLinkManager.handleDeepLink()
  ├─ 解析 URL
  ├─ 呼叫 API
  └─ DeepLinkDelegate.onDeepLinkReceived()
       ↓
UnitySendMessage("AdStageCallbackReceiver", "OnDeepLinkReceived", json)
  ↓
AdStageCallbackReceiver.OnDeepLinkReceived(json)
  ↓
呼叫使用者回呼

疑難排解

1. 深層連結在 Unity Editor 中無法運作

這是正常行為! AdStage SDK 僅在行動平台(Android/iOS)上運作。 在 Editor 中呼叫 AdStage.Initialize() 時 IsInitialized() 會回傳 false, 深層連結回呼僅能在實機上接收。

確認方法:

#if UNITY_EDITOR
Debug.Log("📊 [Editor Mode] 深層連結僅在實機上運作");
#endif

測試方法: 將實際的 Android/iOS 建置安裝到裝置後,用下方疑難排解中的 Intent / URL Scheme 測試(第 2 項、第 3 項)確認深層連結的接收。

2. Android 建置後收不到深層連結

檢查清單:

  1. 確認 AndroidManifest.xml

    • 確認 android:launchMode="singleTask" 設定
    • 確認 Intent Filter 是否正確
  2. 確認 adb logcat

adb logcat | grep -i adstage
  1. Intent 測試
# URL Scheme 測試
adb shell am start -W -a android.intent.action.VIEW -d "myapp://promo/summer" com.example.myapp
 
# HTTPS App Link 測試
adb shell am start -W -a android.intent.action.VIEW -d "https://go.myapp.com/abc123" com.example.myapp

3. iOS 建置後收不到深層連結

檢查清單:

  1. 確認 Info.plist

    • CFBundleURLTypes 設定
    • Associated Domains 設定
  2. Universal Links 驗證

# 確認 Apple App Site Association 檔案
curl https://go.myapp.com/.well-known/apple-app-site-association
  1. 確認 Xcode Console
    • 確認錯誤訊息
    • 確認深層連結接收記錄

4. 延遲深層連結未還原

Android:

# 確認 Install Referrer
adb shell dumpsys package com.example.myapp | grep -i referrer

解決方法:

  1. 在 AndroidManifest.xml 中新增權限:
<uses-permission android:name="com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE" />
  1. 在 Play Console 中設定 Install Referrer

5. 深層連結被重複呼叫

原因: 使用了 launchMode="standard"

解決:

<!-- AndroidManifest.xml -->
android:launchMode="singleTask"

6. Unity 2021+ IL2CPP 建置錯誤

問題:

TypeLoadException: Could not load type 'AdStageSDK.DeepLinkData'

解決: 建立 link.xml 檔案

Assets/link.xml:

<linker>
    <assembly fullname="AdStageSDK" preserve="all"/>
    <assembly fullname="AdStageSDK.Models" preserve="all"/>
    <assembly fullname="Newtonsoft.Json" preserve="all"/>
</linker>

7. JSON 序列化錯誤

問題:

JsonSerializationException: Error converting value

解決:

// Parameters 使用 Dictionary<string, object>
var parameters = new Dictionary<string, object>
{
    { "key1", "value1" },
    { "key2", 123 },  // int 也可以
    { "key3", true }  // bool 也可以
};

確認方法:

# Digital Asset Links 驗證
curl https://go.myapp.com/.well-known/assetlinks.json

檢查清單:

  • ✅ 使用 HTTPS
  • ✅ Content-Type: application/json
  • ✅ 確認 SHA256 指紋是否正確
  • ✅ 套件名稱一致

FAQ

Q: 可以在 Unity Editor 中測試深層連結嗎?
A: 不行。SDK 僅在行動平台上運作,因此深層連結測試必須在實際的 Android/iOS 裝置上進行。

Q: Android 與 iOS 可以使用相同的深層連結 URL 嗎?
A: 可以,URL Scheme 與 HTTPS 連結都可以相同地使用。

Q: 延遲深層連結是如何運作的?
A: 安裝應用程式 → 首次啟動 → 查詢 Install Referrer → 還原已儲存的深層連結 → 呼叫回呼

Q: 深層連結的參數個數有限制嗎?
A: 伺服器沒有限制,但請考量 URL 長度限制(約 2000 個字元)。

Q: 離線狀態下深層連結也能運作嗎?
A: 即時深層連結需要網路。延遲深層連結會被快取,離線狀態下也能還原。

Q: 在 Unity WebGL 上也能運作嗎?
A: WebGL 無法使用原生外掛,因此不支援。在 Web 環境中請直接解析 URL 參數。


支援

聯絡方式:


© 2025 NBase. All rights reserved.

目錄