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

Aur*_*ras 2 android google-cast

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

我不想要一个发送者应用程序,我不想注册任何东西来获得api密钥,没有那些东西.

我到目前为止使用MediaRouter来控制音量并查看它是否与任何东西相连.

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

谷歌演员安卓

哪个知道播放和(或至少)播放状态.

理想情况下,我不想使用谷歌播放服务,但如果这是唯一的方式,c'est la vie.

Aur*_*ras 6

我终于弄明白了.我不得不使用谷歌播放服务和谷歌演员sdk v2但没有注册该应用程序.

项目中包含的图书馆:

compile 'com.android.support:mediarouter-v7:24.0.0' 
compile 'com.google.android.gms:play-services-cast-framework:9.2.0' 
Run Code Online (Sandbox Code Playgroud)

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

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

  1. 您可以通过调用getActiveMediaRoute()来选择一个路线,该方法可以检查哪个Chromecast 处于活动状态(如果没有人连接到Chromecast,它将无法工作).覆盖方法或getActiveChromecastRoute()以根据您的偏好进行选择
  2. 当调用onRouteSelected()时,将使用所选chromecast的选项实例化一个新的Cast GoogleApiClient
  3. 当调用onApplicationMetadataChanged()时,代码将连接到Chromecast上运行的当前应用程序
  4. 成功连接应用程序后,将实例化一个新的RemoteMediaPlayer并请求MediaStatus
  5. 您应该在onStatusUpdated()中获得回调,之后您可以调用mRemoteMediaPlayer.getMediaStatus(),它将包含有关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);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)