You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 09:12:16