当我尝试在运行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 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
我试图按照谷歌的谈话实施媒体按钮控制
我将接收器设置为清单:
<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)
创建MediaSessionCompat
于onCreate()
服务:
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)
? …
在我的应用程序中,我正在利用MediaSessionCompat
媒体播放器服务播放音频.特别是,我想将当前歌曲的元数据广播到蓝牙设备(可以工作),并将锁定屏幕图像设置为当前歌曲的专辑封面.
与此问题类似:在Android中设置锁定屏幕背景(如Spotify do)
每次换歌,我先理清当前MediaMetadataCompat
和PlaybackStateCompat
从MediaSessionCompat
像这样:
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 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函数,发现它正在检查localConfiguration
MediaItem的是否为null:
@Override
public MediaSource createMediaSource(MediaItem mediaItem) {
checkNotNull(mediaItem.localConfiguration);
...
}
Run Code Online (Sandbox Code Playgroud)
这是本地配置:
/** …
Run Code Online (Sandbox Code Playgroud) 我的应用不是媒体播放器.我只想使用新的MediaControllerCompat类来控制当前的媒体播放器.目前我正在使用MediaSessionManager但是想要升级到新的compat类.
当我没有令牌或MediaSessionCompat来实例化它时,如何实例化MediaControllerCompat类?我希望得到一些示例代码.
android android-music-player mediacontroller android-mediasession
背景信息:每当用户按下大多数耳机上的播放/暂停按钮时,我都需要检测(KEYCODE_MEDIA_PLAY_PAUSE).
我拥有它主要使用MediaSessions,但当另一个应用程序开始播放音频时,我停止回调.
这似乎是因为正在播放音频的应用创建了自己的MediaSession,而Android仅将KeyEvents发送到最新的MediaSession.为了防止这种情况,我创建一个OnActiveSessionsChangedListener并在每次触发时创建一个新的MediaSession.
这确实有效,但每次我创建一个新的MediaSession时,监听器再次触发,所以我发现自己陷入了一个inf循环.
我的问题:有谁知道我怎么做以下任何一个??:
什么行不通:
我的代码:
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) 我正在为一家广播电台开发一个简单的音频播放器应用程序.
我已成功制作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) 我无法导入MediaSessionCompat用于导入整个MediaSessionCompat
库的import语句不会显示在Android Studio"IntelliSense"中.它无法解决其中任何内容的符号.
我是否必须进行某种额外配置才能获得此导入功能,例如在应用中android.support.v4.media
?
请有人至少向我解释一下.提前致谢!
我有一个应用程序启动前台服务来播放一些媒体,我希望能够使用智能手表/耳机上的媒体按钮来控制它,并通过媒体样式通知等来控制它。
但我无法让媒体按钮始终如一地工作。在日志中,我可以看到它们经常被发送到其他应用程序,即使我最后启动了 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)