如何使用Google Cast SDK 3添加自定义SessionProvider

时间:2016-08-25 15:17:28

标签: android chromecast google-cast samsung-smart-tv

我们最近将Google Cast SDK更新为版本3.使用此SDK,可以通过在OptionsProvider中实施getAdditionalSessionProviders()来添加对非播放设备的支持。我们创建了一个自定义SessionProvider以使用getAdditionalSessionProviders()方法返回。

但是,此SessionProvider从未使用过,只有在MediaRouteButton文档中所述按下Session时在选择列表中发现并选择了设备时才会使用它。但是我们找不到将我们发现的非流水设备添加到此列表的方法。我们搜索了API,文档和在线提供的示例,但我们无法找到如何执行此操作。我们只找到了较旧的sdk版本的示例,但这些版本完全不同且不可用。

我们希望使用此功能将三星电视与三星的SmartView SDK一起添加到Google Cast列表中,就像YouTube和Netflix应用程序一样。

2 个答案:

答案 0 :(得分:3)

创建自定义媒体路由提供程序:这是针对自定义媒体路由的虚假MediaRouteProvider。这个类除了发布假的自定义MediaRoute之外什么都不做,以便MediaRouter的Cast SDK可以看到和选择它。

import android.content.Context;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Bundle;
import android.support.v7.media.MediaRouteDescriptor;
import android.support.v7.media.MediaRouteDiscoveryRequest;
import android.support.v7.media.MediaRouteProvider;
import android.support.v7.media.MediaRouteProvider.RouteController;
import android.support.v7.media.MediaRouteProviderDescriptor;
import android.support.v7.media.MediaRouter;
import java.util.ArrayList;

public final class CustomMediaRouteProvider extends MediaRouteProvider {
  private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
  private static MediaRouteDescriptor DEFAULT_MEDIA_ROUTE_DESCRIPTOR;

  static {
    // This filter will be used by Cast SDK to match the session category.
    IntentFilter customControls = new IntentFilter();
    customControls.addCategory(CustomSessionProvider.CUSTOM_CATEGORY);

    CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
    CONTROL_FILTERS_BASIC.add(customControls);

    Bundle extras = new Bundle();
    extras.putCharSequence("ROUTE_URL", "http://abcdef.cyz");
    DEFAULT_MEDIA_ROUTE_DESCRIPTOR =
        new MediaRouteDescriptor.Builder("fake-custom-route-id", "fake custom route")
            .setDescription("Foo description")
            .addControlFilters(CONTROL_FILTERS_BASIC)
            .setPlaybackStream(AudioManager.STREAM_MUSIC)
            .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
            .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
            .setVolumeMax(100)
            .setVolume(10)
            .setExtras(extras)
            .build();
  }

  public CustomMediaRouteProvider(Context context) {
    super(context);
  }

  @Override
  public void onDiscoveryRequestChanged(MediaRouteDiscoveryRequest request) {
    if (request == null || request.getSelector() == null) {
      return;
    }

    publishRoutes();
  }

  @Override
  public RouteController onCreateRouteController(String routeId) {
    return null;
  }

  private void publishRoutes() {
    MediaRouteProviderDescriptor providerDescriptor =
        new MediaRouteProviderDescriptor.Builder().addRoute(DEFAULT_MEDIA_ROUTE_DESCRIPTOR).build();

    setDescriptor(providerDescriptor);
  }
}

您的自定义会话需要SessionProvider实现:

import android.content.Context;
import com.google.android.gms.cast.framework.Session;
import com.google.android.gms.cast.framework.SessionProvider;

public class CustomSessionProvider extends SessionProvider {
  public static final String CUSTOM_CATEGORY = "CUSTOM";

  public CustomSessionProvider(Context applicationContext) {
    super(applicationContext, CUSTOM_CATEGORY);
  }

  @Override
  public Session createSession(String sessionId) {
    return new CustomSession(getContext(), getCategory(), sessionId);
  }

  @Override
  public boolean isSessionRecoverable() {
    return true;
  }
}

会话实现:这是自定义媒体路由类型的虚假会话实现。它总是在开始/恢复/结束时成功。

import android.content.Context;
import android.os.Bundle;
import com.google.android.gms.cast.framework.Session;

public class CustomSession extends Session {
  private static final String FAKE_SESSION_ID = "custom.session.id.12345";

  CustomSession(Context applicationContext, String category, String sessionId) {
    super(applicationContext, category, sessionId);
  }

  @Override
  protected void start(Bundle routeInfoExtra) {
    notifySessionStarted(FAKE_SESSION_ID);
  }

  @Override
  protected void resume(Bundle routeInfoExtra) {
    notifySessionResumed(false);
  }

  @Override
  protected void end(boolean stopCasting) {
    notifySessionEnded(0);
  }
}

在Cast V3发件人应用中,指定其他会话提供商:

public class CastOptionsProvider implements OptionsProvider {
@Override
  public List<SessionProvider> getAdditionalSessionProviders(Context appContext) {
    List<SessionProvider> additionalProviders = new ArrayList<>();
    additionalProviders.add(new CustomSessionProvider(appContext));
    return additionalProviders;
  }
}

在您的应用程序中添加MediaRouter提供程序:

public class CastVideosApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    MediaRouter mediaRouter = MediaRouter.getInstance(this);
    mediaRouter.addProvider(new CustomMediaRouteProvider(this));
  }
}

答案 1 :(得分:0)

所以,我遇到了和你一样的问题,我找到了一些方法让它发挥作用,但正如你所指出的那样,由于没有真正记录在这个主题上,我不确定这是“正确的方法”它”。

这基本上就是我做的事情:

媒体路由提供商负责管理您的设备和所有相关命令/通信。您可以使用Media Router API使用非常简单的应用程序对其进行测试。 googlesample有一个关于媒体路由器的github:Android BasicMediaRouter Sample

在自定义Session类中,您可以访问MediaRouter(您在构造函数中传递了上下文)并检索当前的Route

 MediaRouter mediaRouter = MediaRouter.getInstance(context);
  if (mediaRouter != null && mediaRouter.getSelectedRoute() != null)
    Log.d("Cast", "Selected route name is " +  mediaRouter.getSelectedRoute().getName());

这样,你应该能够获得你的设备(如果它是当前选择的设备)(你将在Session的start()方法中得到通知),并将命令从Session对象传递给你的媒体路由提供者,在Media Route样本中完成。