Unity中如何设置仅可通过脚本删除的Android通知?
如何阻止用户删除Unity发送的Android通知(仅允许应用内操作删除)
核心原理
Android系统中,普通通知允许用户手动清除,要实现用户无法删除的效果,必须将通知与前台服务绑定。前台服务的通知属于系统级强制显示的通知,用户无法手动删除,只有当服务停止时,通知才会自动消失。
具体实现步骤
1. 修改通知渠道优先级
前台服务要求通知渠道的优先级至少为High,否则系统可能不允许将其设为前台通知。修改你的Start()方法中的渠道设置:
private void Start() { var channel = new AndroidNotificationChannel() { Id = "channel_ID", Name = "Notifications Channel", Importance = Importance.High, // 必须改为High级别 Description = "Reminder notifications", LockScreenVisibility = LockScreenVisibility.Public, }; AndroidNotificationCenter.RegisterNotificationChannel(channel); if (!Permission.HasUserAuthorizedPermission("android.permission.POST_NOTIFICATIONS")) { Permission.RequestUserPermission("android.permission.POST_NOTIFICATIONS"); } }
2. 通过Android前台服务绑定通知
Unity的AndroidNotificationCenter本身不直接支持前台服务,需要通过Android原生API实现。以下是在Unity中调用原生API创建前台服务的代码:
添加启动前台服务的方法:
private void StartForegroundServiceWithNotification() { AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); AndroidJavaObject context = currentActivity.Call<AndroidJavaObject>("getApplicationContext"); // 创建通知内容 var notification = new AndroidNotification(); notification.Title = "工单提醒"; notification.Text = "请处理未关闭的游戏内工单"; notification.ShouldAutoCancel = false; notification.SmallIcon = "icon_notification"; // 确保Android项目中有该图标资源 // 转换为Android原生Notification对象 AndroidJavaClass builderClass = new AndroidJavaClass("android.app.Notification$Builder"); AndroidJavaObject builder = builderClass.CallStatic<AndroidJavaObject>("create", context, "channel_ID"); builder.Call<AndroidJavaObject>("setContentTitle", notification.Title); builder.Call<AndroidJavaObject>("setContentText", notification.Text); int iconResId = context.Call<int>("getResources") .Call<int>("getIdentifier", notification.SmallIcon, "drawable", context.Call<string>("getPackageName")); builder.Call<AndroidJavaObject>("setSmallIcon", iconResId); builder.Call<AndroidJavaObject>("setAutoCancel", notification.ShouldAutoCancel); builder.Call<AndroidJavaObject>("setOngoing", true); // 标记为持续通知,防止用户手动清除 AndroidJavaObject notificationObj = builder.Call<AndroidJavaObject>("build"); // 启动前台服务 AndroidJavaClass serviceClass = new AndroidJavaClass("com.yourpackage.NotificationForegroundService"); // 替换为你的服务包路径 AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", context, serviceClass); intent.Call<AndroidJavaObject>("putExtra", "notification_id", 1); // 自定义通知ID intent.Call<AndroidJavaObject>("putExtra", "notification", notificationObj); // 适配Android版本(8.0+需用startForegroundService) if (GetAndroidOSVersion() >= 26) { context.Call("startForegroundService", intent); } else { context.Call("startService", intent); } } // 获取当前Android系统版本 private int GetAndroidOSVersion() { AndroidJavaClass buildVersion = new AndroidJavaClass("android.os.Build$VERSION"); return buildVersion.GetStatic<int>("SDK_INT"); }
3. 创建Android前台服务类
在Unity的Plugins/Android/src目录下创建NotificationForegroundService.java(替换包名为你的项目包名):
package com.yourpackage; import android.app.Notification; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class NotificationForegroundService extends Service { private static final int DEFAULT_NOTIFICATION_ID = 1; @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { int notificationId = intent.getIntExtra("notification_id", DEFAULT_NOTIFICATION_ID); Notification notification = intent.getParcelableExtra("notification"); // 将服务设为前台服务,绑定通知 startForeground(notificationId, notification); // 返回START_STICKY确保服务被杀死后可重启(可选,按需调整) return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); // 服务停止时,通知会自动移除 } }
4. 完成操作后停止服务(删除通知)
当用户关闭工单完成指定操作时,调用以下方法停止前台服务,通知会自动消失:
public void StopNotificationWhenTaskCompleted() { AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); AndroidJavaObject context = currentActivity.Call<AndroidJavaObject>("getApplicationContext"); AndroidJavaClass serviceClass = new AndroidJavaClass("com.yourpackage.NotificationForegroundService"); AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", context, serviceClass); context.Call("stopService", intent); }
5. 配置AndroidManifest.xml
确保在AndroidManifest.xml中添加权限和服务声明:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <application ...> <service android:name="com.yourpackage.NotificationForegroundService" android:foregroundServiceType="dataSync" /> <!-- 根据服务类型选择,如dataSync、mediaPlayback等 --> </application>
关键注意事项
setOngoing(true):必须设置该属性,配合前台服务彻底阻止用户手动删除通知。- Android 12+要求指定
foregroundServiceType,否则会触发系统报错。 - 确保Android项目中存在指定的通知图标资源,否则通知无法正常显示。
内容的提问来源于stack exchange,提问作者Rafał Łojek
相关产品推荐
相关产品推荐

