标签: android-mediasession

无法在HUAWEI设备上展开RemoteViews:MediaSessionCompat和NotificationCompat.MediaStyle

当我尝试在运行Android 5.0.1的HUAWEI P8 lite设备上显示通知时,我的应用程序崩溃(它在Nexus和Samsung设备上运行正常).我的大部分代码都来自Ian Lake以正确方式播放的视频媒体播放(Big Android BBQ 2015).我的所有代码都在Android服务中.如果我删除代码:

builder.setStyle(new android.support.v7.app.NotificationCompat.MediaStyle()
            .setShowActionsInCompactView(0, 1)
            .setMediaSession(mMediaSessionCompat.getSessionToken()).setShowCancelButton(true)
            .setCancelButtonIntent(MediaStyleHelper.getActionIntent(this, KeyEvent.KEYCODE_MEDIA_STOP)));
Run Code Online (Sandbox Code Playgroud)

然后应用程序不会崩溃,并显示带有图像和标题的通知.但缺少媒体操作按钮.

堆栈跟踪:

FATAL EXCEPTION: 
main Process: com.app.debug, PID: 21600 android.app.RemoteServiceException: 
Bad notification posted from package com.app.demo.debug: Couldn't expand RemoteViews for: 
StatusBarNotification(pkg=com.app.demo.debug user=UserHandle{0} id=1344663 tag=null score=0 key=0|com.app.demo.debug|1344663|null|10121: Notification(pri=0 contentView=com.app.demo.debug/0x109007f vibrate=null sound=null defaults=0x0 flags=0x62 color=0x00000000 category=transport actions=2 vis=PUBLIC))
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1534)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5538)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Run Code Online (Sandbox Code Playgroud)

码:

private void setUpAsForeground(Book book) 
{

    updateMetaData(book);
    startForeground(NOTIFICATION_ID, setupAudioNotification());
}

public void …
Run Code Online (Sandbox Code Playgroud)

android android-notifications android-mediasession

19
推荐指数
1
解决办法
1463
查看次数

Android Media3 会话和控制器 - 播放未开始

我正在尝试实现 Android Media3 MediaSessionService 和 MediaController,但由于某种原因播放无法开始。我究竟做错了什么?我认为我所做的一切都完全按照在后台播放媒体中所述进行。

播放服务.kt

class PlaybackService : MediaSessionService() {

    private var mediaSession: MediaSession? = null

    override fun onCreate() {
        super.onCreate()
        val player = ExoPlayer.Builder(this).build()
        mediaSession = MediaSession.Builder(this, player).build()
    }

    override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? =
        mediaSession

    override fun onDestroy() {
        mediaSession?.run {
            player.release()
            release()
            mediaSession = null
        }
        super.onDestroy()
    }
}
Run Code Online (Sandbox Code Playgroud)

MainActivity.kt

class MainActivity : ComponentActivity() {

    private lateinit var controllerFuture: ListenableFuture<MediaController>
    private lateinit var controller: MediaController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        log("onCreate MainActivity") …
Run Code Online (Sandbox Code Playgroud)

android android-mediaplayer exoplayer android-mediasession android-jetpack-compose

13
推荐指数
1
解决办法
2929
查看次数

第二次调用setActive(true)时,App不会成为首选的MediaButtonReceiver

我试图按照谷歌的谈话实施媒体按钮控制

我将接收器设置为清单:

<receiver android:name="android.support.v4.media.session.MediaButtonReceiver">
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>

<service android:name=".player.PlayFileService">
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</service>
Run Code Online (Sandbox Code Playgroud)

创建MediaSessionCompatonCreate()服务:

    mediaSession = new MediaSessionCompat(getApplicationContext(), "SOUNDPROCESS");
    mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
    PlaybackStateCompat ps = new PlaybackStateCompat.Builder()
            .setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY_PAUSE)
            .build();
    mediaSession.setPlaybackState(ps);
    mediaSession.setCallback(new MediaSessionCompat.Callback() {
        @Override
        public void onPlay() { ...
           }
    });
Run Code Online (Sandbox Code Playgroud)

并处理意图 onStartCommand()

MediaButtonReceiver.handleIntent(mediaSession, intent);
Run Code Online (Sandbox Code Playgroud)

