Hace unas semanas tuve escrito una guía que demostraba cómo guardar imágenes capturadas en Couchbase Lite como datos de cadena codificados en base64 en una aplicación móvil NativeScript con Angular. Aunque la guía anterior funcionaba tanto para Android como para iOS, los datos estaban localizados en el dispositivo. ¿Y si quisieras sincronizar las imágenes entre dispositivos o incluso almacenarlas en la nube?
Vamos a ver cómo utilizar Couchbase Mobile para sincronizar datos de imágenes entre dispositivos y plataformas en un NativeScript con la aplicación Angular.
A partir de ahora debes tener en cuenta que esta es la segunda parte de la serie. Esto significa que si aún no has seguido el tutorial anterior y no has conseguido una versión funcional del proyecto, deberías poner este tutorial en espera. Empieza con la guía, Guardar imágenes capturadas en una aplicación NativeScript Angular a CouchbaseA continuación, trabaja en la sincronización de las imágenes.
La imagen animada de arriba te dará una idea aproximada de lo que buscamos. Queremos poder sincronizar las imágenes guardadas entre Android e iOS usando Sync Gateway y opcionalmente Couchbase Server.
Requisitos
Los requisitos previos para esta guía son similares a los de la anterior. Necesitarás lo siguiente:
- NativeScript CLI
- Android SDK para Android o Xcode para iOS
- Pasarela de sincronización Couchbase
- Servidor Couchbase (opcional)
Notarás que Sync Gateway y opcionalmente Couchbase Server son los nuevos requerimientos de esta guía en la serie. Los necesitaremos para que la sincronización realmente ocurra. Si no estás familiarizado, Sync Gateway es el middleware de sincronización y Couchbase Server es el servidor de base de datos remoto.
Configuración de Sync Gateway para la replicación
Para utilizar Sync Gateway tendremos que definir una configuración en cuanto a cómo se produce la sincronización y cosas por el estilo.
Crear un sync-gateway-config.json en algún lugar de su ordenador que contenga la siguiente información:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{ "log":["CRUD+", "REST+", "Changes+", "Attach+"], "bases de datos": { "base de datos de imágenes": { "servidor": "morsa:datos", "sync":` function (doc) { canal (doc.canales); } `, "usuarios": { "INVITADO": { "disabled": falso, "admin_channels": ["*"] } } } } } |
En el archivo de configuración anterior estamos guardando todo en morsa:datos
que es una solución en memoria en lugar de persistir en Couchbase Server. La base de datos remota se llama base de datos de imágenes
pero no tiene por qué coincidir con lo que tenemos en el código de nuestra aplicación móvil.
Para simplificar, todo el mundo podrá leer y escribir datos en el mismo canal que un invitado.
Para ejecutar Sync Gateway, ejecute lo siguiente:
1 |
/ruta/hacia/sync_gateway /ruta/hacia/sync-gateway-config.json |
Debería poder acceder a Sync Gateway desde su navegador web en http://localhost:4984/_admin/ y ver todo lo que se está sincronizando, lo que a menudo se denomina replicado.
Añadir la lógica para sincronizar datos de imagen
El código necesario para que la replicación funcione en nuestra aplicación NativeScript con Angular es mínimo.
Abra el archivo app/app.component.ts e incluya el siguiente código TypeScript:
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
import { Componente, OnInit, NgZone } de "@angular/core"; import { Couchbase } from "nativescript-couchbase"; import * as Cámara from "cámara"; import * as ImageSource from "fuente-de-imagen"; @Componente({ selector: "ns-app", templateUrl: "app.component.html", }) export class AppComponent implements OnInit { base de datos privada: cualquiera; private pushReplicator: any; privado pullReplicator: any; imágenes públicas: Array; public constructor(private zona: NgZone) { this.database = new Couchbase("base-de-imágenes"); this.database.createView("images", "1", function(document, emitter) { if(document.type && document.type == "image") { emitter.emit(document._id, document); } }); this.pushReplicator = this.database.createPushReplication("http://192.168.57.1:4984/image-database"); this.pullReplicator = this.database.createPullReplication("http://192.168.57.1:4984/image-database"); this.pushReplicator.setContinuous(true); this.pullReplicator.setContinuous(true); this.images = []; } public ngOnInit() { this.pushReplicator.start(); this.pullReplicator.start(); this.database.addDatabaseChangeListener(changes => { for(let i = 0; i < cambios.longitud; i++) { this.zone.run(() => { let image = ImageSource.fromBase64(this.database.getDocument(changes[i].getDocumentId()).image); this.images.push(imagen); }); } }); let rows = this.database.executeQuery("images"); for(let i = 0; i < longitud.filas; i++) { this.images.push(ImageSource.fromBase64(filas[i].imagen)); } } public captura() { Camera.takePicture({ anchura: 300, altura: 300, keepAspectRatio: true, saveToGallery: false }).then(picture => { let base64 = picture.toBase64String("png", 70); this.database.createDocument({ "tipo": "imagen", "imagen": base64, "timestamp": (new Date()).getTime() }); }, error => { console.dump(error); }); } } |
El código anterior incluye todo lo de la primera parte de la serie, así como esta parte de la serie. Vamos a desglosar sólo lo que se ha añadido en lo que respecta a la replicación.
En el constructor
definimos a dónde vamos a enviar los datos y de dónde vamos a extraerlos.
1 2 3 4 |
this.pushReplicator = this.database.createPushReplication("http://192.168.57.1:4984/image-database"); this.pullReplicator = this.database.createPullReplication("http://192.168.57.1:4984/image-database"); this.pushReplicator.setContinuous(true); this.pullReplicator.setContinuous(true); |
Esto debe hacerse continuamente mientras la aplicación esté abierta.
Asegúrate de utilizar el host o la dirección IP correctos para Sync Gateway. Si estás usando Genymotion como yo, localhost no funcionará. Tendrás que averiguar las direcciones IP correctas.
En el ngOnInit
iniciamos el proceso de replicación y configuramos un oyente.
1 2 3 4 5 6 7 8 9 10 |
this.pushReplicator.start(); this.pullReplicator.start(); this.database.addDatabaseChangeListener(changes => { for(let i = 0; i < cambios.longitud; i++) { this.zone.run(() => { let image = ImageSource.fromBase64(this.database.getDocument(changes[i].getDocumentId()).image); this.images.push(imagen); }); } }); |
Cada vez que haya un cambio en la base de datos haremos un bucle a través de ellos y cargaremos los datos base64. Este ejemplo es simple por lo que no hay actualizaciones o eliminaciones de imágenes. Si este fuera el caso, nuestro listener sería un poco más complejo en lógica.
La razón por la que utilizamos un Angular NgZone
es porque el oyente opera en un hilo diferente. Por zonificación, podemos tomar los datos y asegurarnos de que la interfaz de usuario se actualiza correctamente.
Eso es todo lo que tuvimos que hacer para que las imágenes se sincronizaran entre el dispositivo y el servidor. Fácil, ¿verdad?
Conclusión
Acabas de ver cómo sincronizar datos de imagen entre dispositivos y plataformas utilizando NativeScriptAngular y Couchbase. Este fue un seguimiento del tutorial anterior que escribí llamado, Guardar imágenes capturadas en una aplicación NativeScript Angular a Couchbasedonde pusimos en marcha la aplicación inicial.
En caso de que prefieras no almacenar tus imágenes en la base de datos, puedes considerar crear una API que utilice un almacenamiento de objetos como Minio o Amazon S3. He escrito un tutorial sobre crear una API que guarde en Minio que podría ayudar.
Para obtener más información sobre el uso de Couchbase con Android e iOS, consulte la página Portal para desarrolladores de Couchbase.