当应用程序进入后台时,MediaBrowserServiceCompat 停止播放音乐

Posted

技术标签:

【中文标题】当应用程序进入后台时,MediaBrowserServiceCompat 停止播放音乐【英文标题】:MediaBrowserServiceCompat stopped playing music when app goes background 【发布时间】:2020-12-22 02:49:03 【问题描述】:

当应用程序进入后台时,Mediabrowsercompat 不播放音乐。如果我没有断开活动 onStop 方法中的 mediabrowsercompat 实例,那么它正在工作。但这不是解决方案,因为根据文档,一旦应用程序进入后台,我们必须断开服务。

这是我的 mediabroweserservicecomat 类(我正在使用 Exoplayer 播放音乐):

private static final String PLAYBACK_CHANNEL_ID = "100";
private static final int PLAYBACK_NOTIFICATION_ID =101 ;
private MediaSessionCompat mediaSessionCompat;
private PlaybackStateCompat.Builder stateBuilder;
private SimpleExoPlayer exoPlayer;
private Uri oldUri;
private AudioAttributes audioAttributes;
private PlayerNotificationManager playerNotificationManager;

@Override
public void onCreate() 
    super.onCreate();
    Log.i("Test","Hi");

    initPlayer();
    initAttributes();

    ComponentName mediaButtonReceiver = new ComponentName(getApplicationContext(), MediaButtonReceiver.class);
    mediaSessionCompat = new MediaSessionCompat(getApplicationContext(), "Tag", mediaButtonReceiver, null);
    mediaSessionCompat.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS|
            MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
    stateBuilder = new PlaybackStateCompat.Builder();
    stateBuilder.setActions(PlaybackStateCompat.ACTION_PLAY|PlaybackStateCompat.ACTION_PLAY_PAUSE);
    mediaSessionCompat.setPlaybackState(stateBuilder.build());
    mediaSessionCompat.setCallback(mediaSessionCompatCallback);
    setSessionToken(mediaSessionCompat.getSessionToken());
    mediaSessionCompat.setActive(true);

    Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
    mediaButtonIntent.setClass(this, MediaButtonReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, mediaButtonIntent, 0);
    mediaSessionCompat.setMediaButtonReceiver(pendingIntent);







@Override
public int onStartCommand(Intent intent, int flags, int startId) 
    MediaButtonReceiver.handleIntent(mediaSessionCompat,intent);
    return super.onStartCommand(intent, flags, startId);


private MediaSessionCompat.Callback mediaSessionCompatCallback = new MediaSessionCompat.Callback() 
    @Override
    public void onPlayFromUri(Uri uri, Bundle extras) 
        super.onPlayFromUri(uri, extras);
        if (uri!=null)
            MediaItem mediaSource = MediaItem.fromUri(uri);
            if (uri!=oldUri)
                play(mediaSource);
                onPlay();
            else 
                oldUri = uri;
            
        
    

    @Override
    public void onPlay() 
        super.onPlay();
        Log.i("onPlay","onPlay");
        //startService(new Intent(MusicService.this,MusicForegroundService.class));


        playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(MusicService.this,
                PLAYBACK_CHANNEL_ID, R.string.channel_name, PLAYBACK_NOTIFICATION_ID,
                new PlayerNotificationManager.MediaDescriptionAdapter() 
                    @Override
                    public CharSequence getCurrentContentTitle(Player player) 
                        return "title";
                    

                    @Nullable
                    @Override
                    public PendingIntent createCurrentContentIntent(Player player) 
                        Intent intent = new Intent(getBaseContext(), PlayerFullViewActivity.class);
                        return PendingIntent.getActivity(getBaseContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                    

                    @Nullable
                    @Override
                    public CharSequence getCurrentContentText(Player player) 
                        return "content";
                    

                    @Nullable
                    @Override
                    public Bitmap getCurrentLargeIcon(Player player, PlayerNotificationManager.BitmapCallback callback) 
                        return null;
                    
                ,
                new PlayerNotificationManager.NotificationListener() 
                    @Override
                    public void onNotificationPosted(int notificationId, Notification notification, boolean ongoing) 
                        startForeground(notificationId,notification);
                    

                    @Override
                    public void onNotificationCancelled(int notificationId, boolean dismissedByUser) 
                        stopSelf();
                    
                );

        playerNotificationManager.setPlayer(exoPlayer);

    

    @Override
    public void onPause() 
        super.onPause();
        pause();
    

    @Override
    public void onStop() 
        playerNotificationManager.setPlayer(null);

        super.onStop();
        stop();
    
;

@Override
public void onDestroy() 
    super.onDestroy();
    stop();


private void stop() 
    exoPlayer.setPlayWhenReady(false);
    exoPlayer.release();
    exoPlayer =null;
    updatePlayBackState(PlaybackStateCompat.STATE_NONE);
    mediaSessionCompat.setActive(false);
    mediaSessionCompat.release();


@SuppressLint("WrongConstant")
private void pause() 
    if (exoPlayer!=null)
        exoPlayer.setPlayWhenReady(false);
        if (exoPlayer.getPlaybackState()==PlaybackStateCompat.STATE_PLAYING)
            updatePlayBackState(PlaybackStateCompat.STATE_PAUSED);
        
    




private void play(MediaItem mediaSource)
    if (exoPlayer==null) 
        initPlayer();
    
    if (audioAttributes==null) 
        initAttributes();
    
            exoPlayer.setAudioAttributes(audioAttributes,true);

        exoPlayer.setMediaItem(mediaSource);
        exoPlayer.prepare();
        play();



private void initAttributes() 
    audioAttributes = new AudioAttributes.Builder().setUsage(C.USAGE_MEDIA)
            .setContentType(C.CONTENT_TYPE_MUSIC)
            .build();


private void initPlayer() 
    exoPlayer = new SimpleExoPlayer.Builder(this, new  DefaultRenderersFactory(getBaseContext()),
            new DefaultExtractorsFactory()).build();


private void play() 
    exoPlayer.setPlayWhenReady(true);
    updatePlayBackState(PlaybackStateCompat.STATE_PLAYING);
    mediaSessionCompat.setActive(true);


private void updatePlayBackState(int statePlaying) 
    mediaSessionCompat.setPlaybackState(new PlaybackStateCompat.Builder().
            setState(statePlaying,0L,0).build());




@Nullable
@Override
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) 
    return new BrowserRoot("",null);


