App关闭时Android Unity后台服务通知更新异常问题求助
Unity Android 后台计步服务关闭应用后通知无法更新排查方案
问题现象
- 基于Unity实现Android端计步后台服务,应用在前台、后台挂起状态时,通知栏实时展示计步数据功能正常
- 滑动关闭应用后,后台计步逻辑仍持续运行,但通知无法正常更新
- 调试确认应用关闭时,承载Unity的Activity实例变为null,原有逻辑触发空指针;尝试替换无Activity依赖的PendingIntent构造方案后,通知更新接口抛出新的空指针异常
原有问题代码
原通知构建方法
private Notification crearNotificacion() { String input = "Pasos: " + (Bridge.steps); // 此处依赖Bridge持有的Activity运行时实例,应用关闭后实例为null触发空指针 Intent notificationIntent = new Intent(this, Bridge.myActivity.getClass()); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); Notification notification = new NotificationCompat.Builder(this, "PedometerLib") .setContentTitle("Background Walking Service") .setContentText(input) .setSmallIcon(R.mipmap.ic_launcher) .setContentIntent(pendingIntent) .build(); return notification; }
原通知更新调用
notificationManager.notify(112, crearNotificacion());
第一次修复尝试代码
PendingIntent contentIntent = PendingIntent.getActivity( getApplicationContext(), 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT);
该方案触发报错:
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.core.app.NotificationManagerCompat.notify(int, android.app.Notification)' on a null object reference
根因定位与修复步骤
该需求不需要编写复杂的额外逻辑,只需要修复两个独立的空指针问题,同时适配安卓系统的后台服务限制即可:
修复PendingIntent依赖Activity实例的空指针问题
不要通过运行时持有的Activity引用获取目标类,直接通过类名指定跳转目标,或者通过PackageManager获取应用启动Intent即可,完全不需要依赖存活的Activity实例:// 可选方案1:点击通知启动应用默认入口 Intent launchIntent = getPackageManager().getLaunchIntentForPackage(getPackageName()); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, launchIntent != null ? launchIntent : new Intent(), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); // 可选方案2:明确跳转到Unity主Activity,直接写死类名不依赖运行时引用 // 注意如果Unity导出项目修改了Activity类名,替换成对应全类名即可 Intent notificationIntent = new Intent(); notificationIntent.setClassName(getPackageName(), "com.unity3d.player.UnityPlayerActivity"); notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);注意:安卓12及以上版本构造PendingIntent必须显式指定
FLAG_IMMUTABLE或FLAG_MUTABLE标志位,否则会直接抛出异常。修复NotificationManager实例空指针问题
该报错和PendingIntent逻辑无关,本质是通知管理器实例的初始化位置错误:如果notificationManager是在Activity的生命周期方法中初始化的,Activity销毁后实例会被回收,自然会触发空指针。
把通知管理器的初始化逻辑移到前台服务的onCreate方法中,用服务自身的上下文初始化即可:private NotificationManagerCompat notificationManager; @Override public void onCreate() { super.onCreate(); notificationManager = NotificationManagerCompat.from(this); // 安卓8.0及以上必须提前创建通知渠道,否则通知无法展示 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel("PedometerLib", "计步后台服务", NotificationManager.IMPORTANCE_LOW); channel.setShowBadge(false); notificationManager.createNotificationChannel(channel); } }适配系统后台限制
- 服务启动后必须调用
startForeground(112, crearNotificacion())将其绑定为前台服务,安卓8.0以上未绑定前台的后台服务会被系统在短时间内强制回收,安卓12以上未调用startForeground的服务甚至无法直接启动 - 不要在Bridge类中持有Activity的强引用,应用关闭后Activity会被系统回收,强引用不仅会触发空指针,还会造成内存泄漏
- 计步监听、步数累加、通知更新的逻辑必须完全放在原生Service层实现,不要依赖Unity端的消息回调触发更新——应用关闭后Unity运行时会被销毁,来自Unity层的调用会直接中断。
- 服务启动后必须调用
内容的提问来源于stack exchange,提问作者Pevi
相关产品推荐
相关产品推荐

