Как добавить пользовательский SessionProvider с помощью Google Cast SDK 3

Недавно мы обновили Google Cast SDK до версии 3. С помощью этого SDK должна быть возможность добавить поддержку устройств, не являющихся приведенными, путем реализации getAdditionalSessionProviders() в OptionsProvider. Мы создали пользовательский SessionProvider для возврата методом getAdditionalSessionProviders().

Однако этот SessionProvider никогда не используется, и, вероятно, он будет использоваться только тогда, когда устройство было обнаружено и выбрано в списке выбора, когда нажата кнопка MediaRouteButton, как описано в документации по сеансу. Но мы не можем найти способ добавить наше обнаруженное не приведенное устройство в этот список. Мы искали API, документацию и примеры, доступные в Интернете, но не смогли найти, как это сделать. Мы нашли только примеры старых версий SDK, но они абсолютно разные и не могут быть использованы.

Мы хотели бы использовать эту функцию для добавления телевизоров Samsung в список Google Cast с помощью Samsung SmartView SDK, как это делают приложения YouTube и Netflix.

3 ответа

Создайте пользовательский провайдер медиа-маршрутов. Вот фиктивный Media RouteProvider для пользовательского медиа-маршрута. Этот класс не делает ничего, кроме публикации поддельного пользовательского Media Route, чтобы его можно было увидеть и выбрать с помощью Cast SDK из MediaRouter.

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;
  }
}

И реализация Session: вот фиктивная реализация Session для пользовательского типа медиа-маршрута. Это всегда успешно на начало / возобновление / конец.

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;
  }
}

В вашем приложении добавьте провайдера Media Router:

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

Это раздражает... Я все еще работаю над решением - но я только что нашел несколько обучающих программ по Google Video по этому поводу: https://www.youtube.com/watch?v=_NGB10uN6OI

Итак, у меня была та же проблема, что и у вас, и я нашел какой-то способ заставить ее работать, но, как вы заметили, поскольку по этому вопросу ничего не задокументировано, я не уверен, что это "правильный способ сделать это".

Вот в основном то, что я делаю:

Поставщик медиа-маршрута отвечает за управление вашим устройством и всеми связанными с ним командами / связью. Вы можете проверить это с очень простым приложением, используя Media Router API. В Media Router есть github из googlesample: Android BasicMediaRouter Sample.

В вашем пользовательском классе Session вы можете получить доступ к MediaRouter (вы получили контекст, переданный в конструктор) и получить текущий маршрут:

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

При этом вы сможете получить ваше устройство, если оно выбрано в настоящий момент (вы будете уведомлены в методе start() Session), и передавать команды от объекта Session вашему провайдеру медиа-маршрутов, как это сделано в образец медиа-маршрута.

Другие вопросы по тегам