Parte 3: Adicionando a funcionalidade de sincronização a um servidor centralizado
Este blog com várias partes ajudará o leitor a criar um aplicativo móvel de ponta a ponta usando os recursos líderes do setor do Couchbase Lite.
Um aplicativo de última geração, de ponta a ponta, dimensionável e de nível de produção deve incluir os seguintes recursos:
-
- Um banco de dados incorporado para armazenar dados localmente no dispositivo e reduzir as viagens de rede para um banco de dados centralizado para cada atividade. Isso contribui muito para melhorar a experiência do usuário.
- Realizar pesquisa de texto completo no dispositivo.
- Sincronização com dispositivos móveis semelhantes e um servidor centralizado.
Esta série de posts do blog está dividida em quatro partes:
-
- Parte 1 apresenta o processo de criação de um aplicativo móvel que aproveita o CB Lite e o usa como um banco de dados incorporado para armazenar dados.
- Parte 2 mostra como executar o Full Text Search (FTS) no dispositivo.
- A Parte 3 apresenta a sincronização com um servidor Couchbase centralizado a partir de dispositivos de borda.
- A Parte 4 demonstrará a sincronização ponto a ponto entre dispositivos.
Estamos desenvolvendo este aplicativo com base em Servidor Couchbase e com Couchbase Mobile usados no dispositivo e para o gerenciamento de sincronização.
O Couchbase é um banco de dados em nuvem NoSQL distribuído e premiado. Ele oferece versatilidade, desempenho, escalabilidade e valor financeiro inigualáveis em implantações na nuvem, no local, híbridas, distribuídas e de computação de borda.
O Couchbase Mobile O portfólio inclui:
-
- Um banco de dados incorporado para dispositivos de borda.
- Um Sync Gateway de alto desempenho que oferece recursos de sincronização ponto a ponto e de servidor centralizado.
- Datacenters de borda com tecnologia do Couchbase Server que podem ser implantados na nuvem, no local ou localmente.
Adição da funcionalidade Sync
O código para este tutorial está disponível em meu sofá-base móvel Repositório do GitHub. Estamos trabalhando com o RateIt que faz parte do arquivo Rateit.zip, extraia seus arquivos para uma pasta local.
Como alternativa, você pode seguir as instruções desta série do blog para criar o aplicativo do zero.
A funcionalidade do aplicativo é dividida em três partes:
-
- envio de solicitações
- receber solicitações de outras pessoas
- visualizar a solicitação que você enviou
Enviar solicitações de classificação
O aplicativo que criamos neste tutorial permitirá que os usuários enviem uma solicitação de classificação de tópico a uma pessoa e recebam as respostas.
A ENVIAR PARA indica o número de telefone da pessoa para quem você deseja enviar a solicitação.
O Mensagem indica o que você deseja que eles façam com ela. Nesse caso, como se trata de uma solicitação de classificação, tenho uma mensagem predefinida de: "Rate 1-5" (Classifique de 1 a 5) - indicando que eles precisam fornecer uma classificação quando enviarem a solicitação de volta.
O Assunto indica qualquer tópico sobre o qual você deseja obter uma classificação, por exemplo, pode ser apenas uma palavra ou frase como:
-
- Ator: Chris Hemsworth
- Livro: Orgulho e Preconceito
- www.google.com
Não há nenhuma validação rigorosa de entrada nos campos, mas isso é algo que você faria em um aplicativo móvel de nível de produção.
Quando você clica em ENVIARUma solicitação é enviada para a pessoa-alvo.
Pré-requisitos do software
Nesta parte do blog, exigimos que o software a seguir seja instalado em um desktop ou servidor que será acessado pelo seu aplicativo móvel.
Servidor Couchbase - Instale uma versão em seu laptop ou servidor local usando este link de download gratuito. Após a instalação bem-sucedida, você poderá acessar o console do Couchbase no seu navegador em http://localhost:8091.
Servidor Sync Gateway - Ele pode estar na mesma máquina de desenvolvimento que o Couchbase Server. Faça o download do Sync Gateway aqui e revisar o documentação aqui.
Siga todos os Comece aqui! etapas da documentação, destacadas aqui em verde.
Para começar, faça o seguinte:
-
- Inicie o Sync Gateway em seu laptop.
- Conclua todas as etapas da seção de verificação.
- Dê ao usuário acesso a todos os canais com esta instrução curl:
1 2 3 4 |
enrolar --localização --solicitação PUT 'http://127.0.0.1:4985/rateit/_user/sgwuser1' \ --cabeçalho 'Authorization: Basic c3luY19nYXRld2F5OnBhc3N3b3Jk' \ --cabeçalho 'Content-Type: application/json' \ --dados-bruto '{ "name": "sgwuser1", "roles": ["stdrole"] , "admin_channels": ["*"]}' |
Apresentando o aplicativo móvel RateIt
Conforme mostrado nas postagens anteriores, a página principal do aplicativo tem três botões:
-
- CLIQUE PARA ENVIAR SOLICITAÇÃO DE CLASSIFICAÇÃO
- SOLICITAÇÕES DE CLASSIFICAÇÃO RECEBIDAS
- SOLICITAÇÕES DE CLASSIFICAÇÃO RECEBIDAS
Adicionaremos componentes de interface do usuário para permitir que você ative e desative a sincronização, além de fornecer uma entrada de texto para que os usuários se identifiquem.
Os arquivos de código que manipularemos são mainactivity.java e activity_main.xml.
A sincronização do dispositivo móvel com o servidor centralizado é para aplicativos que precisam atualizar constantemente um servidor centralizado com quaisquer alterações feitas nos dispositivos portáteis. Essa sincronização aplicará essas alterações a outros dispositivos se eles também compartilharem o mesmo aplicativo e a mesma conexão de banco de dados centralizado.
Revisão do código de sincronização do servidor
Adicione o seguinte código a activity_main.xml para incorporar o sincronização interruptor. É uma chave liga/desliga que permite que o usuário decida quando ativar a sincronização.
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 |
<Switch androide:id="@+id/switch1" androide:layout_width="158dp" androide:layout_height="38dp" androide:layout_marginStart="2dp" androide:layout_marginTop="8dp" androide:layout_marginEnd="2dp" androide:layout_marginBottom="8dp" androide:fundo="#F44336" androide:backgroundTint="#F44336" androide:verificado="false" (falso) androide:switchMinWidth="50dp" androide:switchTextAppearance="@style/TextAppearance.AppCompat.Body2" androide:texto="SYNC ON/OFF" androide:textColor="@color/black" androide:textOff="OFF" (DESLIGADO) androide:textOn="ON" androide:textSize="16sp" androide:textStyle="negrito" androide:visibilidade="visível" aplicativo:layout_constraintBottom_toTopOf="@+id/send" aplicativo:layout_constraintEnd_toEndOf="pai" aplicativo:layout_constraintHorizontal_bias="0.0" aplicativo:layout_constraintStart_toStartOf="pai" aplicativo:layout_constraintTop_toBottomOf="@+id/textView" /> |
O seguinte trecho de XML usa o nome de usuário como entrada do usuário e tem um rótulo associado para torná-lo fácil de usar.
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 |
<TextView androide:id="@+id/textView5" androide:layout_width="51dp" androide:layout_height="35dp" androide:layout_marginStart="16dp" androide:layout_marginTop="8dp" androide:fundo="#2196F3" androide:gravidade="center" (centro) androide:texto="USUÁRIO" androide:textStyle="negrito" aplicativo:layout_constraintStart_toEndOf="@+id/switch1" aplicativo:layout_constraintTop_toBottomOf="@+id/textView" /> <EditText androide:id="@+id/username" androide:layout_width="154dp" androide:layout_height="35dp" androide:layout_marginStart="67dp" androide:layout_marginTop="8dp" androide:fundo="@color/white" androide:backgroundTint="@color/white" androide:ems="10" androide:inputType="textPersonName" androide:texto="Nome" aplicativo:layout_constraintStart_toStartOf="@+id/textView5" aplicativo:layout_constraintTop_toBottomOf="@+id/textView" /> |
A página inicial do aplicativo agora terá a seguinte aparência: observe os novos componentes na linha superior:
Agora vamos atualizar Mainactivity.java no Java → com.example.rateit com essas alterações:
-
- Adicione um código que verifique se o sincronização precisa ser alternado.
- Adicione também um código para obter a entrada do usuário campo de entrada
1 2 3 |
Interruptor toggleBtn = (Interruptor) findViewById(R.id.interruptor1); EditText usuário = (EditText) findViewById(R.id.nome de usuário); Cordas nome de usuário = usuário.getText().toString(); |
Adicione um ouvinte para o sincronização botão de alternância que faz o seguinte:
-
-
- Quando o botão de alternância é alterado de ON para DESLIGADO, ou vice-versa, ele ouvirá e agirá de acordo com essas alterações.
- Quando o botão é girado DESLIGADOa replicação será interrompida.
- Quando o botão está definido para a posição ON a replicação será iniciada.
- Quando a replicação é ativada, instanciamos a configuração do replicador com o banco de dados local e fornecemos detalhes do banco de dados centralizado para indicar a origem e o destino das replicações push/pull.
-
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 |
toggleBtn.setOnCheckedChangeListener(newCompoundButton.OnCheckedChangeListener(){ @Override público vazio onCheckedChanged(CompoundButton buttonView, booleano isChecked) { Replicador replicador = nulo; se(isChecked) { DatabaseConfiguration configuração = novo DatabaseConfiguration(); Arquivo dbFile = novo Arquivo(contexto.getFilesDir() , "rateitdb"); configuração.setDirectory(contexto.getFilesDir().getAbsolutePath()); Banco de dados banco de dados = nulo; tentar { banco de dados = novo Banco de dados("rateitdb", configuração); } captura (CouchbaseLiteException e) { e.printStackTrace(); } URI url = nulo; tentar { url = novo URI(Cordas.formato("%s/%s", "ws://10.0.2.2:4984", "rateit")); } captura (URISyntaxException e) { e.printStackTrace(); } Consulta consulta = nulo; CouchbaseLite.inicial(contexto); ReplicatorConfiguration replconfig = novo ReplicatorConfiguration(banco de dados, novo URLEndpoint(url)); replconfig.setType(ReplicatorType.PUSH_AND_PULL); replconfig.setContinuous(verdadeiro); replconfig.setAuthenticator(novo BasicAuthenticator("sgwuser1", "senha".toCharArray())); replicador = novo Replicador(replconfig); setRepEventMonitor(replicador); replicador.iniciar(); Registro.i(Domínio de registro.REPLICADOR.nome(),"Replicação ativada"); } mais { replicador.parar(); Registro.i(Domínio de registro.REPLICADOR.nome(),"Replicação desativada"); } } }); CouchbaseLite.inicial(contexto); } |
Configure o monitor de eventos para eventos de replicação:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
público vazio setRepEventMonitor(Replicador replicador) { ListenerToken token = replicador.addDocumentReplicationListener(replicação -> { para (ReplicatedDocument documento : replicação.getDocuments()) { Registro.i(TAG, "Doc ID: " + documento.obterID()); CouchbaseLiteException erro = documento.getError(); se (erro != nulo) { /Houve um erro Registro.e(TAG, "Erro ao replicar o documento: ", erro); retorno; } } }); } |
Em Mainactivity.java também removemos muitos valores codificados dos registros de solicitações, para que possamos mostrar os registros como eles seriam para diferentes usuários.
No SENDDATA observe como os valores codificados são substituídos por campos de entrada relevantes:
1 2 3 4 5 6 7 8 |
MutableDocument mutableDoc = novo MutableDocument(); mutableDoc.setString("tipo", "enviar"); mutableDoc.setString("sendto", Cordas.valueOf(enviar para)); mutableDoc.setString("de", nome de usuário); mutableDoc.setString("para", enviar para); mutableDoc.setString("URL", Cordas.valueOf(Link de URL)); mutableDoc.setString("classificação", Cordas.valueOf(classificação)); mutableDoc.setDate("createdAt", novo Data()); |
No DADOS RECEBIDOS removemos a gravação extra que anteriormente emulava a obtenção de uma solicitação de classificação. Isso está obsoleto agora que adicionamos a função USUÁRIO campo de entrada que nos permite obter a classificação/solicitações de volta para o usuário específico.
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 |
SearchView pesquisa = (SearchView) findViewById(R.id.searchView); Expressão searchExp = FullTextExpression.índice("descFTSIndex").partida(Cordas.valueOf(pesquisa.getQuery())) ; Consulta consulta = nulo; se (pesquisa.getQuery().toString().acabamento().isEmpty()) { consulta = (Consulta) Criador de consultas.selecionar(SelecionarResultado.todos()).de(Fonte de dados.banco de dados(banco de dados)) .onde(Expressão.propriedade("para").igual a(Expressão.string(nome de usuário)) .e(Expressão.propriedade("tipo").igual a(Expressão.string("enviar")))); } mais { consulta = (Consulta) Criador de consultas.selecionar(SelecionarResultado.todos()).de(Fonte de dados.banco de dados(banco de dados)) .onde(Expressão.propriedade("para").igual a(Expressão.string(nome de usuário)) .e(Expressão.propriedade("tipo").igual a(Expressão.string("enviar"))) .e(searchExp)); } int linhas numéricas = consulta.executar().allResults().tamanho(); Torradas.makeText(getApplicationContext(), "num rows:::"+ linhas numéricas , Torradas.LENGTH_LONG).show(); tentar { consulta.executar().allResults().forEach(resultado -> { Dicionário thisDocsProps = resultado.getDictionary(0); Cordas de = thisDocsProps.getString("de").acabamento(); Cordas para = thisDocsProps.getString("para").acabamento(); Cordas enviar para = thisDocsProps.getString("sendto").acabamento(); Cordas URL = thisDocsProps.getString("URL").acabamento(); Cordas classificação = thisDocsProps.getString("classificação").acabamento(); flutuante estrelas de classificação = thisDocsProps.getFloat("ratingstars"); int estrelas = (int) estrelas de classificação; classificação = Cordas.valueOf(thisDocsProps.getFloat("ratingstars")); userArray.adicionar(novo Usuário(nome de usuário,de, enviar para, URL, classificação,estrelas de classificação)); }); } captura (CouchbaseLiteException e) { e.printStackTrace(); } |
No INCOMINGRATINGS reduza o código para obter solicitações com base em nome de usuário:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Consulta consulta = (Consulta) Criador de consultas.selecionar(SelecionarResultado.todos()).de(Fonte de dados.banco de dados(banco de dados)) .onde(Expressão.propriedade("de").igual a(Expressão.string(nome de usuário)) .e(Expressão.propriedade("tipo").igual a(Expressão.string("classificado")))); int linhas numéricas = consulta.executar().allResults().tamanho(); Torradas.makeText(getApplicationContext(), "num rows:::"+ linhas numéricas , Torradas.LENGTH_LONG).show(); tentar { consulta.executar().allResults().forEach(resultado -> { Dicionário thisDocsProps = resultado.getDictionary(0); Cordas enviar para = thisDocsProps.getString("sendto").acabamento(); Cordas URL = thisDocsProps.getString("URL").acabamento(); Cordas classificação = thisDocsProps.getString("classificação").acabamento(); flutuante estrelas de classificação = thisDocsProps.getFloat("ratingstars"); int estrelas = (int) estrelas de classificação; classificação = Cordas.valueOf(thisDocsProps.getFloat("ratingstars")); RatedArray.adicionar(novo Classificado(enviar para, URL, classificação)); }); } captura (CouchbaseLiteException e) { e.printStackTrace(); } |
Algumas atualizações foram feitas no UserCustomAdapter.java e RatedCustomerAdapter.java também. Para essa iteração, removeremos muitos arquivos DE e PARA porque queremos mostrar o aplicativo para dois usuários diferentes. Isso ajuda a mostrar como funciona a sincronização bidirecional entre o aplicativo e o servidor.
Mudanças semelhantes foram feitas para remover nomes codificados e levamos adiante o nome de usuário e solicitação detalhes na página principal do aplicativo.
Compilação do código do aplicativo móvel
Quando todo o código tiver sido atualizado, clique em Build → ReBuild Project, então Criar → Executar quando a reconstrução estiver concluída.
Você será solicitado a escolher o emulador na primeira vez que executar o aplicativo. Criei o dispositivo NEXUS 5X API 25 e o escolhi quando solicitado.
Quando a execução for concluída, a página principal terá a seguinte aparência:
Agora você implantou com êxito o código no emulador de sua escolha.
Um teste rápido
Vamos criar uma solicitação de classificação seguindo estas etapas:
- Gire o SINCRONIZAÇÃO ligar.
- Insira os detalhes da solicitação de classificação (usuário-alvo, mensagem, assunto).
- Clique em CLIQUE PARA ENVIAR SOLICITAÇÃO DE CLASSIFICAÇÃO.
- Acesse a instância do Couchbase Server. No meu caso, é o console da Web da minha instância local. Navegue até Baldes e Documentos e você verá a solicitação de classificação criada no servidor.
- Agora insira o nome de usuário AlPacino e clique em SOLICITAÇÕES DE CLASSIFICAÇÃO RECEBIDAS-Você deverá ver a solicitação de classificação na seção RECEBIDO seção pronta para ser avaliada. Avalie esta solicitação.
- Ao verificar o console, você verá dois documentos JSON, conforme mostrado abaixo.
Observe os dois registros no console.
Agora, vamos fazer uma alteração na solicitação classificada por AlPacino e altere o número de estrelas para 2 e ver se as alterações chegam ao dispositivo.
Execute o aplicativo e abra SOLICITAÇÕES CLASSIFICADAS RECEBIDAS (parte inferior da tela) para TomCruise e você verá a alteração para 2 estrelas.
Próximas etapas
Esta é a parte 3 da série do blog Criando um aplicativo móvel com o Couchbase. Esta postagem mostrou como ativar a sincronização entre dispositivos e servidores.
Na próxima parte da série, mostraremos como ativar a sincronização de dispositivos ponto a ponto.
Continue aprendendo seguindo esses recursos: