Android应用后台或已关闭时收到推送如何打开来电Activity
Android 后台/进程被杀状态下收到推送自动弹出来电界面实现方案
1. 推送服务基础配置
首先要确保推送通道的可达性,避免进程被杀后消息无法触达:
- 国内机型优先接入小米、华为、OPPO、VIVO、荣耀等厂商系统推送通道,不要仅依赖第三方公网推送
- 推送 payload 中携带完整通话参数:来电人信息、通话ID、通话类型等,方便后续拉起来电页时传递数据
2. 权限配置(核心适配点)
2.1 清单文件注册权限
在 AndroidManifest.xml 中添加如下权限:
<!-- 悬浮窗权限,后台弹出界面基础 --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- Android 10及以上后台启动Activity必备权限 --> <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" /> <!-- 通话类应用可选权限,可提升应用进程优先级 --> <uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
2.2 运行时权限申请
- Android 6.0+ 需要引导用户主动开启 悬浮窗权限,该权限为特殊权限,需要跳转到系统设置页申请
- Android 10+ 所需的
USE_FULL_SCREEN_INTENT为普通权限,清单注册即可生效,无需用户手动授权 - 国内定制ROM额外需要引导用户开启 后台弹出界面 权限,该权限为厂商自定义权限,未开启时即使有悬浮窗权限也无法后台弹出Activity
3. 推送消息接收处理逻辑
在推送服务的消息接收回调中,按如下逻辑处理:
- 如果应用进程存活,直接走原有前台通话逻辑拉起来电Activity即可
- 如果应用进程已被杀,先完成必要的应用基础初始化,再执行来电跳转逻辑
3.1 直接拉起Activity的配置(适用于Android 10以下)
给来电Activity的Intent添加专属Flags:
val intent = Intent(context, IncomingCallActivity::class.java).apply { // 传递通话参数 putExtra("call_id", callId) putExtra("caller_info", callerInfo) // 关键Flags配置 addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) } context.startActivity(intent)
3.2 全屏Intent通知方案(Android 10+推荐,被拦截概率最低)
Android 10之后对后台启动Activity做了严格限制,更稳妥的实现方式是先发高优先级全屏Intent通知,系统会自动判断场景弹出界面:
// 构建来电页面跳转PendingIntent val fullScreenIntent = Intent(context, IncomingCallActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_NO_USER_ACTION } val fullScreenPendingIntent = PendingIntent.getActivity( context, callId.hashCode(), fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // 构建高优先级来电通知 val notificationBuilder = NotificationCompat.Builder(context, CHANNEL_ID_CALL) .setSmallIcon(R.drawable.ic_incoming_call) .setContentTitle("新来电") .setContentText("$callerName 正在呼叫你") .setPriority(NotificationCompat.PRIORITY_MAX) .setCategory(NotificationCompat.CATEGORY_CALL) .setFullScreenIntent(fullScreenPendingIntent, true) .setAutoCancel(true) .setOngoing(true) // 发送通知,系统会自动匹配场景弹出来电页 val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.notify(callId.hashCode(), notificationBuilder.build())
该方案的优势是:锁屏状态下会直接亮屏弹出来电界面,用户正在使用其他应用时会先显示悬浮通知条,符合系统权限规范,被系统拦截的概率极低。
4. 来电Activity专属配置
在 AndroidManifest.xml 中给来电Activity添加如下属性:
<activity android:name=".ui.IncomingCallActivity" android:launchMode="singleTop" android:showOnLockScreen="true" android:turnScreenOn="true" android:excludeFromRecents="true" android:taskAffinity="" android:exported="true"> <intent-filter> <action android:name="com.yourapp.action.INCOMING_CALL" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
其中showOnLockScreen和turnScreenOn属性可以让Activity在锁屏状态下直接显示并点亮屏幕,无需用户先解锁设备。
常见问题排查
- 进程被杀后收不到推送:检查厂商推送通道配置是否正确,是否申请了应用自启动权限
- 收到推送但弹不出界面:检查悬浮窗权限、厂商自定义的后台弹出界面权限是否开启
- 仅显示通知不跳转页面:检查通知优先级是否设置为最高,全屏Intent参数是否配置正确
内容的提问来源于stack exchange,提问作者Rameo Singh
相关产品推荐
相关产品推荐