@Override
public void onLoadChildren(@NonNull String parentId, @NonNull Result<List<MediaBrowserCompat.MediaItem>> result) 
     result.sendResult(null);

这是我的活动课:

ActivityPlayerFullViewBinding activityPlayerFullViewBinding;

private MediaBrowserCompat mediaBrowserCompat;
private MediaBrowserCompat.ConnectionCallback connectionCallback = new MediaBrowserCompat.ConnectionCallback()
    @Override
    public void onConnected() 
        super.onConnected();
        MediaSessionCompat.Token sessionToken = mediaBrowserCompat.getSessionToken();
        if (sessionToken!=null)
            try 
                MediaControllerCompat mediaControllerCompat = new
                        MediaControllerCompat(PlayerFullViewActivity.this, sessionToken);
                MediaControllerCompat.setMediaController(PlayerFullViewActivity.this,mediaControllerCompat);
                playPauseBuild();
                Log.d("onConnected","ConnectionSuccess");

             catch (RemoteException e) 
                e.printStackTrace();
            
        
    

    @Override
    public void onConnectionFailed() 
        super.onConnectionFailed();
        Log.d("onConnectionFaild","ConnectionFailed");
    
;

MediaControllerCompat.Callback controllerCallback =
        new MediaControllerCompat.Callback() 
            @Override
            public void onMetadataChanged(MediaMetadataCompat metadata) 

            @Override
            public void onPlaybackStateChanged(PlaybackStateCompat state) 
        ;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);

    activityPlayerFullViewBinding = DataBindingUtil.setContentView(this,R.layout.activity_player_full_view);
    ComponentName componentName = new ComponentName(this,MusicService.class);
    mediaBrowserCompat = new MediaBrowserCompat(this,componentName,connectionCallback,null);




private void playPauseBuild() 
    MediaControllerCompat mediaController = MediaControllerCompat.getMediaController(PlayerFullViewActivity.this);
    activityPlayerFullViewBinding.playPauseBtn
            .setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View v) 
                        int state = mediaController.getPlaybackState().getState();
                        if (state== PlaybackStateCompat.STATE_PAUSED||state==PlaybackStateCompat.STATE_STOPPED||
                                state==PlaybackStateCompat.STATE_NONE)
                            mediaController.getTransportControls().playFromUri(
                                    Uri.parse("https://www.mboxdrive.com/Eminem-Sing-For-The-Moment9jamo.com_.mp3"),null);

                            activityPlayerFullViewBinding.playPauseBtn.setText("Pause");
                        else if (state == PlaybackStateCompat.STATE_PLAYING ||
                                state == PlaybackStateCompat.STATE_BUFFERING ||
                                state == PlaybackStateCompat.STATE_CONNECTING)

                            mediaController.getTransportControls().pause();
                            activityPlayerFullViewBinding.playPauseBtn.setText("Play");
                        
                    


            );
    mediaController.registerCallback(controllerCallback);



@Override
protected void onStart() 
    super.onStart();
    mediaBrowserCompat.connect();


@Override
public void onResume() 
    super.onResume();
    setVolumeControlStream(AudioManager.STREAM_MUSIC);

@Override
protected void onStop() 
    super.onStop();
    Log.i("onStop","onStop");
    MediaControllerCompat mediaController = MediaControllerCompat.getMediaController(this);

    if (mediaController != null) 
        mediaController.unregisterCallback(controllerCallback);
    
    
    mediaBrowserCompat.disconnect();

【问题讨论】:

【参考方案1】:

在浪费了两个不眠之夜之后。我找到了解决方法。我不知道这是否是处理这个问题的正确方法。但是,如果您曾经遇到过这个问题。你可以试试:

 @Override
protected void onStart() 
    super.onStart();
    if (!mediaBrowserCompat.isConnected())
         mediaBrowserCompat.connect();



@Override
protected void onStop() 
    super.onStop();
    Log.i("onStop","onStop");
    MediaControllerCompat mediaController = MediaControllerCompat.getMediaController(this);

    if (mediaController != null) 
        mediaController.unregisterCallback(controllerCallback);
    

   // mediaBrowserCompat.disconnect();


@Override
protected void onDestroy() 
    super.onDestroy();
    mediaBrowserCompat.disconnect();

【讨论】:

以上是关于当应用程序进入后台时,MediaBrowserServiceCompat 停止播放音乐的主要内容,如果未能解决你的问题,请参考以下文章

当应用程序进入后台模式时释放图形

当应用程序从后台进入前台时,MPMoviePlayerController 黑屏

当应用程序进入后台时更改 rootview 控制器 (applicationDidEnterBackground)

CAAnimation:当应用程序进入后台时自动禁用动画

当应用程序进入后台时 UIWindow 变为 NULL

当应用程序进入后台时,URLSessions 给 URLResponse nil