Ao desenvolver um aplicativo, é muito útil usar a replicação push e pull no modo contínuo. Tudo é tratado pelos replicadores para garantir que seu aplicativo e o Sync Gateway sempre tenham os documentos mais recentes sincronizados.
No entanto, uma replicação pull contínua significa que o Couchbase Lite usará técnicas como polling longo ou soquetes da Web para verificar se há novos dados a serem obtidos do Sync Gateway. Isso pode afetar a duração da bateria e, consequentemente, a experiência do usuário.
Nesta postagem, exploraremos uma alternativa à replicação pull contínua usando o Google Cloud Messaging, o serviço de notificação por push do Android.
Você pode dar uma olhada em exemplo de trabalho no ToDoLite Android. Vamos ver como você pode incluir a sincronização do GCM em seu aplicativo!
Habilitando o GCM em seu aplicativo
Primeiro, vamos configurar o ToDoLite Android para se registrar no Google Cloud Messaging. Criaremos um novo projeto de API do Google no diretório console do desenvolvedor. Siga este guia para configurá-lo. Você deve ter um número de projeto e uma chave de API. Agora podemos atualizar a seção AndroidManifest.xml com as permissões, o filtro de intenção e o serviço necessários. Ele deve ter a seguinte aparência:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// ... // ... /* ... atividades ... */ |
Observação: Confira o exemplo do site do desenvolvedor do Android também.
Se o projeto estiver configurado corretamente, poderemos recuperar o token do dispositivo com o número do projeto que obtivemos ao criar o aplicativo no console do desenvolvedor do Google. Adicione um método na atividade principal para recuperar o token do dispositivo do GCM e salvá-lo no documento do perfil do usuário, por exemplo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
vazio getDeviceToken() { novo AsyncTask() { @Substituir protegida Cordas doInBackground(Vazio... parâmetros) { GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(getApplicationContext()); Cordas deviceToken = gcm.registro("632113338862"); Registro.i("GCM", "Token do dispositivo : " + deviceToken); // atualizar o documento do perfil do usuário retorno nulo; } }.executar(nulo, nulo, nulo); } |
Observação: Os tokens de dispositivo no Android sempre começam com APA91, portanto, fique atento a eles no LogCat ;)
Em seguida, temos de adicionar algum código para tratar uma notificação recebida. Fizemos uma subclasse da classe WakefulBroadcastReceiver, na qual o método onReceive é chamado toda vez que recebemos uma notificação.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
público classe GcmBroadcastReceiver se estende Receptor WakefulBroadcastReceiver { @Substituir público vazio onReceive(Contexto contexto, Intenção intenção) { // Especifique explicitamente que o GcmMessageHandler tratará a intenção. ComponentName componente = novo ComponentName(contexto.getPackageName(), GcmMessageHandler.classe.getName()); // Iniciar o serviço, mantendo o dispositivo acordado enquanto ele estiver sendo iniciado. startWakefulService(contexto, (intenção.setComponent(componente))); setResultCode(Atividade.RESULT_OK); } } |
A partir daí, o serviço em vigília inicia a classe GcmMessageHandler e executa uma replicação pull de uma só vez. O serviço de vigília é executado mesmo que seu aplicativo esteja em execução em segundo plano. Assim, seu aplicativo mostraria os novos dados de acordo com a abertura do aplicativo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
público classe GcmMessageHandler se estende IntentService { /* ... */ @Substituir protegida vazio onHandleIntent(Intenção intenção) { mIntent = intenção; showToast(); Aplicativo aplicativo = (Aplicativo) getApplication(); tentar { URL url = novo URL(BuildConfig.SYNC_URL_HTTP); Replicação puxar = aplicativo.getDatabase().createPullReplication(url); puxar.addChangeListener(getReplicationListener()); puxar.iniciar(); } captura (ExceçãoURLE malformada e) { e.printStackTrace(); } } privado Replicação.ChangeListener getReplicationListener() { retorno novo Replicação.ChangeListener() { @Substituir público vazio alterado(Replicação.ChangeEvent evento) { Registro.i("GCM", "O status da replicação é : " + evento.getSource().getStatus()); se (evento.getSource().getStatus() == Replicação.Status da Replicação.REPLICATION_STOPPED) { GcmBroadcastReceiver.completeWakefulIntent(mIntent); } } }; } /* ... */ } |
Observe que estamos usando o ouvinte de alteração de replicação para sermos notificados quando ela for concluída e para encerrar o serviço wakeful.
Isso é tudo o que precisamos fazer no lado do Android para lidar com a notificação de sincronização.
Salvando os tokens do dispositivo
Agora podemos armazenar o token do dispositivo no documento do perfil do usuário. Cada usuário pode estar conectado a mais de um dispositivo ao mesmo tempo, portanto, devemos armazenar cada um deles. O documento do usuário terá a seguinte aparência:
1 2 3 4 5 |
{ "_id": "profile:johnny@couchbase.com", ... "device_tokens": ["APA91K...", "APA91O..."] } |
Na próxima seção, falaremos sobre a adição de lógica de aplicativo adicional ao Sync Gateway usando o Changes Feed.
O Gateway de sincronização altera o feed
O /database/changes retorna uma lista ordenada das alterações feitas nos documentos do banco de dados. Esse ponto de extremidade faz parte do CouchDB especificação e tanto o Couchbase Lite Listener quanto o Sync Gateway o implementam.
É muito fácil se conectar ao Changes Feed do Sync Gateway para adicionar lógica extra ao back-end, como, no nosso caso, enviar notificações push.
Você pode usar qualquer biblioteca que implemente a API de feed de alterações:
- NodeJS: https://github.com/iriscouch/follow
- Ir: https://github.com/fjl/go-couchdb
- Python: https://github.com/djc/couchdb-python
- Java: https://github.com/helun/Ektorp
De todos os parâmetros disponíveis na string de consulta, os mais importantes em nosso caso são:
- feed=continuous para garantir que recebamos as alterações imediatamente
- since=now para obter as alterações da hora atual; caso contrário, ele registrará todas as alterações desde que o banco de dados foi criado!
Por fim, vamos nos concentrar na última peça do quebra-cabeça: dada uma alteração de documento do feed de alterações, precisamos obter os documentos do perfil do usuário "interessado" nessa mudança porque eles detêm os tokens de dispositivo.
Alterações no Feed → GCM
No ToDoLite, há três tipos de documentos: um perfil, uma lista e uma tarefa. O documento de tarefa contém uma referência à lista à qual pertence e uma lista tem um proprietário e uma matriz de membros.
Quando um documento de tarefa ou um documento de lista é alterado, gostaríamos de notificar o proprietário e os membros dessa lista. Há dois tipos de eventos que gostaríamos de tratar:
1. Um evento de modificação de documento de lista:
- obter o documento de perfil do proprietário
- obter o documento de perfil de cada membro
2. Um evento de modificação de documento de tarefa:
- obter o documento da lista ao qual pertence
- siga as mesmas etapas de 1)
Com os tokens de dispositivo recuperados, a última etapa é enviar uma solicitação aos servidores do Google Cloud Messaging com nossa chave de API e carga útil de notificação. Você também pode encontrar muitas bibliotecas no GitHub que simplificam a interação com os servidores GCM:
- NodeJS: https://github.com/ToothlessGear/node-gcm
- Ir: https://github.com/alexjlockwood/gcm
- Python: https://github.com/geeknam/python-gcm
- Java: https://github.com/inloop/easygcm
Encerramento
O uso do Google Cloud Messaging para acionar a busca de dados no lado do servidor pode proporcionar uma excelente experiência ao usuário sem nenhuma sobrecarga adicional de uso da bateria e da rede.
Siga a leia-me instruções para executar a demonstração do ToDoLite.
Gostaria muito de saber como você está usando as notificações do Google Cloud Messaging em seu aplicativo. Deixe sua opinião nos comentários abaixo!
Mais leituras:
- Dicas sobre como configurar o GCM em seu aplicativo: https://blog.pushbullet.com/2014/02/12/keeping-google-cloud-messaging-for-android-working-reliably-techincal-post/
- Sincronização de dados no aplicativo Google I/O: http://android-developers.blogspot.co.uk/2014/09/conference-data-sync-gcm-google-io.html