O procedimento a seguir permite converter seu app de envio do Android do SDK do Google 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 muito 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 fornece widgets que obedecem aos requisitos de UX do Cast. O v2 não oferecia nenhum componente de interface e exigia que você implementasse esses widgets.
- O uso do GoogleApiClient não é mais necessário para usar a API Cast.
- O closed captioning no CAF Sender é semelhante ao da v2.
Dependências
A V2 e a CAF têm as mesmas dependências nas bibliotecas de suporte e no 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 com suporte do CAF é a 9 (Gingerbread).
Inicialização
No CAF, uma etapa de inicialização explícita é necessária 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 lentamente o CastContext
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 passa para o primeiro plano e vai para o segundo plano,
respectivamente. MediaRouteSelector
e MediaRouter.Callback
não devem ser
usados.
Botão "Transmitir" e caixa de diálogo "Transmitir"
Assim como na v2, esses componentes são fornecidos pela biblioteca de suporte MediaRouter.
O botão "Transmitir" ainda é implementado pelo
MediaRouteButton
e pode ser adicionado à atividade (usando um
ActionBar
ou um
Toolbar
),
como um item de 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 Google 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 de transmissão é apresentada automaticamente.
Controle do dispositivo
No CAF, o controle do dispositivo é processado 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 Web Receiver usando
GoogleApiClient
. A interação entre o remetente e o receptor da Web agora é representada
como uma "sessão". A classe
SessionManager
gerencia o ciclo de vida da sessão e inicia e encerra sessões automaticamente
em resposta aos gestos do usuário: uma sessão é iniciada quando o usuário seleciona um dispositivo
do Google Cast na caixa de diálogo do Google Cast e é encerrada quando o usuário toca no botão "Parar transmissão"
na caixa de diálogo do Google Cast ou quando o próprio app de envio é encerrado. O aplicativo
do remetente pode ser notificado sobre eventos do 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 Google Cast. A classe tem métodos para
controlar o volume e os estados de silenciamento do dispositivo, o que era feito anteriormente na v2
usando métodos em Cast.CastApi
.
Na v2, os callbacks
Cast.Listener
forneciam notificações sobre mudanças no estado do dispositivo, incluindo
volume, estado de mudo, 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 do estado do dispositivo são enviadas por
callback
CastStateListener
. Esses listeners são registrados com o CastSession
. Não
se esqueça de cancelar o registro de listeners quando os fragmentos, atividades ou apps associados forem
transferidos para o segundo plano.
Lógica de reativação
Assim como na v2, o CAF tenta restabelecer as conexões de rede que foram perdidas devido à perda temporária do sinal do Wi-Fi ou a outros erros de rede. Isso agora é 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 for restaurada. O framework se encarrega de se reconectar ao aplicativo do receptor da Web e reconectar todos os canais do Google Cast como parte desse processo.
Além disso, o CAF também adiciona a retomada automática de sessões, que é ativada por
padrão (e pode ser desativada usando
CastOptions
.
Se o aplicativo de envio for enviado para o segundo plano ou for encerrado (por
deslizar para longe ou devido a uma falha) enquanto uma sessão do Google Cast estiver em andamento, o
framework vai tentar retomar essa sessão quando o aplicativo de envio
voltar para o primeiro plano ou for reiniciado. Isso é processado automaticamente pelo
SessionManager
, que emitirá os callbacks apropriados em qualquer instância
SessionManagerListener
registrada.
Registro de canais personalizados
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 próxima seção para mais detalhes.
Controle de mídia
A classe v2
RemoteMediaPlayer
foi descontinuada e não deve ser usada. No CAF, ele é substituído pela nova classe
RemoteMediaClient
, que oferece uma funcionalidade equivalente em uma API mais conveniente. Não é
necessário inicializar ou registrar esse objeto explicitamente. O framework
instanciará o objeto automaticamente e registrará o canal de mídia
subjacente no início da sessão se o aplicativo do receptor da Web conectado
for compatível com o 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 meio de um callback
PendingResult
que pode ser usado para acompanhar o progresso e o resultado final da
solicitação.
O RemoteMediaPlayer
da v2 enviava notificações sobre mudanças no estado do
reprodutor de mídia no Web Receiver pelo
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 do remetente compartilhem a
única instância de RemoteMediaClient
associada à sessão.
Na v2, o aplicativo remetente precisava assumir a responsabilidade de manter a interface do usuário sincronizada 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 for mostrado aos usuários pela primeira vez.
Minicontrole
Na v2, é necessário implementar um minicontrole 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 minicontrole.
Notificação e tela de bloqueio
Na v2, os controles de notificação e tela de bloqueio não são fornecidos pelo SDK. Para esse SDK, é necessário criar esses recursos no app de envio usando as APIs do framework do Android.
No CAF, o SDK oferece um
NotificationsOptions.Builder
para ajudar a criar controles de mídia para a notificação e a tela de bloqueio
no app remetente. Os controles de notificação e da 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 controle expandido do zero no app remetente.
O CAF fornece uma classe auxiliar
UIMediaController
que facilita a criação do próprio controlador
expandido.
O CAF adiciona um widget de controlador expandido pré-criado
ExpandedControllerActivity
que você pode adicionar ao app. Não é mais necessário
implementar um controlador 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.