然后,setActive(true);当我获得音频焦点时,然后setActive(false);当我停止播放时,我会打电话.这是第一次,我的应用程序成为首选媒体按钮接收器并接收回调.

但是,如果我在我的应用程序中停止播放,请进入另一个应用程序,如Google Play音乐并开始在那里播放,然后返回我的应用程序并调用setActive(true)Google Play音乐继续接收回调,媒体按钮在我的应用中无效.

根据我的理解,最后一次调用setActive(true)应优先考虑.我已经确认isActive()返回true.我也可以通过MediaSessionCompat每次创建一个新的方法解决这个问题,但这似乎并不理想.

每次打电话时,如何让我的应用程序成为首选的媒体按钮接收器setActive(true)? …

android android-mediasession

11
推荐指数
1
解决办法
1076
查看次数

MediaMetadataCompat METADATA_KEY_ART仅在第一次设置图像

在我的应用程序中,我正在利用MediaSessionCompat媒体播放器服务播放音频.特别是,我想将当前歌曲的元数据广播到蓝牙设备(可以工作),并将锁定屏幕图像设置为当前歌曲的专辑封面.

与此问题类似:在Android中设置锁定屏幕背景(如Spotify do)

每次换歌,我先理清当前MediaMetadataCompatPlaybackStateCompatMediaSessionCompat像这样:

mSession.setActive(false);
mSession.setMetadata(null);
mSession.setPlaybackState(null);
Run Code Online (Sandbox Code Playgroud)

然后,我使用各自的构建器创建这些类的新实例

MediaMetadataCompat metadata = new MediaMetadataCompat.Builder()
        .putString(MediaMetadataCompat.METADATA_KEY_TITLE,
                                songName)
        .putString(MediaMetadataCompat.METADATA_KEY_ARTIST,
                                artistName)
        .putString(MediaMetadataCompat.METADATA_KEY_ALBUM,
                                albumName)
        .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, durationMs)
        .putBitmap(MediaMetadataCompat.METADATA_KEY_ART, bitmap)
        .build();

PlaybackStateCompat state = new PlaybackStateCompat.Builder()
        .setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_PAUSE |
                                    PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)
        .setState(PlaybackStateCompat.STATE_PLAYING, positionMs, 1.0f, SystemClock.elapsedRealtime())
        .build();
Run Code Online (Sandbox Code Playgroud)

然后我在上面设置新的元数据 MediaSessionCompat

mSession.setActive(true);
mSession.setMetadata(metadata);
mSession.setPlaybackState(state);
Run Code Online (Sandbox Code Playgroud)

在我的蓝牙设备上,元数据工作正常,并且每次歌曲更改时都会更改.然而,在我的手机上,锁屏专辑封面仅在第一次更新.我已经确认我设置的位图是新的,但图像不会改变.

我还在服务中创建媒体样式通知,以允许用户通过持久通知和锁定屏幕控制音乐.

NotificationCompat.MediaStyle style = new NotificationCompat.MediaStyle();
style.setShowActionsInCompactView(0, 1, 2, 3, 4);

