Android Studio中实现Firebase通知仿WhatsApp弹窗悬浮效果
Android 全场景悬浮通知实现方案
你之前调研的Theme.Holo.Dialog已在API 23之后正式废弃,无需引入相关依赖,按照以下步骤即可实现全部需求:
前置权限配置
要实现覆盖其他应用、后台/未启动状态弹出悬浮通知的效果,首先需要配置对应权限:
- Android 6.0(API 23)及以上需要
SYSTEM_ALERT_WINDOW悬浮窗权限 - Android 13(API 33)及以上需要
POST_NOTIFICATIONS通知权限 - 小米、华为、OPPO等国内定制ROM还需要额外申请「后台弹出界面」权限
清单文件静态配置
<!-- 悬浮窗基础权限 --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- Android13+ 通知权限 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- 国内ROM后台弹出界面适配权限 --> <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
动态权限申请
悬浮窗属于特殊权限,需要引导用户跳转系统设置页手动开启:
// 检查悬浮窗权限是否已授予 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(context)) { val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:${context.packageName}")) startActivityForResult(intent, 1001) // 1001为自定义请求码 }
1. 前台场景弹窗通知实现
应用在前台时直接弹出自定义Dialog即可,无需依赖旧版Holo主题:
- 首先在
res/values/styles.xml中自定义弹窗主题
<style name="ForegroundNotificationTheme" parent="Theme.MaterialComponents.Dialog"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowIsFloating">true</item> <item name="android:windowCloseOnTouchOutside">true</item> </style>
- 在Firebase消息回调
onMessageReceived中判断应用当前是否处于前台,是则使用上述主题创建Dialog,传入通知内容后展示即可,可自定义点击事件跳转对应业务页面。
2. 全场景悬浮通知(后台/未启动也可触发)
这部分直接通过系统WindowManager添加悬浮View实现,不受应用生命周期限制,只要权限正常就可以弹出:
核心实现步骤
- 自定义悬浮通知布局,可参考WhatsApp的样式实现头像、消息内容、关闭按钮等控件
- 在
FirebaseMessagingService的onMessageReceived回调中,无需判断应用前后台状态,只要权限正常就构造悬浮View - 配置悬浮窗参数后添加到WindowManager即可,参数配置示例:
val layoutParams = WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT, // Android8.0以上用APPLICATION_OVERLAY类型,之前用TYPE_PHONE if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY else WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, PixelFormat.TRANSLUCENT ) // 设置悬浮窗默认显示在顶部居中位置 layoutParams.gravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL // 将自定义View添加到WindowManager windowManager.addView(customNotificationView, layoutParams)
- 给悬浮View添加触摸拖动、点击跳转、关闭逻辑,点击跳转页面示例:
customNotificationView.setOnClickListener { val intent = Intent(context, TargetActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP) putExtra("notify_data", 你的通知数据) } context.startActivity(intent) // 跳转后移除悬浮窗,避免内存泄漏 windowManager.removeView(customNotificationView) }
注意事项
- 悬浮窗使用完后必须调用
removeView移除,避免内存泄漏 - 国内定制ROM的悬浮窗、后台弹出权限默认关闭,建议在应用首次启动时增加引导页提示用户手动开启
- Android12以上禁止从后台广播/服务直接启动Activity,在悬浮窗点击事件中直接加
FLAG_ACTIVITY_NEW_TASK启动即可规避该限制
内容的提问来源于stack exchange,提问作者Karmar
相关产品推荐
相关产品推荐

