在 Android 中设置锁屏背景(如 Spotify)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22281616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:46:39  来源:igfitidea点击:

Set lock screen background in Android (like Spotify do)

android

提问by Nifhel

I know that this topic has been already discussed here, hereand here, and the answer seems to be that it is not possible.

我知道这里这里这里已经讨论过这个话题,答案似乎是不可能的。

But I recently installed Spotify in my Nexus 4 (4.4.2), and it seems to be possible. When I listen a song in Spotify the lock screen background change with the cover of the album that I'm listening (see screenshots).

但我最近在我的 Nexus 4 (4.4.2) 中安装了 Spotify,这似乎是可能的。当我在 Spotify 中听一首歌时,锁屏背景会随着我正在听的专辑封面而改变(见截图)。

My theory was: when the phone is locked they change the phone wallpaperwith the album cover in order to change also the lock screen background, then they set back the previous one when the phone is unlocked. But this is not how they do it, because in the permissions list of Spotify there is no "android.permission.SET_WALLPAPER"... :(

我的理论是:当手机被锁定时,他们将手机壁纸与专辑封面一起更改,以更改锁屏背景,然后在手机解锁时将之前的背景调回原位。但这不是他们的做法,因为在 Spotify 的权限列表中没有“android.permission.SET_WALLPAPER”... :(

How do they do it? Some theory?

他们是怎么做到的呢?一些理论?

Screenshot lock screenScreenshot lock screen

截图锁屏截图锁屏

采纳答案by Kai

Edit:The solution below only works for applications that have registered itself as a media controller, so apps that don't play audio can't/shouldn't use this mechanism to change the lockscreen wallpaper.

编辑:下面的解决方案仅适用于已将自身注册为媒体控制器的应用程序,因此不播放音频的应用程序不能/不应使用此机制来更改锁屏壁纸。



It can be done using RemoteControlClient, part of Android since ICS. If you want a working example, download VLC for Android and check out org.videolan.vlc.AudioService:

它可以使用RemoteControlClient完成,这是自 ICS 以来 Android 的一部分。如果您想要一个工作示例,请下载适用于 Android 的 VLC 并查看org.videolan.vlc.AudioService

This part of the code is to intercept media controls.

这部分代码是拦截媒体控件。

/**
 * Set up the remote control and tell the system we want to be the default receiver for the MEDIA buttons
 * @see http://android-developers.blogspot.fr/2010/06/allowing-applications-to-play-nicer.html
 */
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void setUpRemoteControlClient() {
    Context context = VLCApplication.getAppContext();
    AudioManager audioManager = (AudioManager)context.getSystemService(AUDIO_SERVICE);

    if(Util.isICSOrLater()) {
        audioManager.registerMediaButtonEventReceiver(mRemoteControlClientReceiverComponent);

        if (mRemoteControlClient == null) {
            Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
            mediaButtonIntent.setComponent(mRemoteControlClientReceiverComponent);
            PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(context, 0, mediaButtonIntent, 0);

            // create and register the remote control client
            mRemoteControlClient = new RemoteControlClient(mediaPendingIntent);
            audioManager.registerRemoteControlClient(mRemoteControlClient);
        }

        mRemoteControlClient.setTransportControlFlags(
                RemoteControlClient.FLAG_KEY_MEDIA_PLAY |
                RemoteControlClient.FLAG_KEY_MEDIA_PAUSE |
                RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS |
                RemoteControlClient.FLAG_KEY_MEDIA_NEXT |
                RemoteControlClient.FLAG_KEY_MEDIA_STOP);
    } else if (Util.isFroyoOrLater()) {
        audioManager.registerMediaButtonEventReceiver(mRemoteControlClientReceiverComponent);
    }
}

This part is to update artwork, among other info:

这部分是更新艺术品,以及其他信息:

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void updateRemoteControlClientMetadata() {
    if(!Util.isICSOrLater()) // NOP check
        return;

    if (mRemoteControlClient != null) {
        MetadataEditor editor = mRemoteControlClient.editMetadata(true);
        editor.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, getCurrentMedia().getAlbum());
        editor.putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, getCurrentMedia().getArtist());
        editor.putString(MediaMetadataRetriever.METADATA_KEY_GENRE, getCurrentMedia().getGenre());
        editor.putString(MediaMetadataRetriever.METADATA_KEY_TITLE, getCurrentMedia().getTitle());
        editor.putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, getCurrentMedia().getLength());
        editor.putBitmap(MetadataEditor.BITMAP_KEY_ARTWORK, getCover());
        editor.apply();
    }
}

