AudioManager#registreMediaButtonBroadcastReceiver(PendingIntent);
/**
* @hide
* no-op if (pi == null) or (eventReceiver == null)
*/
public void registerMediaButtonIntent(PendingIntent pi, ComponentName eventReceiver) {
if (pi == null) {
Log.e(TAG, "Cannot call registerMediaButtonIntent() with a null parameter");
return;
}
MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext());
helper.addMediaButtonListener(pi, eventReceiver, getContext());
}
下面看下MediaSessionLegacyHelper#addMediaButtonListener():
public void addMediaButtonListener(PendingIntent pi, ComponentName mbrComponent,
Context context) {
if (pi == null) {
Log.w(TAG, "Pending intent was null, can't addMediaButtonListener.");
return;
}
SessionHolder holder = getHolder(pi, true);
if (holder == null) {
return;
}
if (holder.mMediaButtonListener != null) {
// Already have this listener registered
if (DEBUG) {
Log.d(TAG, "addMediaButtonListener already added " + pi);
}
}
holder.mMediaButtonListener = new MediaButtonListener(pi, context);
// TODO determine if handling transport performer commands should also
// set this flag
holder.mFlags |= MediaSession.FLAG_HANDLES_MEDIA_BUTTONS;
holder.mSession.setFlags(holder.mFlags);
holder.mSession.setMediaButtonReceiver(pi);
holder.update();
if (DEBUG) {
Log.d(TAG, "addMediaButtonListener added " + pi);
}
}
其中在getHolder()中用到了mSessions,是一个ArrayMap。
holder.mSession.setMediaButtonReceiver(pi);分析这句:其中mSession是MediaSession类型
/**
* Set a pending intent for your media button receiver to allow restarting
* playback after the session has been stopped. If your app is started in
* this way an {@link Intent#ACTION_MEDIA_BUTTON} intent will be sent via
* the pending intent.
*
* @param mbr The {@link PendingIntent} to send the media button event to.
*/
public void setMediaButtonReceiver(@Nullable PendingIntent mbr) {
try {
mBinder.setMediaButtonReceiver(mbr);
} catch (RemoteException e) {
Log.wtf(TAG, "Failure in setMediaButtonReceiver.", e);
}
}
其中用到了mBinder(ISession),这是一个IInterface,就肯定是把Receiver注册到一个远程对象中了,就是一个注册到一个系统服务中,而这个系统服务持有这个ISession实例。MediaSession应该是媒体会话的意思
它的实现者是private final class SessionStub extends ISession.Stub,而SessionStub是MediaSessionRecord的内部类。
SessionStub#setMediaButtonReceiver()
@Override
public void setMediaButtonReceiver(PendingIntent pi) {
mMediaButtonReceiver = pi;
}
由上可知SessionStub和一个媒体会话,即一个MediaButtonReceiver对应。MediaSession和MediaSessionRecord也是。
那在AudioManager注册完Receiver后,AudioManager在截取了ACTION_MEDIA_BUTTONG广播后是如果分配给这些Receiver的,下面接着分析:
MediaSessionLegacyHelper#sendMediaButtonEvent(KeyEvent keyEvent, boolean needWakeLock)是入口:
public void sendMediaButtonEvent(KeyEvent keyEvent, boolean needWakeLock) {
if (keyEvent == null) {
Log.w(TAG, "Tried to send a null key event. Ignoring.");
return;
}
mSessionManager.dispatchMediaKeyEvent(keyEvent,

本文详细介绍了在Android 7.0中如何注册MediaButtonBroadcastReceiver,以及AudioManager如何处理ACTION_MEDIA_BUTTON广播。通过分析MediaSessionLegacyHelper、MediaSessionRecord和SessionManagerImpl的内部机制,揭示了媒体会话的优先级分配规则,特别是MediaSessionStack的getPriorityLocked方法在确定优先级时的角色。同时,讨论了如何提高MediaButton事件的处理优先级,以及可能的策略应对焦点抢夺问题。
最低0.47元/天 解锁文章
1073

被折叠的 条评论
为什么被折叠?



