Android:在Chromecast上获取当前正在播放的媒体吗? [英] Android: Get current playing media on Chromecast?

查看:53
本文介绍了Android:在Chromecast上获取当前正在播放的媒体吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一款可控制Chromecast以及其上正在播放的内容的应用.

I'm working on an app that controls the Chromecast and whatever's playing on it.

我不需要发件人应用程序,我不想注册任何东西以获得api密钥,而这些都没有.

I don't want a sender app, I don't want to register anything to get an api key, none of that stuff.

到目前为止,我正在使用MediaRouter来控制音量并查看其是否连接到任何东西.

I'm using so far MediaRouter to control the volume and to see if it's connected to anything.

但是我想要类似Google Cast的应用程序

But I want something like the Google Cast app:

知道什么正在播放以及(或至少)播放状态.

Which knows what's playing and (or at least) the playback state.

理想情况下,我不想使用Google Play服务,但是如果这是唯一的方法,那就来吧.

Ideally I wouldn't want to use google play services, but if it's the only way, c'est la vie.

推荐答案

我终于知道了.我不得不使用Google Play服务和Google Cast sdk v2,但没有注册该应用程序.

I finally figured it out. I had to use the google play services and the google cast sdk v2 but without registering the application.

项目中包含的库:

compile 'com.android.support:mediarouter-v7:24.0.0' 
compile 'com.google.android.gms:play-services-cast-framework:9.2.0' 

请注意,在下面的代码中,onCreate()和onDestroy()不是Activity,Fragment或Service中的方法,因此请不要复制/粘贴代码并期望它可以工作.这些方法中的代码必须复制/粘贴到您自己的方法中.

Beware that in the code below onCreate() and onDestroy() aren't methods in an Activity, Fragment or Service, so don't copy/paste the code and expect it works. The code in those methods must pe copy/pasted in your own methods.