回答by Juuso Ohtonen

For me, the most instructive example was Random Music Player, mentioned in documentation about Android 4.0 APIs:

对我来说,最有启发性的例子是Random Music Player,在关于 Android 4.0 API 的文档中提到:

"For a sample implementation, see the Random Music Player, which provides compatibility logic such that it enables the remote control client on Android 4.0 devices while continuing to support devices back to Android 2.1."

“有关示例实现,请参阅 Random Music Player,它提供了兼容性逻辑,以便在 Android 4.0 设备上启用远程控制客户端,同时继续支持返回 Android 2.1 的设备。”

In addition, I converted text to bitmapto have text as album art.

此外,我将文本转换为位图以将文本作为专辑封面。

回答by Carlos Anyona

Well, after trying some ways, I have a simple code here; Try using this method;

嗯,在尝试了一些方法之后,我这里有一个简单的代码;尝试使用这种方法;

private void updateMetaData() {
    mediaSession =new MediaSessionCompat(context,"BXPlayer");

    Bitmap cover = BitmapFactory.decodeResource(context.getResources(),
            R.drawable.cover2); 

   mediaSession.setMetadata(new MediaMetadataCompat.Builder()
            .putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, cover)
            .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, mSelectedSong.getArtist())
            .putString(MediaMetadataCompat.METADATA_KEY_ALBUM, mSelectedSong.getAlbum())
            .putString(MediaMetadataCompat.METADATA_KEY_TITLE, mSelectedSong.getTitle())
            .build());
}

then in your notification you need to set style to android.support.v4.media.app.NotificationCompat.MediaStyle()and set the media session token to use the current metadata. Check this snippet below;

然后在您的通知中,您需要将样式设置为android.support.v4.media.app.NotificationCompat.MediaStyle()并设置媒体会话令牌以使用当前元数据。检查下面的这个片段;

builder.setStyle(new android.support.v4.media.app.NotificationCompat.MediaStyle()
            .setShowActionsInCompactView(0, 1, 2)
    .setMediaSession(mediaSession.getSessionToken()));
    return builder.build();

To work, you must include implementation "com.android.support:support-v4:$latest_version"in your app build.gradleAnd boom! you are good to go.

要工作,您必须implementation "com.android.support:support-v4:$latest_version"在您的应用程序中包含build.gradle和繁荣!你已准备好出发。

回答by JoshuaTree

So here is the new "official docs"

所以这是新的“官方文档”

At the bottom it describes the lock screen details

在底部它描述了锁屏细节

https://developer.android.com/guide/topics/media-apps/working-with-a-media-session.html#maintain-state

https://developer.android.com/guide/topics/media-apps/working-with-a-media-session.html#maintain-state

As an alternative, once I understood all the terms and jargon, this tutorial helped me outline the general structure for the MediaSessionCompat services.

作为替代方案,一旦我理解了所有术语和行话,本教程将帮助我概述 MediaSessionCompat 服务的一般结构。

https://code.tutsplus.com/tutorials/background-audio-in-android-with-mediasessioncompat--cms-27030

https://code.tutsplus.com/tutorials/background-audio-in-android-with-mediasessioncompat--cms-27030

Finally, there is an API for lock screen wallpaper in Nougat and greater. Why this is not support lib is beyond me at this time.

最后,Nougat 及更高版本有一个用于锁屏壁纸的 API。为什么这不是支持 lib 目前我无法理解。

回答by Sameer J

as explained herethe key is to to pass a MediaMetadata object to your MediaSession. If these terms seems alien to you it's best to start the linked tutorial from the top.

如此所述,关键是将 MediaMetadata 对象传递给您的 MediaSession。如果这些术语对您来说似乎陌生,最好从顶部开始链接教程。

I found the .putBitmap(MediaMetadata.METADATA_KEY_ART, bitmap)line to be the one that is taken to load the image to the lockscreen background. But be sure to populate .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap)as well.

我发现该.putBitmap(MediaMetadata.METADATA_KEY_ART, bitmap)行是将图像加载到锁屏背景的行。但一定要填充.putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap)