O procedimento a seguir permite converter seu app de envio para Android do SDK do Cast v2 para o CAF Sender, que é baseado no singleton CastContext.
O SDK do remetente do CAF do Cast usa o CastContext para gerenciar o GoogleAPIClient em seu nome. O CastContext gerencia ciclos de vida, erros e callbacks para você, o que simplifica bastante o desenvolvimento de um app do Cast.
Introdução
- O CAF Sender ainda é distribuído como parte do Google Play Services usando o gerenciador do SDK do Android.
- Foram adicionados novos pacotes que assumem a responsabilidade de obedecer à
lista de verificação de design do Google Cast (
com.google.android.gms.cast.framework.*). - O CAF Sender oferece widgets que atendem aos requisitos de UX do Cast. A v2 não oferecia componentes de IU e exigia que você implementasse esses widgets.
- O uso de GoogleApiClient não é mais necessário para usar a API Cast.
- A legenda descritiva no CAF Sender é semelhante à v2.
Dependências
A V2 e o CAF têm as mesmas dependências das bibliotecas de suporte e do Google Play Services (9.2.0 ou mais recente), conforme descrito no guia de recursos da biblioteca de suporte.
A versão mínima do SDK do Android compatível com o CAF é a 9 (Gingerbread).
Inicialização
No CAF, é necessária uma etapa de inicialização explícita para o framework do Cast. Isso
envolve inicializar o
singleton
CastContext, usando um
OptionsProvider
adequado para especificar o ID do aplicativo do receptor da Web e outras opções globais.
public class CastOptionsProvider implements OptionsProvider {
@Override
public CastOptions getCastOptions(Context context) {
return new CastOptions.Builder()
.setReceiverApplicationId(context.getString(R.string.app_id))
.build();
}
@Override
public List<SessionProvider> getAdditionalSessionProviders(Context context) {
return null;
}
}
Declare o OptionsProvider na tag "application" do arquivo AndroidManifest.xml do app:
<application>
...
<meta-data
android:name=
"com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="com.google.sample.cast.refplayer.CastOptionsProvider" />
</application>
Inicialize o CastContext de forma lenta no método onCreate de cada atividade:
private CastContext mCastContext;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.video_browser);
setupActionBar();
mCastContext = CastContext.getSharedInstance(this);
}
Essas etapas não eram necessárias na v2.
Descoberta de dispositivos
No CAF, o processo de descoberta é iniciado e interrompido automaticamente pelo
framework quando o app entra em primeiro e segundo plano,
respectivamente. MediaRouteSelector e MediaRouter.Callback não devem ser
usados.
Botão e caixa de diálogo Transmitir
Assim como na v2, esses componentes são fornecidos pela biblioteca de suporte do MediaRouter.
O botão Transmitir ainda é implementado pelo
MediaRouteButton
e pode ser adicionado à sua atividade (usando um
ActionBar
ou um
Toolbar)
como um item no seu menu.
<item
android:id="@+id/media_route_menu_item"
android:title="@string/media_route_menu_title"
app:actionProviderClass="android.support.v7.app.MediaRouteActionProvider"
app:showAsAction="always"/>
Substitua o método onCreateOptionMenu() de cada atividade usando
CastButtonFactory
para conectar o MediaRouteButton ao framework do Cast:
private MenuItem mediaRouteMenuItem;
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.browse, menu);
mediaRouteMenuItem =
CastButtonFactory.setUpMediaRouteButton(getApplicationContext(),
menu,
R.id.media_route_menu_item);
return true;
}
Quando alguém toca no botão, a caixa de diálogo do Cast é apresentada automaticamente.
Controle do dispositivo
No CAF, o controle do dispositivo é feito principalmente pelo framework. O aplicativo remetente não precisa processar (e não deve tentar processar) a conexão com o dispositivo e iniciar o aplicativo receptor da Web usando GoogleApiClient. A interação entre o remetente e o receptor da Web agora é representada
como uma "sessão". A classe
SessionManager
processa o ciclo de vida da sessão e inicia e interrompe sessões automaticamente
em resposta a interações do usuário: uma sessão é iniciada quando o usuário seleciona um dispositivo de transmissão
na caixa de diálogo do Google Cast e é encerrada quando o usuário toca no botão "Parar de transmitir"
na caixa de diálogo do Google Cast ou quando o próprio app remetente é encerrado. O app remetente pode ser notificado sobre eventos de ciclo de vida da sessão registrando um SessionManagerListener com o SessionManager. Os callbacks SessionManagerListener definem
métodos de callback para todos os eventos de ciclo de vida da sessão.
A classe
CastSession
representa uma sessão com um dispositivo de transmissão. A classe tem métodos para
controlar o volume do dispositivo e os estados de silenciamento, o que antes era feito na v2
usando métodos em Cast.CastApi.
Na v2, os callbacks
Cast.Listener
forneciam notificações de mudanças no estado do dispositivo, incluindo
volume, estado de silenciamento, status de espera e assim por diante.
No CAF, as notificações de mudança de estado de volume/silenciamento ainda são enviadas por métodos de callback
no Cast.Listener. Esses listeners são registrados com
CastSession.
Todas as notificações restantes de estado do dispositivo são entregues por callbacks
CastStateListener.
Esses listeners são registrados com o CastSession. Não se esqueça de
cancelar o registro dos listeners quando os fragmentos, as atividades ou os apps associados forem
para o segundo plano.
Lógica de reconexão
Assim como na v2, o CAF tenta restabelecer conexões de rede perdidas devido à perda temporária de sinal de Wi-Fi ou outros erros de rede. Agora isso é feito no nível da sessão. Uma sessão pode entrar em um estado "suspenso" quando a conexão é perdida e voltar para um estado "conectado" quando a conectividade é restaurada. O framework cuida da reconexão com o aplicativo receptor da Web e com todos os canais de transmissão como parte desse processo.
Além disso, o CAF também adiciona a retomada automática de sessão, que é ativada por
padrão (e pode ser desativada usando
CastOptions.
Se o aplicativo remetente for enviado para o segundo plano ou for encerrado (por
deslizar ou devido a uma falha) enquanto uma sessão do Cast estiver em andamento, o
framework tentará retomar essa sessão quando o aplicativo remetente
retornar ao primeiro plano ou for reiniciado. Isso é processado automaticamente pelo
SessionManager, que emitirá os callbacks apropriados em todas as instâncias
SessionManagerListener registradas.
Registro de canal personalizado
Na v2, os canais personalizados (implementados usando
Cast.MessageReceivedCallback)
são registrados com o Cast.CastApi. No CAF, os canais personalizados são registrados com a instância CastSession. O registro pode ser feito no método de callback
SessionManagerListener.onSessionStarted. Para aplicativos de mídia, não é mais necessário registrar explicitamente
o canal de controle de mídia usando Cast.CastApi.setMessageReceivedCallbacks.
Consulte a seção a seguir para mais detalhes.
Controle de mídia
A classe v2
RemoteMediaPlayer
foi descontinuada e não deve ser usada. No CAF, ela foi substituída pela nova classe
RemoteMediaClient,
que oferece uma funcionalidade equivalente em uma API mais conveniente. Não é
necessário inicializar ou registrar explicitamente esse objeto. O framework
vai instanciar o objeto automaticamente e registrar o canal de mídia
subjacente no horário de início da sessão se o aplicativo receptor da Web que está sendo conectado
oferecer suporte ao namespace de mídia.
O RemoteMediaClient pode ser acessado como o método getRemoteMediaClient do objeto CastSession.
Na v2, todas as solicitações de mídia emitidas no RemoteMediaPlayer retornavam um
RemoteMediaPlayer.MediaChannelResult por um callback PendingResult.
No CAF, todas as solicitações de mídia emitidas no RemoteMediaClient retornam um
RemoteMediaClient.MediaChannelResult
por um callback
PendingResult,
que pode ser usado para acompanhar o progresso e o resultado final da
solicitação.
A v2 de RemoteMediaPlayer enviava notificações sobre mudanças no estado do player de mídia
no receptor da Web usando o
RemoteMediaPlayer.OnStatusUpdatedListener.
No CAF, o RemoteMediaClient fornece callbacks equivalentes pela interface
RemoteMediaClient.Listener. Qualquer número de listeners pode ser registrado com o
RemoteMediaClient, o que permite que vários componentes de remetente compartilhem a
única instância de RemoteMediaClient associada à sessão.
Na v2, o aplicativo remetente precisava manter a interface do usuário em sincronia com o estado do player de mídia no receptor da Web.
No CAF, a classe
UIMediaController
assume a maior parte dessa responsabilidade.
Sobreposição introdutória
A V2 não oferece uma interface de sobreposição introdutória.
O CAF oferece uma visualização personalizada
IntroductoryOverlay
para destacar o botão Transmitir quando ele é mostrado pela primeira vez aos usuários.
Minicontrole
Na v2, é preciso implementar um minicontrolador do zero no app remetente.
No CAF, o SDK oferece uma visualização personalizada,
MiniControllerFragment,
que pode ser adicionada ao arquivo de layout do app das atividades em que
você quer mostrar o minicontrolador.
Notificação e tela de bloqueio
Na v2, os controladores para notificação e tela de bloqueio não são fornecidos pelo SDK. Para esse SDK, você precisa criar esses recursos no app remetente usando as APIs do framework do Android.
No CAF, o SDK fornece um
NotificationsOptions.Builder
para ajudar você a criar controles de mídia para a notificação e a tela de bloqueio
no app remetente. Os controles de notificação e tela de bloqueio podem ser ativados
com o
CastOptions
ao inicializar o CastContext.
public CastOptions getCastOptions(Context context) {
NotificationOptions notificationOptions = new NotificationOptions.Builder()
.setTargetActivityClassName(VideoBrowserActivity.class.getName())
.build();
CastMediaOptions mediaOptions = new CastMediaOptions.Builder()
.setNotificationOptions(notificationOptions)
.build();
return new CastOptions.Builder()
.setReceiverApplicationId(context.getString(R.string.app_id))
.setCastMediaOptions(mediaOptions)
.build();
}
Controle expandido
Na v2, é necessário implementar um controlador expandido do zero no app remetente.
O CAF fornece uma classe auxiliar
UIMediaController
que facilita a criação do seu próprio controlador
expandido.
O CAF adiciona um widget de controle expandido pré-criado
ExpandedControllerActivity
que pode ser adicionado ao app. Não é mais necessário
implementar um controle expandido personalizado usando UIMediaController.
Seleção de áudio
Na v2, é necessário usar MediaSessionCompat para gerenciar o foco de áudio.
No CAF, o foco de áudio é gerenciado automaticamente.
Registros de depuração
No CAF, não há opções de registro.
Apps de exemplo
Temos tutoriais de codelab e apps de exemplo que usam o CAF.