这是正在发生的步骤:

  1. 您可以通过投射按钮选择一条路由,方法是调用getActiveMediaRoute()来检查哪个Chromecast是活动的(如果没有人连接到Chromecast,则该路由将不起作用).覆盖要根据您的偏好选择的方法或getActiveChromecastRoute()
  2. 调用onRouteSelected()时,将使用选定的Chromecast的选项实例化新的Cast GoogleApiClient
  3. 调用onApplicationMetadataChanged()时,代码将连接到在Chromecast上运行的当前应用程序
  4. 成功连接应用程序后,将实例化一个新的RemoteMediaPlayer并请求MediaStatus
  5. 您应该在onStatusUpdated()中获得一个回调,然后您可以调用mRemoteMediaPlayer.getMediaStatus(),它将包含有关Chromecast正在播放的内容的数据.
  1. You select a route either via the cast button either by calling getActiveMediaRoute() which checks for which Chromecast is active (it won't work if nobody is connected to the Chromecast). Override the method or getActiveChromecastRoute() to select based on your preferences
  2. When onRouteSelected() is called a new Cast GoogleApiClient is instanced with options for the selected chromecast
  3. When onApplicationMetadataChanged() is called the code will connect to the current application running on the Chromecast
  4. After the application is successfully connected a new RemoteMediaPlayer is instanced and the MediaStatus is requested
  5. You should get a callback in onStatusUpdated() and after that you can call mRemoteMediaPlayer.getMediaStatus() and it will contain the data about what's being played on the Chromecast.


public static final String CHROMECAST_SIGNATURE = "cast.media.CastMediaRouteProviderService";

private final MediaRouteSelector mSelector;
private final MediaRouter mMediaRouter;
private CastDevice mSelectedDevice;
private Cast.Listener mCastClientListener;
private RemoteMediaPlayer mRemoteMediaPlayer;

@Override
public void onCreate() {
    mMediaRouter = MediaRouter.getInstance(context);

    mSelector = new MediaRouteSelector.Builder()
            // These are the framework-supported intents
            .addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
            .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
            .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
            .build();

    mMediaRouter.addCallback(mSelector, mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY | MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS);
}

@Override
public void onDestroy() {
    mMediaRouter.removeCallback(mMediaRouterCallback);
}

@UiThread
private boolean isChromecastActive() {
    return getActiveChromecastRoute() != null;
}

@UiThread
private Boolean isChromecastPlaying() {
    if (mRemoteMediaPlayer == null || mRemoteMediaPlayer.getMediaStatus() == null) {
        return null;
    }

    // Here you can get the playback status and the metadata for what's playing
    // But only after the onStatusUpdated() method is called in the mRemoteMediaPlayer callback
    int state = mRemoteMediaPlayer.getMediaStatus().getPlayerState();
    return (state == MediaStatus.PLAYER_STATE_BUFFERING || state == MediaStatus.PLAYER_STATE_PLAYING);
}

@UiThread
private MediaRouter.RouteInfo getActiveChromecastRoute() {
    for (MediaRouter.RouteInfo route : mMediaRouter.getRoutes()) {
        if (isCastDevice(route)) {
            if (route.getConnectionState() == MediaRouter.RouteInfo.CONNECTION_STATE_CONNECTED) {
                return route;
            }
        }
    }

    return null;
}

private int getMediaRouteVolume(@NonNull MediaRouter.RouteInfo route) {
    return route.getVolume();
}

private void setMediaRouteVolume(@NonNull MediaRouter.RouteInfo route, int volume) {
    route.requestSetVolume(volume);
}

private int getMediaRouteMaxVolume(@NonNull MediaRouter.RouteInfo route) {
    return route.getVolumeMax();
}

@UiThread
private MediaRouter.RouteInfo getActiveMediaRoute() {
    if (isChromecastActive()) {
        MediaRouter.RouteInfo route = getActiveChromecastRoute();

        if (route != null) {
            if (!route.isSelected()) {
                mMediaRouter.selectRoute(route);
            }
        }
        else if (mSelectedDevice != null) {
            mSelectedDevice = null;
        }

        return route;
    }

    return null;
}

private boolean isCastDevice(MediaRouter.RouteInfo routeInfo) {
    return routeInfo.getId().contains(CHROMECAST_SIGNATURE);
}

private MediaRouter.Callback mMediaRouterCallback = new MediaRouter.Callback() {
    @Override
    public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo route) {
        if (isCastDevice(route)) {
            Log.i("MediaRouter", "Chromecast found: " + route);
        }
    }

    @Override
    public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
        if (isCastDevice(route)) {
            Log.i("MediaRouter", "Chromecast changed: " + route);
        }
    }

    @Override
    public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo route) {
        if (mSelectedDevice == null && isCastDevice(route)) {
            Log.i("MediaRouter", "Chromecast selected: " + route);

            mSelectedDevice = CastDevice.getFromBundle(route.getExtras());
            mCastClientListener = new Cast.Listener() {
                @Override
                public void onApplicationStatusChanged() {
                    Log.i("MediaRouter", "Cast.Listener.onApplicationStatusChanged()");
                }

                @Override
                public void onApplicationMetadataChanged(ApplicationMetadata applicationMetadata) {
                    Log.i("MediaRouter", "Cast.Listener.onApplicationMetadataChanged(" + applicationMetadata + ")");

                    if (applicationMetadata != null) {
                        LaunchOptions launchOptions = new LaunchOptions.Builder().setRelaunchIfRunning(false).build();
                        Cast.CastApi.launchApplication(mApiClient, applicationMetadata.getApplicationId(), launchOptions).setResultCallback(new ResultCallback<Cast.ApplicationConnectionResult>() {
                            @Override
                            public void onResult(@NonNull Cast.ApplicationConnectionResult applicationConnectionResult) {
                                Log.i("MediaRouter", "Cast.CastApi.joinApplication.onResult() " + applicationConnectionResult.getSessionId());

                                mRemoteMediaPlayer = new RemoteMediaPlayer();
                                mRemoteMediaPlayer.setOnStatusUpdatedListener( new RemoteMediaPlayer.OnStatusUpdatedListener() {
                                    @Override
                                    public void onStatusUpdated() {
                                        MediaStatus mediaStatus = mRemoteMediaPlayer.getMediaStatus();
                                        Log.i("MediaRouter", "Remote media player status " + mediaStatus.getPlayerState());
                                        // TODO: you can call isChromecastPlaying() now
                                    }
                                });

                                try {
                                    Cast.CastApi.setMessageReceivedCallbacks(mApiClient, mRemoteMediaPlayer.getNamespace(), mRemoteMediaPlayer);
                                } catch(IOException e) {
                                    Log.e("MediaRouter", "Exception while creating media channel ", e );
                                } catch(NullPointerException e) {
                                    Log.e("MediaRouter", "Something wasn't reinitialized for reconnectChannels", e);
                                }


                                mRemoteMediaPlayer.requestStatus(mApiClient).setResultCallback(new ResultCallback<RemoteMediaPlayer.MediaChannelResult>() {
                                    @Override
                                    public void onResult(@NonNull RemoteMediaPlayer.MediaChannelResult mediaChannelResult) {
                                        Log.i("MediaRouter", "requestStatus() " + mediaChannelResult);
                                    }
                                });

                                try {
                                    Cast.CastApi.requestStatus(mApiClient);
                                } catch (IOException e) {
                                    Log.e("MediaRouter", "Couldn't request status", e);
                                }
                            }
                        });
                    }
                }

                @Override
                public void onApplicationDisconnected(int i) {
                    Log.i("MediaRouter", "Cast.Listener.onApplicationDisconnected(" + i + ")");
                }

                @Override
                public void onActiveInputStateChanged(int i) {
                    Log.i("MediaRouter", "Cast.Listener.onActiveInputStateChanged(" + i + ")");
                }

                @Override
                public void onStandbyStateChanged(int i) {
                    Log.i("MediaRouter", "Cast.Listener.onStandbyStateChanged(" + i + ")");
                }

                @Override
                public void onVolumeChanged() {
                    Log.i("MediaRouter", "Cast.Listener.onVolumeChanged()");
                }
            };

            Cast.CastOptions.Builder apiOptionsBuilder = new Cast.CastOptions.Builder(mSelectedDevice, mCastClientListener);

            mApiClient = new GoogleApiClient.Builder(getContext())
                    .addApi( Cast.API, apiOptionsBuilder.build() )
                    .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
                        @Override
                        public void onConnected(@Nullable Bundle bundle) {
                            Log.i("MediaRouter", "GoogleApiClient.onConnected()");
                            Log.i("MediaRouter", "Bundle " + bundle);
                        }

                        @Override
                        public void onConnectionSuspended(int i) {
                            Log.i("MediaRouter", "GoogleApiClient.onConnectionSuspended(" + i + ")");
                        }
                    })
                    .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
                        @Override
                        public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
                            Log.i("MediaRouter", "GoogleApiClient.onConnectionFailed()");
                        }
                    })
                    .build();

            mApiClient.connect();
        }
        else {
            mSelectedDevice = null;
            mRemoteMediaPlayer = null;
        }
    }

    @Override
    public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo route) {
        if (isCastDevice(route)) {
            if (mSelectedDevice != null && mSelectedDevice.isSameDevice(CastDevice.getFromBundle(route.getExtras()))) {
                mSelectedDevice = null;
            }
            Log.i("MediaRouter", "Chromecast lost: " + route);
        }
    }
};

这篇关于Android:在Chromecast上获取当前正在播放的媒体吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