Intent intent = new Intent(this, DestinationActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

PendingIntent pendingIntent …
Run Code Online (Sandbox Code Playgroud)

android android-mediasession

11
推荐指数
1
解决办法
2071
查看次数

使用media3库时添加MediaItem导致错误

我正在使用最新的Android Media3库,但是我在使用它时发现了一个问题......

我创建了一个MediaSessionService,然后在Activity中获取了 MediaController ,然后当我尝试调用媒体控制器并添加一些 MediaItem 时,发生了错误:

 java.lang.NullPointerException
        at androidx.media3.common.util.Assertions.checkNotNull(Assertions.java:155)
        at androidx.media3.exoplayer.source.DefaultMediaSourceFactory.createMediaSource(DefaultMediaSourceFactory.java:338)
        at androidx.media3.exoplayer.ExoPlayerImpl.createMediaSources(ExoPlayerImpl.java:1164)
        at androidx.media3.exoplayer.ExoPlayerImpl.addMediaItems(ExoPlayerImpl.java:463)
        at androidx.media3.exoplayer.SimpleExoPlayer.addMediaItems(SimpleExoPlayer.java:1146)
        at androidx.media3.common.BasePlayer.addMediaItems(BasePlayer.java:69)
        at androidx.media3.common.BasePlayer.addMediaItem(BasePlayer.java:64)
        at androidx.media3.common.ForwardingPlayer.addMediaItem(ForwardingPlayer.java:90)
        at androidx.media3.session.PlayerWrapper.addMediaItem(PlayerWrapper.java:346)
        at androidx.media3.session.MediaSessionStub.lambda$addMediaItem$28(MediaSessionStub.java:1052)
        at androidx.media3.session.MediaSessionStub$$ExternalSyntheticLambda8.run(Unknown Source:2)
        at androidx.media3.session.MediaSessionStub.lambda$getSessionTaskWithPlayerCommandRunnable$2$androidx-media3-session-MediaSessionStub(MediaSessionStub.java:234)
        at androidx.media3.session.MediaSessionStub$$ExternalSyntheticLambda52.run(Unknown Source:14)
        at androidx.media3.session.MediaSessionStub.lambda$flushCommandQueue$50(MediaSessionStub.java:1479)
        at androidx.media3.session.MediaSessionStub$$ExternalSyntheticLambda58.run(Unknown Source:2)
        at androidx.media3.common.util.Util.postOrRun(Util.java:517)
        at androidx.media3.session.MediaSessionStub.flushCommandQueue(MediaSessionStub.java:1473)
        at androidx.media3.session.MediaControllerImplBase$FlushCommandQueueHandler.handleMessage(MediaControllerImplBase.java:3035)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7813)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Run Code Online (Sandbox Code Playgroud)

于是我检查了DefaultMediaSourceFactory的createMediaSource函数,发现它正在检查localConfigurationMediaItem的是否为null:

  @Override
  public MediaSource createMediaSource(MediaItem mediaItem) {
    checkNotNull(mediaItem.localConfiguration);
    ...
  }
Run Code Online (Sandbox Code Playgroud)

这是本地配置:

