【问题标题】:Media Control on Lock Screen like Google Play Music in android?锁定屏幕上的媒体控制,如 android 中的 Google Play 音乐?
【发布时间】:2014-07-09 11:08:41
【问题描述】:

我已经阅读了锁屏小部件文档,我实现了它,但这不是自动放置在主锁窗口上的东西。我正在寻找通过主锁屏窗口(在 Jelly Bean 及更高版本中)提供媒体控制的解决方案,例如 Google Play 音乐应用程序。

看看显然不是锁屏小部件的 Google Play 音乐锁。

【问题讨论】:

    标签: android android-appwidget lockscreenwidget


    【解决方案1】:

    您检查过 RemoteControlClient 吗?即使应用程序处于锁定模式,它也可用于 Android 音乐遥控器。(与您附加的图像相同)

    请查看RemoteControlClient

    当您接收到歌曲曲目的播放、暂停、下一个和上一个的命令操作时,只需调用以下方法。

      private void lockScreenControls() {
    
        // Use the media button APIs (if available) to register ourselves for media button
        // events
    
        MediaButtonHelper.registerMediaButtonEventReceiverCompat(mAudioManager, mMediaButtonReceiverComponent);
        // Use the remote control APIs (if available) to set the playback state
        if (mRemoteControlClientCompat == null) {
            Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
            intent.setComponent(mMediaButtonReceiverComponent);
            mRemoteControlClientCompat = new RemoteControlClientCompat(PendingIntent.getBroadcast(this /*context*/,0 /*requestCode, ignored*/, intent /*intent*/, 0 /*flags*/));
            RemoteControlHelper.registerRemoteControlClient(mAudioManager,mRemoteControlClientCompat);
        }
        mRemoteControlClientCompat.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING);
        mRemoteControlClientCompat.setTransportControlFlags(
                RemoteControlClient.FLAG_KEY_MEDIA_PAUSE |
                RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS |
                RemoteControlClient.FLAG_KEY_MEDIA_NEXT |
                RemoteControlClient.FLAG_KEY_MEDIA_STOP);
    
      //update remote controls
        mRemoteControlClientCompat.editMetadata(true)
                .putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, "NombreArtista")
                .putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, "Titulo Album")
                .putString(MediaMetadataRetriever.METADATA_KEY_TITLE, nombreCancion)
                //.putLong(MediaMetadataRetriever.METADATA_KEY_DURATION,playingItem.getDuration())
                        // TODO: fetch real item artwork
                .putBitmap(RemoteControlClientCompat.MetadataEditorCompat.METADATA_KEY_ARTWORK, getAlbumArt())
                .apply();
        }
    }
    

    MediaButtonHelper 类

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    import android.content.ComponentName;
    import android.media.AudioManager;
    import android.util.Log;
    
    /**
     * Class that assists with handling new media button APIs available in API level 8.
     */
    public class MediaButtonHelper {
        // Backwards compatibility code (methods available as of API Level 8)
        private static final String TAG = "MediaButtonHelper";
    
        static {
            initializeStaticCompatMethods();
        }
    
        static Method sMethodRegisterMediaButtonEventReceiver;
        static Method sMethodUnregisterMediaButtonEventReceiver;
    
        static void initializeStaticCompatMethods() {
            try {
                sMethodRegisterMediaButtonEventReceiver = AudioManager.class.getMethod(
                        "registerMediaButtonEventReceiver",
                        new Class[] { ComponentName.class });
                sMethodUnregisterMediaButtonEventReceiver = AudioManager.class.getMethod(
                        "unregisterMediaButtonEventReceiver",
                        new Class[] { ComponentName.class });
            } catch (NoSuchMethodException e) {
                // Silently fail when running on an OS before API level 8.
            }
        }
    
        public static void registerMediaButtonEventReceiverCompat(AudioManager audioManager,
                ComponentName receiver) {
            if (sMethodRegisterMediaButtonEventReceiver == null)
                return;
    
            try {
                sMethodRegisterMediaButtonEventReceiver.invoke(audioManager, receiver);
            } catch (InvocationTargetException e) {
                // Unpack original exception when possible
                Throwable cause = e.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                } else {
                    // Unexpected checked exception; wrap and re-throw
                    throw new RuntimeException(e);
                }
            } catch (IllegalAccessException e) {
                Log.e(TAG, "IllegalAccessException invoking registerMediaButtonEventReceiver.");
                e.printStackTrace();
            }
        }
    
        @SuppressWarnings("unused")
        public static void unregisterMediaButtonEventReceiverCompat(AudioManager audioManager,
                ComponentName receiver) {
            if (sMethodUnregisterMediaButtonEventReceiver == null)
                return;
    
            try {
                sMethodUnregisterMediaButtonEventReceiver.invoke(audioManager, receiver);
            } catch (InvocationTargetException e) {
                // Unpack original exception when possible
                Throwable cause = e.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                } else {
                    // Unexpected checked exception; wrap and re-throw
                    throw new RuntimeException(e);
                }
            } catch (IllegalAccessException e) {
                Log.e(TAG, "IllegalAccessException invoking unregisterMediaButtonEventReceiver.");
                e.printStackTrace();
            }
        }
    }
    

    还请查看此开发者应用程序,了解如何集成 RemoteControlClient:Random Music Player 但是 RemoteControlClient 的 UI 根据设备延迟,您无法将其 UI 更新为您自己的,但您可以控制显示和显示音乐应用的组件和控件。

    更新

    上面提到的类现在已被弃用。因此,请与Media Session 联系并进行相应更新。

    【讨论】:

    • 感谢此代码!但是你能给我们一个关于如何做到这一点的完整教程吗!
    • RemoteController 已弃用,是否有更新教程的链接?
    • 我收到can't resolve MediaButtonHelper 错误。请建议如何消除此错误
    • @AnandSavjani 在答案中添加了 MediaButtonHelper 类。请根据您的需要进行更新。 :)
    • 其中一些方法现已弃用,请检查链接并提供答案请stackoverflow.com/questions/54633202/…
    【解决方案2】:

    RemoteControlClient 是您正在寻找的东西,但现在它已被弃用并已被 MediaSession 取代。

    文档在这里: https://developer.android.com/reference/android/media/session/MediaSession.html

    【讨论】:

    • MediaSession 看起来不错,但它需要 API 21,我仍然必须支持 API 16+
    • 然后使用 MediaSessionCompat 代替@dkzm
    • 它适用于 4.4,但 6.0 显示通知而不是按钮,有什么技巧吗?
    • 如果我们可以通过 mediaSessionCompat 在锁屏/notfctn 上提供播放控制,为什么还要使用 mediaBrowserServiceCompat?
    • @eremzeit:你知道 RemoteViews 是否可以改变锁屏壁纸吗?
    【解决方案3】:

    如果您的媒体控件在通知中运行良好并且媒体控件已显示在锁定屏幕上但无法正常工作,那么您可以按照此代码开始在锁定屏幕上使用媒体控件(播放、暂停、下一个、上一个): -

    private MediaSessionCompat mMediaSessionCompat;  
    private AudioManager audioManager;
    

    在您的服务类的 onCreate 中调用以下方法:

    private void RegisterRemoteClient() {
        audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        assert audioManager != null;
        audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
                AudioManager.AUDIOFOCUS_GAIN);
    
        ComponentName mRemoteControlResponder = new ComponentName(getPackageName(),
                NotificationBroadcast.class.getName());
    
    
        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
                )
                .build();
        mMediaSessionCompat.setPlaybackState(playbackStateCompat);
        mMediaSessionCompat.setCallback(mMediaSessionCallback);
        mMediaSessionCompat.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
    }
    

    现在在服务类中创建这个回调:

    private MediaSessionCompat.Callback mMediaSessionCallback = new MediaSessionCompat.Callback() {
    
        @Override
        public void onPlay() {
            super.onPlay();
            mMediaSessionCompat.setActive(true);
            Log.d("dvmMediaSessionCompat ","onPlay");
            if (PlayerConstants.SONG_PAUSED){
                Controls.playControl(getApplicationContext());
            }
        }
    
        @Override
        public void onPause() {
            super.onPause();
            Log.d("dvmMediaSessionCompat ","onPause");
            if (!PlayerConstants.SONG_PAUSED){
                Controls.pauseControl(getApplicationContext());
            }
            else
                Controls.playControl(getApplicationContext());
    
    
        }
        @Override
        public void onSkipToQueueItem(long queueId) {
    
        }
    
        @Override
        public void onSeekTo(long position) {
    
        }
    
        @Override
        public void onStop() {
            Log.d("dvmMediaSessionCompat ","onStop");
        }
    
        @Override
        public void onSkipToNext() {
            Log.d("dvmMediaSessionCompat ","onSkipToNext");
            Controls.nextControl(getApplicationContext());
        }
    
        @Override
        public void onSkipToPrevious() {
            Log.d("dvmMediaSessionCompat ","onSkipToPrevious");
            Controls.previousControl(getApplicationContext());
        }
    
    };
    

    这就是我所做的并且控件开始工作,我只是忘记在我的 MediaSessionCompat 实例上添加 setCallback,这就是我的控件不起作用的原因。但现在它运行良好。

    注意:Controls.nextControl(context) 这是我添加了我自己的功能来切换歌曲的方法,你可以用你的逻辑替换它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多