You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

设备锁屏时接收VoIP通知无法按Deep Link跳转至对应页面

解决锁屏状态下VoIP通知深度链接跳转异常问题

1. 检查CallKeep通知触发后的主动跳转逻辑

锁屏状态下系统对应用唤醒有特殊限制,不能依赖系统通知的默认跳转逻辑,需在收到VoIP推送后主动触发深度链接:

  • 在VoIP推送回调中,调用displayIncomingCall显示来电界面后,手动触发深度链接导航,同时可结合AppState监听确保应用激活后执行跳转:
import { Linking, AppState } from 'react-native';
import RNCallKeep from 'react-native-callkeep';

const handleVoIPPush = async (payload) => {
  const { sessionName, displayName, roleType, hasVideo } = payload;
  // 显示来电界面
  RNCallKeep.displayIncomingCall('unique-uuid', displayName, displayName, 'video', false);
  
  // 监听应用激活状态,确保跳转在应用活跃时执行
  const appStateListener = AppState.addEventListener('change', (state) => {
    if (state === 'active') {
      Linking.openURL(`calling://Call/${sessionName}/${displayName}/${roleType}/${hasVideo}`);
      appStateListener.remove();
    }
  });
};

2. 优化react-navigation的linking配置

应用从终止状态被锁屏唤醒时,若深度链接解析失败会 fallback 到初始路由,需自定义初始URL获取逻辑:

import AsyncStorage from '@react-native-async-storage/async-storage';

const linking = {
  prefixes: ['calling://'],
  config: {
    screens: {
      Call: {
        path: 'Call/:sessionName/:displayName/:roleType/:hasVideo',
      },
      InitialScreen: {
        path: 'InitialScreen',
      },
    },
  },
  async getInitialURL() {
    const url = await Linking.getInitialURL();
    // 从存储中读取VoIP推送参数,构造深度链接(需在推送回调中先存储参数)
    const voipPayload = await AsyncStorage.getItem('latestVoIPPayload');
    if (voipPayload && !url) {
      const { sessionName, displayName, roleType, hasVideo } = JSON.parse(voipPayload);
      return `calling://Call/${sessionName}/${displayName}/${roleType}/${hasVideo}`;
    }
    return url;
  },
};

3. 配置iOS后台权限与通知回调

iOS锁屏下需确保应用有足够权限唤醒并处理导航:

  • 在Info.plist中添加后台模式权限:
<key>UIBackgroundModes</key>
<array>
  <string>voip</string>
  <string>remote-notification</string>
</array>
  • 在原生UNUserNotificationCenter回调中手动处理跳转,避免系统默认行为:
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler {
    NSDictionary *userInfo = response.notification.request.content.userInfo;
    NSString *urlStr = [NSString stringWithFormat:@"calling://Call/%@/%@/%@/%@", 
                        userInfo[@"sessionName"], 
                        userInfo[@"displayName"], 
                        userInfo[@"roleType"], 
                        userInfo[@"hasVideo"]];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlStr] options:@{} completionHandler:nil];
    completionHandler();
}

4. 调整Android通知的PendingIntent

Android需确保通知点击触发的是深度链接而非主Activity:

// 在FirebaseMessagingService的onMessageReceived中构建通知
Intent deepLinkIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("calling://Call/" + sessionName + "/" + displayName + "/" + roleType + "/" + hasVideo));
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, deepLinkIntent, PendingIntent.FLAG_IMMUTABLE);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "VOIP_CHANNEL")
        .setSmallIcon(R.drawable.ic_call)
        .setContentTitle(displayName)
        .setContentText("Incoming VoIP Call")
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .setContentIntent(pendingIntent)
        .setAutoCancel(true);

NotificationManagerCompat.from(this).notify(1, builder.build());

5. 排查深度链接解析日志

添加导航和链接监听,确认深度链接是否被正确接收与解析:

import { navigationContainerRef } from './path-to-navigation-ref';

// 监听导航状态变化
navigationContainerRef.current?.addListener('state', (e) => {
  console.log('Nav state:', e.data.state);
});

// 监听链接事件
Linking.addEventListener('url', (event) => {
  console.log('Received URL:', event.url);
});

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 23:42:10