设备锁屏时接收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
相关产品推荐
相关产品推荐

