Android:在Chromecast上获取当前播放媒体?

Android:在Chromecast上获取当前播放媒体?,android,google-cast,Android,Google Cast,我正在开发一个控制Chromecast和它上面播放的任何东西的应用程序 我不想要一个发送者应用程序,我不想注册任何东西来获取api密钥,这些都不是 到目前为止,我正在使用MediaRouter来控制音量,并查看它是否连接到任何东西 但我想要像Google Cast这样的应用程序: 它知道正在播放什么和(或至少)播放状态 理想情况下,我不想使用google play服务,但如果这是唯一的方法,那就是生活。我终于找到了答案。我不得不使用google play服务和google cast sdk v

我正在开发一个控制Chromecast和它上面播放的任何东西的应用程序

我不想要一个发送者应用程序,我不想注册任何东西来获取api密钥,这些都不是

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

但我想要像Google Cast这样的应用程序:

它知道正在播放什么和(或至少)播放状态


理想情况下,我不想使用google play服务,但如果这是唯一的方法,那就是生活。

我终于找到了答案。我不得不使用google play服务和google cast sdk v2,但没有注册应用程序

项目中包含的库:

compile 'com.android.support:mediarouter-v7:24.0.0' 
compile 'com.google.android.gms:play-services-cast-framework:9.2.0' 
请注意,在下面的代码中,onCreate()和onDestroy()不是活动、片段或服务中的方法,因此不要复制/粘贴代码并期望它能正常工作。这些方法中的代码必须复制/粘贴到您自己的方法中

以下是正在发生的事情的步骤:

  • 您可以通过cast按钮或调用getActiveMediaRoute()来选择路由,该路由检查哪个Chromecast处于活动状态(如果没有人连接Chromecast,则该路由将不起作用)。重写方法或getActiveChromecastRoute()以根据您的首选项进行选择
  • 调用onRouteSelected()时,将实例化一个新的Cast GoogleAppClient,其中包含所选chromecast的选项
  • 调用onApplicationMetadataChanged()时,代码将连接到Chromecast上运行的当前应用程序
  • 成功连接应用程序后,将实例化新的RemoteMediaPlayer并请求MediaStatus
  • 您应该在onStatusUpdated()中获得回调,然后可以调用mRemoteMediaPlayer.getMediaStatus(),它将包含有关Chromecast上正在播放的内容的数据
    public静态最终字符串CHROMECAST\u SIGNATURE=“cast.media.CastMediaRouteProviderService”;
    专用最终媒体路由选择器mSelector;
    专用最终媒体路由器;
    专用设备mSelectedDevice;
    private Cast.Listener mCastClientListener;
    专用RemoteMediaPlayer mRemoteMediaPlayer;
    @凌驾
    public void onCreate(){
    mMediaRouter=MediaRouter.getInstance(上下文);
    mSelector=新的MediaRouteSelector.Builder()
    //这些是框架支持的意图
    .addControlCategory(MediaControlIntent.CATEGORY\u LIVE\u AUDIO)
    .addControlCategory(MediaControlIntent.CATEGORY\u LIVE\u视频)
    .addControlCategory(MediaControlIntent.CATEGORY\u远程播放)
    .build();
    mMediaRouter.addCallback(mSelector、mMediaRouterCallback、MediaRouter.CALLBACK_标志_请求_发现| MediaRouter.CALLBACK标志_未过滤_事件);
    }
    @凌驾
    公共空间{
    mMediaRouter.removeCallback(mMediaRouterCallback);
    }
    @超线程
    私有布尔IschromeCastative(){
    返回getActiveChromecastRoute()!=null;
    }
    @超线程
    私有布尔isChromecastPlaying(){
    if(mRemoteMediaPlayer==null | | mRemoteMediaPlayer.getMediaStatus()==null){
    返回null;
    }
    //在这里,您可以获得播放状态和正在播放内容的元数据
    //但是只有在mRemoteMediaPlayer回调中调用onStatusUpdated()方法之后
    int state=mRemoteMediaPlayer.getMediaStatus().getPlayerState();
    返回(state==MediaStatus.PLAYER_state_BUFFERING | | state==MediaStatus.PLAYER_state_PLAYING);
    }
    @超线程
    专用MediaRouter.RouteInfo getActiveChromecastRoute(){
    对于(MediaRouter.RouteInfo路由:mMediaRouter.getRoutes()){
    if(ISCAST设备(路由)){
    if(route.getConnectionState()==MediaRouter.RouteInfo.CONNECTION\u STATE\u CONNECTED){
    返回路线;
    }
    }
    }
    返回null;
    }
    私有int GetMediaRouteVorume(@NonNull MediaRouter.RouteInfo route){
    return route.getVolume();
    }
    私有void setMediaRouteVorume(@NonNull MediaRouter.RouteInfo路由,int卷){
    route.requestSetVolume(卷);
    }
    私有int getMediaRouteMaxVolume(@NonNull MediaRouter.RouteInfo route){
    return route.getVolumeMax();
    }
    @超线程
    专用MediaRouter.RouteInfo getActiveMediaRoute(){
    if(IschromeCastative()){
    MediaRouter.RouteInfo路由=getActiveChromecastRoute();
    if(路由!=null){
    如果(!route.isSelected()){
    mMediaRouter。选择route(路由);
    }
    }
    else if(mSelectedDevice!=null){
    mSelectedDevice=null;
    }
    返回路线;
    }
    返回null;
    }
    专用布尔isCastDevice(MediaRouter.RouteInfo RouteInfo){
    返回routeInfo.getId().contains(CHROMECAST_签名);
    }
    私有MediaRouter.Callback mMediaRouterCallback=新的MediaRouter.Callback(){
    @凌驾
    路由上的公共无效(MediaRouter路由器、MediaRouter.RouteInfo路由){
    if(ISCAST设备(路由)){
    Log.i(“MediaRouter”,“Chromecast发现:”+路由);
    }
    }
    @凌驾
    路由更改上的公共无效(MediaRouter路由器、MediaRouter.RouteInfo路由){
    if(ISCAST设备(路由)){
    Log.i(“MediaRouter”,“Chromecast更改:”+路由);
    }
    }
    @凌驾
    已选择路由上的公共无效(MediaRouter路由器、MediaRouter.RouteInfo路由){
    if(mSelectedDevice==null&&isCastDevice(路由)){
    Log.i(“MediaRouter”,“选择Chromecast:”+路由);
    mSelectedDevice=CastDevice.getFromBundle(route.getExtras());
    mCastClientListener=new Cast.Listener(){
    @凌驾
    Application StatusChanged()上的公共无效{
    Log.i(“MediaRouter”、“Cast.Listener.onApplicationStatusChanged()”;
    }
    @凌驾
    ApplicationMetadataChanged上的公共无效(ApplicationMetadata ApplicationMetadata){
    Log.i(“MediaRouter”、“Ca”
    
    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);
            }
        }
    };