我有一个 Android Auto 应用程序。我想利用分页在应用程序内浏览。您似乎可以通过获取对 MediaBrowserCompat 的引用并将这些常量传递给 .subscribe() 来设置 EXTRA_PAGE 和 EXTRA_PAGE_SIZE。但是,我不知道如何获取对 Android Auto Audio 用于调用 .subscribe() 的 MediaBrowserCompat 的引用。
对于应该简单的事情来说,这似乎太复杂了,我只是想太多了吗?
我有一个 Android Auto 应用程序。我想利用分页在应用程序内浏览。您似乎可以通过获取对 MediaBrowserCompat 的引用并将这些常量传递给 .subscribe() 来设置 EXTRA_PAGE 和 EXTRA_PAGE_SIZE。但是,我不知道如何获取对 Android Auto Audio 用于调用 .subscribe() 的 MediaBrowserCompat 的引用。
对于应该简单的事情来说,这似乎太复杂了,我只是想太多了吗?
如何获取对 Android Auto MediaBrowser 的引用?为此,您应该知道包名和类名(如果您尝试将其绑定到应用程序之外)。如果您不知道这些详细信息,则可以从包管理器中获取所有信息。
final Intent providerIntent =
new Intent(MediaBrowserService.SERVICE_INTERFACE);
List<ResolveInfo> mediaApps =
mPackageManager.queryIntentServices(providerIntent, 0);
for (ResolveInfo info : mediaApps) {
new MediaBrowserCompat(context,
new ComponentName(info.serviceInfo.packageName,
info.serviceInfo.name), mConnectionCallbacks, null);
}
如何设置 EXTRA_PAGE 和 EXTRA_PAGE_SIZE?
Bundle bundle = new Bundle();
bundle.putInt(MediaBrowserCompat.EXTRA_PAGE, 1);
bundle.putInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, 1);
mBrowser.subscribe("__SOME_ID__", bundle, callback);
如果您在服务端使用捆绑包覆盖 onLoadChildren(),那么您也必须处理分页逻辑。您可以通过仅覆盖不带捆绑包的 onLoadChildren 来绕过它。
请注意:通常在 Android 中,当您在末尾看到 compat 后缀时,它是没有 compat 的新(增强)版本。
MediaActivity 不是特殊的Activity,它是一种Activity,专门用来播放音乐。而且,当您询问 MediaBrowserCompat 和 MediaBrowserServiceCompat 时,我将我的默认架构(下面介绍的架构 2)更改为架构 1(下面介绍的架构 1,它是版本 22 中新引入的),只是为了给出您所要求的确切答案。
两种架构是:
建筑1)
1) MediaActivity <--uses----> MediaBrowserCompat <---uses--> MediaServiceBrowserCompat <----> MediaSessionCompat <---> MediaSession <--pass session token --> MediaControllerCompat <-- it also passes token to create --> MediaController /* latest API introduced in 22 */
2)
<service android:name=".MyMediaBrowserServiceCompat"
android:label="@string/service_name" >
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
3) Uses MediaSessionCompat to control music playing.
4) Once a session is created the owner of the session may pass its session token to other processes to allow them to create a MediaControllerCompat to interact with the session.
5) A MediaController can be created if you have a MediaSessionCompat.Token from the session owner.
现在,您创建了 MediaController
从这里开始,两种架构都做同样的事情。
建筑2)
1)MediaActivity <--uses----> MediaBrowser <---uses--> MediaServiceBrowser /* old one introduced in 21. This is default */
2)
<service android:name=".MyMediaBrowserService"
android:label="@string/service_name" >
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
3) Uses MediaSession to control music playing
4) Once a session is created the owner of the session may pass its session token to other processes to allow them to create a MediaController to interact with the session.
5) A MediaController can be created through MediaSessionManager if you hold the "android.permission.MEDIA_CONTENT_CONTROL" permission or are an enabled notification listener or by getting a MediaSession.Token directly from the session owner.
现在,您创建了 MediaController
从这里开始,两种架构都做同样的事情。
注意:默认情况下,当您创建 Android Auto 项目时,它仍然使用架构 2,但是,我使用的是架构 1,因为您要求通过 MediaBrowserCompat 进行。所以,你在这里可能会有点困惑。
由于确切的实现有点长,所以我提供了确切的链接,您可以通过 MediaBrowserCompat 方式找到实现(架构 1) https://github.com/googlesamples/android-MediaBrowserService
我在这里发布基于架构的基本代码——因为它是版本 22 中引入的新代码——足以展示如何获得 MediaBrowserCompat 参考。
mConnectionCallbacks 是将 MediaServiceBrowserCompat 与 MediaBrowserCompat 连接起来的主要内容。MediaBrowserCompat 控制由 MediaServiceBrowserCompat 提供的媒体。适合用于控制媒体的活动称为 MediaActivity。MediaActivity 使用 MediaBrowserCompat 来控制媒体(例如,音量、播放变化等)。MediaBrowserCompat 设置 mConnectionCallbacks 进一步具有 onConnected() 等方法,您可以在其中放置自己的逻辑。
public class MyMediaActivity /* can be any activity */ extends AppCompatActivity {
private MediaBrowserCompat mMediaBrowserCompat; /* your reference here */
MediaControllerCompat mediaController = MediaControllerCompat.getMediaController(MyMediaActivity.this);
MediaControllerCompat.Callback controllerCallback =
new MediaControllerCompat.Callback() {
@Override
public void onMetadataChanged(MediaMetadataCompat metadata) {
}
@Override
public void onPlaybackStateChanged(PlaybackStateCompat state) {
}
};
private MediaBrowserCompat.ConnectionCallback mConnectionCallbacks =
new MediaBrowserCompat.ConnectionCallback() {
@Override
public void onConnected() {
// Get the token for the MediaSession
MediaSessionCompat.Token token = mMediaBrowserCompat.getSessionToken();
// Create a MediaControllerCompat
MediaControllerCompat mediaController =
null;
try {
mediaController = new MediaControllerCompat(MyMediaActivity.this, // Context
token);
} catch (RemoteException e) {
e.printStackTrace();
}
// Save the controller
MediaControllerCompat.setMediaController(MyMediaActivity.this, mediaController);
// Finish building the UI
buildTransportControls();
}
@Override
public void onConnectionSuspended() {
// The Service has crashed. Disable transport controls until it automatically reconnects
}
@Override
public void onConnectionFailed() {
// The Service has refused our connection
}
};
void buildTransportControls() {
/* you can define your view to control music here */
/* your stuffs here */
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Display the initial state
MediaMetadataCompat metadata = mediaController.getMetadata();
PlaybackStateCompat pbState = mediaController.getPlaybackState();
// Register a Callback to stay in sync
mediaController.registerCallback(controllerCallback);
mConnectionCallbacks = new MediaBrowserCompat.ConnectionCallback();
/* your MediaBrowserCompat instance reference here*/
mMediaBrowserCompat = new MediaBrowserCompat(this,
new ComponentName(this, MyMediaBrowserServiceCompat.class),
mConnectionCallbacks,
null); // optional Bundle
/* now you can call subscribe() callbacks via mMediaBrowserCompat.subscribe(.....) anywhere inside this Activity's
lifecycle callbacks
*/
}
@Override
public void onStart() {
super.onStart();
mMediaBrowserCompat.connect();
}
@Override
public void onStop() {
super.onStop();
// (see "stay in sync with the MediaSession")
if (MediaControllerCompat.getMediaController(MyMediaActivity.this) != null) {
MediaControllerCompat.getMediaController(MyMediaActivity.this).unregisterCallback(controllerCallback);
}
mMediaBrowserCompat.disconnect();
}
}
而且,现在,您可以创建MediaBrowserServiceCompat /* 注意MediaBrowserServiceCompat 是服务*/ 如下。
public class MyMediaBrowserServiceCompat extends MediaBrowserServiceCompat {
/* various calbacks here */
}
如需更多研究,您可以阅读此链接,它准确地解释了我上面提出的逻辑。 https://developer.android.com/guide/topics/media-apps/audio-app/building-a-mediabrowser-client.html#connect-ui-and-mediacontroller