React Native Expo后台通知任务前后台正常,被杀进程后失效(集成CallKeep)
应用被终止时如何用Expo + CallKeep触发来电通知?
问题背景
我正在开发React Native Expo项目,使用expo-notifications、expo-task-manager和react-native-callkeep处理来电通知,目标是应用被终止(被杀/关闭)时仍能显示来电界面。
当前实现代码:
import { Component } from 'react'; import Routes from "./Navigations/Route"; import * as React from 'react'; import { registerRootComponent } from 'expo'; import { Provider } from 'react-redux'; import store from './store/store'; import * as TaskManager from "expo-task-manager"; import * as Notifications from "expo-notifications"; import CallKeep from 'react-native-callkeep'; const BACKGROUND_NOTIFICATION_TASK = "BACKGROUND-NOTIFICATION-TASK"; TaskManager.defineTask( BACKGROUND_NOTIFICATION_TASK, ({ data, error, executionInfo }) => { if (error) { console.log("Error occurred:", error); } if (data) { console.log("Data received:", data); let res = JSON.parse(data.notification.data.body); CallKeep.displayIncomingCall(res.uuid, "9999999999", res.instructorName, 'generic', true); } } ); Notifications.registerTaskAsync(BACKGROUND_NOTIFICATION_TASK); export default class App extends Component { componentDidMount() { // Any other initialization } render() { return ( <Provider store={store}> <Routes /> </Provider> ); } }; registerRootComponent(App);
当前状态:应用前台、后台状态下运行正常,收到纯数据通知时会触发后台任务,CallKeep可成功显示来电界面。通知负载示例:
{ "to": "device_token", "data": { "customKey": "customValue" } }
问题:应用被终止(被杀/关闭)时,后台任务无法触发,来电界面不显示(测试环境为Android)。
解决方案(Android平台)
1. 修改推送负载为带可见通知的格式
Expo的TaskManager在应用被完全杀死后,无法处理纯data字段的推送,必须包含notification字段(即带有可见通知栏提示的推送)才能唤醒后台任务。调整后的推送负载:
{ "to": "device_token", "notification": { "title": "来电提醒", "body": "有新的来电", "sound": "default" }, "data": { "uuid": "unique-call-id", "instructorName": "讲师姓名", "phoneNumber": "9999999999" } }
2. 配置应用权限与插件参数
在app.json中添加必要的权限声明和插件配置,确保系统允许应用后台运行并显示来电界面:
{ "expo": { "android": { "permissions": [ "RECEIVE_BOOT_COMPLETED", "FOREGROUND_SERVICE", "READ_PHONE_STATE", "CALL_PHONE" ], "useNextNotificationsApi": true }, "plugins": [ [ "expo-notifications", { "icon": "./assets/notification-icon.png", "color": "#ffffff", "sounds": ["./assets/ringtone.mp3"] } ], [ "react-native-callkeep", { "ios": { "appName": "你的应用名称" }, "android": { "alertTitle": "来电权限申请", "alertDescription": "应用需要权限才能显示来电界面", "cancelButton": "取消", "okButton": "允许" } } ] ] } }
3. 优化后台任务逻辑
确保应用被唤醒时CallKeep已完成初始化,正确解析推送中的来电数据:
TaskManager.defineTask( BACKGROUND_NOTIFICATION_TASK, async ({ data, error, executionInfo }) => { if (error) { console.error("后台任务执行错误:", error); return; } // 解析推送中的来电数据 const callData = data?.notification?.data; if (!callData) return; // 初始化CallKeep(应用被杀死后唤醒时需重新初始化) CallKeep.setup({ ios: { appName: "你的应用名称" }, android: { alertTitle: "来电权限申请", alertDescription: "应用需要权限才能显示来电界面", cancelButton: "取消", okButton: "允许" } }); // 显示来电界面 CallKeep.displayIncomingCall( callData.uuid, callData.phoneNumber, callData.instructorName, 'generic', true ); } );
4. 处理Android厂商的后台限制
多数Android厂商(小米、华为、OPPO等)会对被杀死的应用做后台运行限制,需要引导用户完成以下设置:
- 关闭应用的电池优化(设置 -> 电池 -> 电池优化 -> 找到应用 -> 选择不优化)
- 开启应用的自启动权限(不同厂商路径不同,一般在应用设置的权限或自启动选项中)
- 在多任务界面将应用锁定到后台(下拉应用卡片即可锁定)
可以在应用首次启动时添加引导弹窗,告知用户开启这些权限以保证来电通知正常工作。
5. 使用EAS Build构建正式包
Expo Go在测试后台任务时存在沙箱限制,无法完全模拟生产环境的行为。使用EAS Build构建正式的APK/AAB包,能更准确地测试应用被终止后的来电通知触发逻辑。
内容的提问来源于stack exchange,提问作者Pradeep Charan
相关产品推荐
相关产品推荐