/** …
Run Code Online (Sandbox Code Playgroud)

android android-mediaplayer android-mediasession

10
推荐指数
1
解决办法
3906
查看次数

你如何使用MediaControllerCompat来控制当前的玩家?

我的应用不是媒体播放器.我只想使用新的MediaControllerCompat类来控制当前的媒体播放器.目前我正在使用MediaSessionManager但是想要升级到新的compat类.

当我没有令牌或MediaSessionCompat来实例化它时,如何实例化MediaControllerCompat类?我希望得到一些示例代码.

android android-music-player mediacontroller android-mediasession

8
推荐指数
1
解决办法
2973
查看次数

始终接收所有Android媒体按钮事件的回调(即使其他应用正在播放音频)

背景信息:每当用户按下大多数耳机上的播放/暂停按钮时,我都需要检测(KEYCODE_MEDIA_PLAY_PAUSE).

我拥有它主要使用MediaSessions,但当另一个应用程序开始播放音频时,我停止回调.

这似乎是因为正在播放音频的应用创建了自己的MediaSession,而Android仅将KeyEvents发送到最新的MediaSession.为了防止这种情况,我创建一个OnActiveSessionsChangedListener并在每次触发时创建一个新的MediaSession.

这确实有效,但每次我创建一个新的MediaSession时,监听器再次触发,所以我发现自己陷入了一个inf循环.

我的问题:有谁知道我怎么做以下任何一个??:

  • 防止其他应用窃取我的媒体按钮焦点
  • 当我将媒体按钮焦点丢失到另一个应用程序时检测到,所以我只能创建一个新的MediaSession,而不是每当活动会话改变时
  • 检查我当前是否已经有媒体按钮焦点,所以我不必要地创建一个新的MediaSession

什么行不通:

  • AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION上的BroadcastReceiver不起作用,因为应用程序必须手动触发该广播,而许多应用程序,如NPR One不
  • AudioManager.OnAudioFocusChangeListener不起作用,因为它需要我有音频焦点
  • Broadcast.Receiver在android.intent.action.MEDIA_BUTTON上具有最高优先级并调用abortBroadcast(),但当其他应用程序播放音频时,我的接收器未被触发.此外,其他应用程序也可以设置最高优先级.

我的代码:

mMediaSessionManager.addOnActiveSessionsChangedListener(controllers -> {
    boolean updateButtonReceiver = false;

    // recreate MediaSession if another app handles media buttons
    for (MediaController mediaController : controllers) {
        if (!TextUtils.equals(getPackageName(), mediaController.getPackageName())) {
            if ((mediaController.getFlags() & (MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS)) != 0L) {
                updateButtonReceiver = true;
            }
        }

    }

    if (updateButtonReceiver) {
        // using a handler with a delay of about 2 seconds because this listener fires very often.
        mAudioFocusHandler.removeCallbacksAndMessages(null); …
Run Code Online (Sandbox Code Playgroud)

android android-mediasession

8
推荐指数
1
解决办法
5731
查看次数

onMetadataChanged从未调用过MediaControllerCompat.Callback

我正在为一家广播电台开发一个简单的音频播放器应用程序.
我已成功制作MediaBrowser并注册了一个回调来监听playBack- 或metadata更改.

var mediaBrowser : MediaBrowserCompat by Delegates.notNull()
mediaBrowser = MediaBrowserCompat(
        activity,
        ComponentName(activity, MediaPlaybackService::class.java),
        object : MediaBrowserCompat.ConnectionCallback() {
            override fun onConnected() {
                val mediaController = MediaControllerCompat(activity, mediaBrowser.sessionToken)
                MediaControllerCompat.setMediaController(activity, mediaController)
                mediaController.registerCallback(ControllerCallback)
                mediaControllerFunc()
            }
        },
        null
)

object ControllerCallback : MediaControllerCompat.Callback() {
    override fun onMetadataChanged(metadata: MediaMetadataCompat) {
        //TODO: Never called
    }

    override fun onPlaybackStateChanged(state: PlaybackStateCompat) {
        //Called
    }
}
Run Code Online (Sandbox Code Playgroud)

playback当我打电话收到的变化

mediaSession.setPlaybackState(
    PlaybackStateCompat.Builder()
            .setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE)
            .setState(STATE_PLAYING, DEFAULT_PLAYBACK_POSITION, DEFAULT_PLAYBACK_SPEED)
            .build()
)
Run Code Online (Sandbox Code Playgroud)

但元数据更改不是.
即使我打电话

mediaSession.setMetadata(
    MediaMetadataCompat.Builder()
        .putLong(METADATA_KEY_DURATION, …
Run Code Online (Sandbox Code Playgroud)

audio android android-mediaplayer android-mediasession

8
推荐指数
1
解决办法
1328
查看次数

无法解析符号'MediaSessionCompat'

我无法导入MediaSessionCompat用于导入整个MediaSessionCompat库的import语句不会显示在Android Studio"IntelliSense"中.它无法解决其中任何内容的符号.

我是否必须进行某种额外配置才能获得此导入功能,例如在应用中android.support.v4.media

请有人至少向我解释一下.提前致谢!

android android-mediasession

8
推荐指数
2
解决办法
2445
查看次数

捕获 Android 媒体按钮事件

我有一个应用程序启动前台服务来播放一些媒体,我希望能够使用智能手表/耳机上的媒体按钮来控制它,并通过媒体样式通知等来控制它。

但我无法让媒体按钮始终如一地工作。在日志中,我可以看到它们经常被发送到其他应用程序,即使我最后启动了 MediaSession 和播放。

但尽管有一个媒体会话,我在其中 setActive(true) 并定义了媒体回调,但我无法让它工作?

显现:

<service
    android:name=".services.MediaControllerService"
    android:enabled="true"
    android:exported="true"
    android:permission="android.permission.FOREGROUND_SERVICE">
    <intent-filter android:priority="999">
        <action android:name="android.intent.action.MEDIA_BUTTON"/>
    </intent-filter>
</service>
Run Code Online (Sandbox Code Playgroud)

代码(注意这些包,在 android 10 中很难找到一起工作并给我 MediaStyle 的正确包组合)...

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioAttributes;
import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.media.MediaMetadata;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.view.KeyEvent;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.media.session.MediaButtonReceiver;

public class TextToSpeechMediaControllerService extends Service { 
    public static final String START_SERVICE_ACTION_INTENT = "serviceStart";
    private TextToSpeechPlayer player;
    private MediaMetadataCompat mediaMetaData; …
Run Code Online (Sandbox Code Playgroud)

android android-mediaplayer android-mediasession androidx

8
推荐指数
1
解决办法
7261
查看次数