媒体会话兼容未在 Pre-Lollipop 上显示锁屏控件

2024-01-06

我在用着MediaSessionCompat来自 AppCompat 支持库修订版 22。在 Lollipop 上,我收到通知,而且锁屏的背景是专辑封面。一切都很顺利。

在棒棒糖之前的设备上,锁屏上的音乐控件根本不显示。这很奇怪,我尝试了一切,但它没有出现,甚至背景也没有改变。

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

Note: 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();

这是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());

}


媒体会话回调方法

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();
    }
};

媒体按钮接收器清单条目

<!-- 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>

几周以来我一直在尝试解决这个问题,但没有成功,并且迫切需要帮助。

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


虽然没有严格要求MediaSession, RemoteControlClient在 API14-19 设备上使用,确实需要音频焦点 http://developer.android.com/training/managing-audio/audio-focus.html并且 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
}

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

媒体会话兼容未在 Pre-Lollipop 上显示锁屏控件 的相关文章

随机推荐

  • Python,Enum 类型有什么用? [复制]

    这个问题在这里已经有答案了 在Python 3 4中 我们在标准库中得到了一个Enum lib enum 我们可以获得一个向后移植enum适用于 Python 2 4 至 2 7 甚至 3 1 至 3 3 enum34 https pypi
  • Pytest - 访问 class_method 上的 session_scope 固定装置

    我正在使用 celery 固定装置来测试项目上的几个任务 我想知道是否有一种方法可以访问类方法内的会话范围固定装置 默认情况下 芹菜固定装置是会话范围的 引用 pytest mark usefixture celery worker cla
  • 将带有空格的字符串传递给javascript

    我正在尝试将带有空格的 php 定义的字符串传递给 javascript 函数 以便我可以附加到查询字符串 然而 该函数仅在没有空格时才起作用 甚至在有空格时也不会执行 通过使用alert 进行测试 有没有一种方法可以将带有空格的字符串传递
  • 位操作将多个值存储在一个 int C++ 中

    我需要帮助完成一项我似乎无法弄清楚的编程实验室作业 问题是 允许用户输入 4 个整数值 全部在 0 到 15 之间 含 0 和 15 将这 4 个值存储到名为 packit 的单个 32 位整数中 允许用户选择他们希望从 packit 恢复
  • 防止重复图像保存到 SD 卡

    我有一个形成多行的列表活动应用程序 每行打开一个包含视图的活动 其中一个是一个按钮 单击时打开无限图库类 图像存储在应用程序内的 RES gt 可绘制文件夹中 每个图像下面都有按钮 按下时会将图像保存到 SD card 目录中有一个名为 s
  • 如何将单位包与 rmarkdown 一起用于 pdf 文档

    我在 rmarkdown 文档中使用units 包来输出pdf 然而 这些单元既不能作为内联代码运行 也不能作为代码块运行 是否可以使用带有 rmarkdown 的单位 RStudio 中 rmarkdown 文档的 MWE title U
  • 创建一系列 NSTextContainer 时,如何根据文本内容指定容器分隔符?

    我正在创建一系列 NSTextContainer 来保存 HTML 资源中的文本 我可以将 HTML 添加到属性字符串 将其分配给 NSTextStorage 和 NSLayoutManager 并创建一系列 NSTextContainer
  • 如何使用 Application Insight 的持久性通道防止丢失遥测事件?

    我已将 Microsoft Application Insights 集成到我的 Windows 窗体应用程序中 在文件中有关 Windows 桌面应用程序 服务和辅助角色的应用程序见解 https github com Azure azu
  • 图像的随机位置

    我找到了一个可以随机定位 div 图像的脚本 然而 它并没有完全按照我想要 需要的方式工作 每个图像都加载在一个 div 中 我猜这并不理想 我有大约 30 张图片 但它们加载得不好并且var posy Math random docume
  • dotenv gem 在 Rails 6 或 Ruby 2.6.5 中无法获取变量

    我当时用的是多特恩宝石 https github com bkeepers dotenv将开发环境变量存储在机密文件中 在我的计算机上升级 ruby 和 Rails 后 gem 不再提取变量 为了尝试找出原因 经过一段时间尝试不同的选项 我
  • 如何将微秒时间戳转换为日期时间?

    我正在从 Google Chrome 中获取 cookie 过期日期 从表面上看 Chrome 使用 1601 01 01 00 00 00 UTC 作为纪元的时间戳来存储 cookie 过期时间 我目前的实现如下 stamp int re
  • 在音频设备连接/断开时自动收到通知?

    每当用户连接或断开音频设备时是否可以自动收到通知 在 Vista 中 您可以使用 Core AudioIMMNotificationClient 接口 http msdn microsoft com en us library window
  • Sidekiq - 无法在 5.000 秒内获得数据库连接

    我在 os x 上开发 Rails 4 和 Sidekiq 时收到以下警告 10 13 39 worker 1 2014 09 22T07 13 39 857Z 86981 TID oug0oog10 WARN could not obta
  • 如何在OpenCart中设置配置?

    警告 require once sgweb1 minufashion system startup php function require once 无法打开流 没有这样的文件或 目录在 D inetpub vhosts sgwebgen
  • 从可访问性的角度来看,我应该更喜欢

    这个问题在这里已经有答案了 通常 在书籍 教程和一些实际网页中 我看到导航栏标记为 li a 中的 s 元素 ul 中的元素 ul li
  • 类型错误:无法连接“str”和“type”对象

    在解决我的问题之前 我已经四处寻找答案 但似乎找不到任何针对我的情况的信息 好的 基本上我通过 cmd 调用我的脚本并传入 16 个参数并使用它们来设置我拥有的一些变量 我正在创建一个自定义 html 报告供我们公司使用 我只是用这些变量来
  • pandas.read_excel() 输出“OverflowError:日期值超出范围”,而不存在日期列

    我正在尝试将一个大的 Excel 文件 400k x 40 导入到 Pandas DataFrame 中 虽然它在我的本地计算机上运行良好 但在移植到 Python 3 7 Pandas 1 2 4 和 Openpyxl 3 0 7 的 L
  • 如何在配置文件中隐藏数据库密码

    我正在开发一个 C 项目 该项目需要访问数据库以读取其输入 到目前为止 我们使用了默认用户名 postgres 和存储在基于 xml 的配置文件中的 固定明文 密码以及许多其他设置 现在我需要的是在提供配置文件时向用户隐藏密码 FYI 开发
  • gulp 构建语义用户界面非常慢

    我已经为此搜索了好几天 但运气不佳 我通过 NPM 通过 Laravel 安装安装了 Semantic UI 我修改了项目根目录中的 gulpfile js 以导入语义 UI 的构建和监视任务 var elixir require lara
  • 媒体会话兼容未在 Pre-Lollipop 上显示锁屏控件

    我在用着MediaSessionCompat来自 AppCompat 支持库修订版 22 在 Lollipop 上 我收到通知 而且锁屏的背景是专辑封面 一切都很顺利 在棒棒糖之前的设备上 锁屏上的音乐控件根本不显示 这很奇怪 我尝试了一切