Media Session Compat未在Pre-Lollipop上显示锁屏控件

Aks*_*iya 34 android lockscreen android-mediaplayer android-5.0-lollipop

我正在使用MediaSessionCompatAppCompat支持库修订版22.在Lollipop上我收到通知,而且锁屏背景也是专辑封面.一切都很酷.

在Pre-Lollipop设备上,锁屏上的音乐控件根本没有显示.这很奇怪,我尝试了一切,但它没有出现,甚至没有出现背景变化.

我希望有人能解决这个问题.

注意:RemoteControlClient曾经用于Lollipop和KitKat

/**
 * Initializes the remote control client
 */
private void setupMediaSession() {
    /* Activate Audio Manager */
    mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,
            AudioManager.AUDIOFOCUS_GAIN);

    ComponentName mRemoteControlResponder = new ComponentName(getPackageName(),
            MediaButtonReceiver.class.getName());
    final Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
    mediaButtonIntent.setComponent(mRemoteControlResponder);
    mMediaSessionCompat = new MediaSessionCompat(getApplication(), "JairSession", mRemoteControlResponder, null);
    mMediaSessionCompat.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
    PlaybackStateCompat playbackStateCompat = new PlaybackStateCompat.Builder()
            .setActions(
                    PlaybackStateCompat.ACTION_SEEK_TO |
                    PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
                    PlaybackStateCompat.ACTION_SKIP_TO_NEXT |
                    PlaybackStateCompat.ACTION_PLAY |
                    PlaybackStateCompat.ACTION_PAUSE |
                    PlaybackStateCompat.ACTION_STOP
            )
            .setState(
                    isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
                    getCurrentPosition(),
                    1.0f)
            .build();
    mMediaSessionCompat.setPlaybackState(playbackStateCompat);
    mMediaSessionCompat.setCallback(mMediaSessionCallback);
    mMediaSessionCompat.setSessionActivity(retrievePlaybackActions(5));
    mMediaSessionCompat.setActive(true);
    updateMediaSessionMetaData();
    mTransportController = mMediaSessionCompat.getController().getTransportControls();
Run Code Online (Sandbox Code Playgroud)

这是updateMediaSessionMetaData():

/**
 * Updates the lockscreen controls, if enabled.
 */
private void updateMediaSessionMetaData() {
            MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
            builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, getArtistName());
            builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, getAlbumName());
            builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, getTrackName());
            builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, getDuration());
            builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, MusicUtils.getArtwork(this, getAlbumID(), true));
            mMediaSessionCompat.setMetadata(builder.build());
Run Code Online (Sandbox Code Playgroud)

}


媒体会话回调方法

private final MediaSessionCompat.Callback mMediaSessionCallback = new MediaSessionCompat.Callback() {

    @Override
    public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
        final String intentAction = mediaButtonEvent.getAction();
        if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intentAction)) {
            if (PrefUtils.isHeadsetPause(getBaseContext())) {
                Log.d(LOG_TAG, "Headset disconnected");
                pause();
            }
        } else if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
            final KeyEvent event = mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
            if (event == null) return super.onMediaButtonEvent(mediaButtonEvent);
            final int keycode = event.getKeyCode();
            final int action = event.getAction();
            final long eventTime = event.getEventTime();
            if (event.getRepeatCount() == 0 && action == KeyEvent.ACTION_DOWN) {
                switch (keycode) {
                    case KeyEvent.KEYCODE_HEADSETHOOK:
                        if (eventTime - mLastClickTime < DOUBLE_CLICK) {
                            playNext(mSongNumber);
                            mLastClickTime = 0;
                        } else {
                            if (isPlaying())
                                pause();
                            else resume();
                            mLastClickTime = eventTime;
                        }
                        break;
                    case KeyEvent.KEYCODE_MEDIA_STOP:
                        mTransportController.stop();
                        break;
                    case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
                        if (isMediaPlayerActive()) {
                            if (isPlaying()) mTransportController.pause();
                            else mTransportController.play();
                        }
                        break;
                    case KeyEvent.KEYCODE_MEDIA_NEXT:
                        mTransportController.skipToNext();
                        break;
                    case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
                        mTransportController.skipToPrevious();
                        break;
                    case KeyEvent.KEYCODE_MEDIA_PAUSE:
                        mTransportController.pause();
                        break;
                    case KeyEvent.KEYCODE_MEDIA_PLAY:
                        mTransportController.play();
                        break;
                }
            }
        }
        return super.onMediaButtonEvent(mediaButtonEvent);
    }

    @Override
    public void onPlay() {
        super.onPlay();
        resume();
    }

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

    @Override
    public void onSkipToNext() {
        super.onSkipToNext();
        playNext(mSongNumber);
    }

    @Override
    public void onSkipToPrevious() {
        super.onSkipToPrevious();
        playPrevious(mSongNumber);
    }

    @Override
    public void onSeekTo(long pos) {
        super.onSeekTo(pos);
        seekTo(pos);
    }

    @Override
    public void onStop() {
        super.onStop();
        pause();
        commitMusicData();
        updatePlayingUI(STOP_ACTION);
        stopSelf();
    }
};
Run Code Online (Sandbox Code Playgroud)

媒体按钮接收器清单条目

<!-- Media button receiver -->
    <receiver android:name=".receiver.MediaButtonReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.MEDIA_BUTTON" />
            <action android:name="android.media.AUDIO_BECOMING_NOISY" />
        </intent-filter>
    </receiver>
Run Code Online (Sandbox Code Playgroud)

几个星期以来,我一直在努力解决这个问题但没有成功,并迫切需要帮助.

编辑:MediaSessionCompat的教程或示例也可以

ian*_*ake 10

虽然不是严格要求MediaSession,RemoteControlClient对API14-19设备上使用,确实需要声音的焦点,它是100%,强烈建议所有的媒体播放.

添加如下行:

AudioManager audioManager = (AudioManager)
    getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this,
    AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
if (result != AudioManager.AUDIOFOCUS_GAIN) {
    return; //Failed to gain audio focus
}
Run Code Online (Sandbox Code Playgroud)

在播放任何媒体之前,应获得音频焦点并显示控件.

  • 你的代码在API 16模拟器上运行正常 - 查看[这个超级最小的例子](https://gist.github.com/ianhanniballake/15dce0b233b4f4b23ef8),它为我显示锁定屏幕控件. (2认同)

Aks*_*iya 8

最后我想出了一个解决方案.感谢@ianhanniballake@ user1549672

  1. 按照@ianhanniballake的建议添加音频焦点
  2. BroadcastReceiver如果在Google和官方Android文档上搜索,则可以找到添加音乐意图
  3. setupMediaSession()在上面的问题中写下给定的
  4. 非常重要提及Flags正确
  5. MediaSessionCallbacks上面也可以
  6. 非常重要更新MediaSession打开MediaPlayer#onPause(),MediaPlayer#onStart()最后当@ user1549672提到的新歌播放(包括下一个和上一个播放)时
  7. 释放MediaSession对象onDestory()

嗯,就是这样,大多数材料(代码)都在上面提供.这个问题花了几个月才解决,最后还是完成了.


Sij*_*iju 5

最后我得到了你和我的问题的答案。问题是你需要指定操作 (mMediaSessionCompat.setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE) 即使在更新 mediasession 时也是如此。所以你的代码现在应该看起来像

  private void updateMediaSessionMetaData() {
     int playState = mPlaying
            ? PlaybackStateCompat.STATE_PLAYING
            : PlaybackStateCompat.STATE_PAUSED;
           mMediaSessionCompat.setMetadata(new MediaMetadataCompat.Builder()
                .putString(MediaMetadata.METADATA_KEY_ARTIST, getArtist())
                .putString(MediaMetadata.METADATA_KEY_ALBUM, getAlbum())
                .putString(MediaMetadata.METADATA_KEY_TITLE, getSongTitle())
                .putLong(MediaMetadata.METADATA_KEY_DURATION, duration())
                .putLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER, mSongPosn)
                .putLong(MediaMetadata.METADATA_KEY_NUM_TRACKS, songs.size())
                .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, albumArt)
                .build());
mMediaSessionCompat.setPlaybackState(new PlaybackStateCompat.Builder()
                .setState(playState, position(), 1.0f)
                .setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE| PlaybackStateCompat.ACTION_SKIP_TO_NEXT|PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS).build()); 
Run Code Online (Sandbox Code Playgroud)

更新:为 MediaCallback 和 Receiver 添加了代码

   private final class MediaSessionCallback extends MediaSessionCompat.Callback {

    @Override
    public void onPlay() {
        pausePlayer();
    }
    @Override
    public void onPause() {
        pausePlayer();
    }
    public void onSeekTo(long pos) {
        seek(pos);
    }
    @Override
    public void onSkipToNext() {
        playNext();
    }
    @Override
    public void onSkipToPrevious() {
        playPrev();
    }
}
Run Code Online (Sandbox Code Playgroud)

接收者 :

 public class MusicIntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

        if (intent.getAction().equals(
                android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {

            Intent intent1 = new Intent(MusicService.ACTION_PAUSE);
            intent1.setClass(context,
                    com.xyz.service.MusicService.class);
            // send an intent to our MusicService to telling it to pause the
            // audio
            context.startService(intent1);

        } else if (intent.getAction().equals(Intent.ACTION_MEDIA_BUTTON)) {

            KeyEvent keyEvent = (KeyEvent) intent.getExtras().get(
                    Intent.EXTRA_KEY_EVENT);
            if (keyEvent.getAction() != KeyEvent.ACTION_DOWN)
                return;

            switch (keyEvent.getKeyCode()) {
                case KeyEvent.KEYCODE_HEADSETHOOK:
                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
                    Intent intentToggle = new Intent(
                            MusicService.ACTION_TOGGLE_PLAYBACK);
                    intentToggle.setClass(context,
                            com.xyz.service.MusicService.class);
                    context.startService(intentToggle);
                    break;
                case KeyEvent.KEYCODE_MEDIA_PLAY:
                    Intent intentPlay = new Intent(MusicService.ACTION_PLAY);
                    intentPlay.setClass(context,
                            com.xyz.service.MusicService.class);
                    context.startService(intentPlay);

                    break;
                case KeyEvent.KEYCODE_MEDIA_PAUSE:
                    Intent intentPause = new Intent(MusicService.ACTION_PAUSE);
                    intentPause.setClass(context,
                            com.xyz.service.MusicService.class);
                    context.startService(intentPause);

                    break;
                case KeyEvent.KEYCODE_MEDIA_NEXT:
                    Intent intentNext = new Intent(MusicService.ACTION_NEXT);
                    intentNext.setClass(context,
                            com.xyz.service.MusicService.class);
                    context.startService(intentNext);

                    break;
                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
                    Intent intentPrev = new Intent(MusicService.ACTION_PREV);
                    intentPrev.setClass(context,
                            com.xyz.service.MusicService.class);
                    context.startService(intentPrev);

                    break;
                default:
                    break;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)