Unity3D中配置OneSignal:接收通知但后台不显示
解决Unity3D+Firebase+OneSignal:仅在应用运行时接收通知的问题
我之前也遇到过类似的需求,结合OneSignal和Unity的特性,给你整理了一套可行的方案:
核心思路
要实现「仅应用运行时显示通知」,关键在于拦截通知的展示逻辑:只在应用处于活跃状态(前台/后台进程存活)时处理通知弹窗,应用完全未运行时直接跳过展示,仅按需处理数据内容。
步骤1:调整Firebase消息发送类型
首先要确保你通过Firebase发送的是**数据消息(Data Message)**而非通知消息(Notification Message)。因为通知消息会被Android系统自动触发展示,不受客户端控制;而数据消息完全由我们的代码决定如何处理,更适配需求。
修改你现有的Firebase发送代码,把所有通知内容放到data字段中,避免使用notification字段:
var sendNotification = (data) => { var headers = { "Content-Type": "application/json; charset=utf-8", "Authorization": "key=YOUR_FIREBASE_SERVER_KEY" }; var payload = { to: "TARGET_DEVICE_TOKEN", data: { // 所有通知内容、自定义数据都放在这里 title: "你的通知标题", body: "你的通知内容", customKey: "自定义业务数据" } }; // 后续发送请求的逻辑保持不变... };
步骤2:Unity中集成OneSignal的通知拦截逻辑
在Unity里注册OneSignal的通知接收回调,在回调中判断应用运行状态,决定是否展示通知:
using UnityEngine; using OneSignalSDK; public class NotificationManager : MonoBehaviour { void Start() { // 初始化OneSignal(确保已完成基础配置) OneSignal.Initialize("YOUR_ONESIGNAL_APP_ID"); // 注册通知接收拦截回调 OneSignal.Notifications.Received += OnNotificationReceived; } private void OnNotificationReceived(NotificationReceivedEvent notificationEvent) { // 判断应用是否处于运行状态:前台聚焦 或 后台进程存活 bool isAppRunning = Application.isFocused || IsAppInBackground(); if (!isAppRunning) { // 应用未运行,取消通知展示 notificationEvent.Cancel = true; Debug.Log("应用未运行,跳过通知展示"); return; } // 应用运行中,可选择让OneSignal默认展示,或自定义Unity UI弹窗 Debug.Log("应用运行中,展示通知:" + notificationEvent.Notification.Title); } // 辅助方法:判断Android应用是否在后台存活 private bool IsAppInBackground() { #if UNITY_ANDROID && !UNITY_EDITOR AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); AndroidJavaClass activityManager = new AndroidJavaClass("android.app.ActivityManager"); AndroidJavaObject appTasks = activityManager.CallStatic<AndroidJavaObject>("getService").Call<AndroidJavaObject>("getAppTasks"); foreach (AndroidJavaObject task in appTasks.Call<AndroidJavaObject>("toArray")) { AndroidJavaObject taskInfo = task.Call<AndroidJavaObject>("getTaskInfo"); int state = taskInfo.Get<int>("state"); // 状态为2表示应用在后台存活 if (state == 2) return true; } #endif return false; } }
步骤3:Android端后台逻辑加固
如果需要更严格控制后台场景的通知展示,可以自定义OneSignal的NotificationService来拦截:
- 在Unity的Android插件目录下创建
CustomNotificationService.java:
import com.onesignal.OSNotificationReceivedEvent; import com.onesignal.OneSignal; import android.app.ActivityManager; import android.content.Context; import java.util.List; public class CustomNotificationService extends OneSignal.OSNotificationReceivedHandler { @Override public void notificationReceived(OSNotificationReceivedEvent event) { Context context = event.getApplicationContext(); ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses(); boolean isAppRunning = false; for (ActivityManager.RunningAppProcessInfo process : runningProcesses) { if (process.processName.equals(context.getPackageName()) && process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { isAppRunning = true; break; } } if (!isAppRunning) { // 应用未在前台运行,取消通知 event.complete(null); return; } // 应用运行中,允许通知展示 event.complete(event.getNotification()); } }
- 在AndroidManifest.xml中注册该Service:
<service android:name=".CustomNotificationService" android:permission="android.permission.BIND_JOB_SERVICE"> <intent-filter> <action android:name="com.onesignal.NotificationReceived" /> </intent-filter> </service>
验证场景
完成配置后测试两种核心场景:
- 应用前台运行:发送数据消息,正常弹出通知
- 应用完全退出(杀死进程):发送数据消息,无通知弹窗,重新打开应用后可按需处理数据
内容的提问来源于stack exchange,提问作者user2960523
相关产品推荐
相关产品推荐

