Android 14设备后台Activity启动被阻断问题求助
从日志关键信息backgroundStartPrivileges: BackgroundStartPrivileges[allowsBackgroundActivityStarts=false]和callingUidHasAnyVisibleWindow: false可以明确:Android 14的后台启动限制拦截了你的Activity启动请求,因为应用处于后台且没有提供系统认可的用户交互来源凭证。以下是针对性的修复方案:
1. 利用MediaSession的用户交互令牌(核心修复)
Android 14中,从MediaLibraryService响应Android Auto的用户操作时,必须使用系统授予的**来源令牌(Originating Token)**来获取后台启动权限。这个令牌来自触发操作的MediaSession控制器,需要传递给PendingIntent。
修改onAddMediaItems方法中的启动逻辑:
@Override public ListenableFuture<MediaLibraryService.MediaLibrarySession.Result> onAddMediaItems(MediaLibrarySession session, MediaSession.ControllerInfo controller, List<MediaItem> mediaItems) { // 构建启动Activity的Intent Intent intent = new Intent(this, StreamListMainActivity.class); intent.setAction(StreamListMainActivity.PLAY_STREAM); intent.putExtra(StreamListMainActivity.STREAM_INDEX, index); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.setPackage(getContext().getPackageName()); // 获取Android Auto控制器提供的用户交互令牌 IBinder originatingToken = controller.getOriginatingToken(); ActivityOptions options = ActivityOptions.makeBasic(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { options.setPendingIntentBackgroundActivityStartMode(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED); // 关键:传递系统认可的来源令牌,证明启动请求来自用户交互 options.setOriginatingPendingIntentToken(originatingToken); } // 创建带权限的PendingIntent PendingIntent pendingIntent = PendingIntent.getActivity( getContext(), 998, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, options.toBundle() ); try { pendingIntent.send(); } catch (PendingIntent.CanceledException e) { AppLogger.Exception(LOG_TAG, e); } // 继续处理媒体项逻辑 return super.onAddMediaItems(session, controller, mediaItems); }
2. 确保服务处于前台状态
虽然你的服务已声明foregroundServiceType="mediaPlayback",但需确保在启动Activity前服务已进入前台状态,前台服务拥有更高的后台操作权限:
// 在AudioPlayerService的初始化或交互触发时调用 private void ensureForegroundState() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // 替换为你自己的媒体通知构建逻辑 Notification mediaNotification = createMediaPlaybackNotification(); startForeground(1001, mediaNotification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK); } }
3. 调整Intent Flags(可选优化)
添加FLAG_ACTIVITY_SINGLE_TOP避免重复创建Activity实例,同时帮助系统识别这是一个合法的后台启动场景:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
为什么之前的代码失效?
你仅设置了MODE_BACKGROUND_ACTIVITY_START_ALLOWED,但未提供Android 14要求的用户交互来源令牌。这个令牌是系统为Android Auto的用户操作授予的临时权限凭证,缺少它,系统会判定启动请求为无用户触发的后台行为,直接拦截。
内容的提问来源于stack exchange,提问作者Mike Macpherson

