You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何检测推送通知点击并实现应用不同启动页跳转?

嘿,这个需求我在项目里折腾过好多次,给你分Android和iOS两边拆解下具体实现思路,都是实际跑通的靠谱方案~

Android 端实现步骤
  • 首先给你要跳转的指定页面配置Deep Link,或者在Manifest里加特定的Intent Filter。比如你要跳转到TargetHomeActivity,就在它的Manifest标签里这么写:
<activity
    android:name=".pages.TargetHomeActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- 自定义一个专属的scheme,比如和你应用包名挂钩的 -->
        <data android:scheme="myapp" android:host="targethome" />
    </intent-filter>
</activity>
  • 然后发送推送的时候,在payload里带上这个Deep Link的信息。比如用FCM的话,payload里加data字段:
{
  "data": {
    "deep_link": "myapp://targethome",
    "message": "新消息提醒"
  },
  "to": "用户的设备Token"
}
  • 接下来在推送接收服务里解析这个链接,启动目标页面。比如在FirebaseMessagingServiceonMessageReceived方法里:
override fun onMessageReceived(remoteMessage: RemoteMessage) {
    remoteMessage.data["deep_link"]?.let { deepLink ->
        val intent = Intent(Intent.ACTION_VIEW, Uri.parse(deepLink))
        // 加这两个flag确保启动方式正确,避免重复栈
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
        applicationContext.startActivity(intent)
    }
}

⚠️ 重点提醒:如果应用是被后台杀死的状态,点击推送会先启动默认的Launcher Activity,这时候得在Launcher Activity的onCreate里检查Intent的data,再跳转:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    intent.data?.let { uri ->
        if (uri.toString() == "myapp://targethome") {
            startActivity(Intent(this, TargetHomeActivity::class.java))
            finish() // 关闭默认首页,避免返回时回到它
        }
    }
}
iOS 端实现步骤
  • 先配置自定义URL Scheme(或者更安全的Universal Links,这里先讲简单的Scheme方式)。打开Xcode,进入项目设置 -> Targets -> Info -> URL Types,新增一个URL Scheme,比如myapp
  • 发送APNs推送时,在payload里加自定义字段标记目标页面:
{
  "aps": {
    "alert": "你有新消息",
    "sound": "default"
  },
  "target_page": "TargetHome"
}
  • 然后处理推送点击事件,分两种情况:
    1. AppDelegate的老版本写法:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // 检查是不是通过推送启动的应用
    if let remoteNotification = launchOptions?[.remoteNotification] as? [String: Any] {
        handlePushJump(remoteNotification)
    }
    return true
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    handlePushJump(userInfo)
    completionHandler(.newData)
}

private func handlePushJump(_ userInfo: [AnyHashable: Any]) {
    guard let target = userInfo["target_page"] as? String, target == "TargetHome" else { return }
    // 替换根控制器为目标页面
    if let window = UIApplication.shared.windows.first {
        let targetVC = TargetHomeViewController()
        window.rootViewController = UINavigationController(rootViewController: targetVC)
        window.makeKeyAndVisible()
    }
}
  1. iOS 13+用SceneDelegate的写法:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // 检查推送启动参数
    if let remoteNotification = connectionOptions.remoteNotification {
        handlePushJump(remoteNotification.request.content.userInfo)
    }
}

func scene(_ scene: UIScene, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
    handlePushJump(userInfo)
}

private func handlePushJump(_ userInfo: [AnyHashable: Any]) {
    guard let target = userInfo["target_page"] as? String, target == "TargetHome" else { return }
    guard let windowScene = scene as? UIWindowScene, let window = windowScene.windows.first else { return }
    let targetVC = TargetHomeViewController()
    window.rootViewController = UINavigationController(rootViewController: targetVC)
    window.makeKeyAndVisible()
}
通用注意事项
  • 不管哪端,都要做好空值判断,避免解析payload时出现崩溃。
  • Android端要注意exported="true"BROWSABLE分类的配置,不然系统会拦截Intent。
  • iOS如果追求更高安全性,建议用Universal Links替代自定义Scheme,避免被其他应用劫持,不过配置需要在开发者后台和服务器上操作,稍微繁琐点。
  • 测试时一定要覆盖三种状态:应用前台、后台运行、后台完全杀死,确保每种情况跳转都正常。

内容的提问来源于stack exchange,提问作者Kirill

火山引擎 最新活动