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

Android 11+移除最近任务时音乐播放器前台服务停止问题

Android 11+ 划走最近任务后音乐播放服务终止问题修复

问题现象

开发简易音乐播放器时出现版本差异化故障:

  • Android 11(API 30)及以上系统:应用从最近任务列表划走后,音乐播放服务直接停止运行
  • Android 11以下系统:相同操作下服务可正常保持后台运行

现有相关代码

服务端核心逻辑

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
  return START_NOT_STICKY;
}

private void notification_manager() {
       
        playerNotificationManager = new PlayerNotificationManager.Builder(AudioPlayerService.this, ConstantValues.PLAYBACK_CHANNEL_ID_INT_ID,
                ConstantValues.PLAYBACK_CHANNEL_ID)
                .setMediaDescriptionAdapter(mediaDescriptionAdapter)
                .setNotificationListener(notificationListener)
                .setCustomActionReceiver(null).setChannelNameResourceId(R.string.app_name).setChannelImportance(NotificationUtil.IMPORTANCE_HIGH)
                .build();
        // 配置播放器通知样式
        playerNotificationManager.setPriority(NotificationCompat.PRIORITY_HIGH);
        playerNotificationManager.setPlayer(player);
        playerNotificationManager.setUseFastForwardAction(false);
        playerNotificationManager.setUseRewindAction(false);
        playerNotificationManager.setUseRewindActionInCompactView(false);
        playerNotificationManager.setUseChronometer(false);
        playerNotificationManager.setUsePlayPauseActions(true);
        playerNotificationManager.setUseStopAction(true);
        playerNotificationManager.setColorized(true);
        playerNotificationManager.setBadgeIconType(NotificationCompat.BADGE_ICON_LARGE);
       
    }

@Nullable
            @Override
            public PendingIntent createCurrentContentIntent(Player player) {
                Intent intent = new Intent(AudioPlayerService.this, MainActivity.class);
                PendingIntent pendingIntent = null;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
                    pendingIntent = PendingIntent.getActivity(AudioPlayerService.this, 0, intent, PendingIntent.FLAG_IMMUTABLE);

            }else {
                pendingIntent = PendingIntent.getActivity(AudioPlayerService.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

            }
            return pendingIntent;
        }

项目Gradle配置

compileSdk 31

defaultConfig {
    applicationId "com.test.musicplayer"
    minSdk 21
    targetSdk 31
    versionCode 1
    versionName "1.0"
    multiDexEnabled true
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

故障根因

  • onStartCommand返回值配置错误:返回START_NOT_STICKY意味着服务被系统回收或用户强制终止后不会自动重启,也不会保留重启所需的上下文信息
  • 前台服务逻辑缺失:现有代码仅初始化了PlayerNotificationManager,但没有按照系统要求在播放时调用startForeground()将服务提升为前台服务优先级。Android 11开始收紧了后台服务限制,普通后台服务在应用退到后台或被划走最近任务时会被系统直接杀死,低版本系统无此强校验规则。
  • 未适配API 31前台服务规则:项目targetSdk为31,正好命中Android 12新增的前台服务类型校验要求,未声明媒体播放类型的前台服务会在应用移除最近任务时被立即终止。

修复步骤

  1. 调整服务重启策略
    修改onStartCommand返回值为START_STICKY,保证服务异常终止后系统可尝试重启:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);
    // 原有处理播放指令的逻辑保留
    return START_STICKY;
}
  1. 正确绑定前台服务生命周期
    实现PlayerNotificationManager.NotificationListener接口,在通知发布时主动调用前台服务启动逻辑,不要依赖组件库的默认实现:
PlayerNotificationManager.NotificationListener notificationListener = new PlayerNotificationManager.NotificationListener() {
    @Override
    public void onNotificationCancelled(int notificationId, boolean dismissedByUser) {
        // 用户主动关闭通知时停止服务
        stopSelf();
    }

    @Override
    public void onNotificationPosted(int notificationId, Notification notification, boolean ongoing) {
        if (ongoing) {
            // 播放状态下启动前台服务,避免被系统杀死
            startForeground(notificationId, notification);
        } else {
            // 暂停状态下解除前台服务优先级,保留通知栏显示
            stopForeground(false);
        }
    }
};
  1. 补充清单文件配置
    在AndroidManifest.xml中添加所需权限和服务声明,适配高版本系统要求:
<!-- 前台服务基础权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Android 12+ 媒体播放类前台服务专属权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />

<service
    android:name=".AudioPlayerService"
    android:exported="false"
    android:foregroundServiceType="mediaPlayback">
    <intent-filter>
        <action android:name="androidx.media.session.MediaButtonReceiver" />
    </intent-filter>
</service>
  1. 处理任务移除场景
    重写服务的onTaskRemoved方法,避免系统在划走最近任务时直接杀死进程:
@Override
public void onTaskRemoved(Intent rootIntent) {
    // 若需要划走任务后继续播放,此处不调用stopSelf即可
    // 若需要划走后停止播放,可在此处释放播放器资源并调用stopSelf()
    super.onTaskRemoved(rootIntent);
}

补充:如果后续升级到AndroidX Media3库,可直接使用官方封装的MediaSessionService,内部已经完成了所有系统版本的前台服务适配,不需要手动处理上述生命周期逻辑。

内容的提问来源于stack exchange,提问作者1234567

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 18:24:32