Bienvenidos a la segunda parte de mi tutorial sobre cómo salvar su base de datos a Dropbox desde dentro de una aplicación móvil Cordova. Aquí veremos cómo administrar la copia de seguridad y restauración de una base de datos usando un complemento útil: Portero de SQLite por Dave Alden. El complemento es fantástico, funciona muy bien y permítanme compartir con ustedes Estoy orgulloso de haberme unido al grupo de colaboradores corrigiendo un pequeño error que impedía usar con éxito exportDbToSql() y importDbFromSql().
Complemento SQLite Porter
SQLite Porter le permite exportar e importar una base de datos usando solo unas pocas líneas de código. Puede exportar la base de datos a un archivo json o un archivo sql usando exportDbToJson() y exportDbToSql() funciones. Para importar una base de datos, puede utilizar las funciones correspondientes. importJsonToDb() y importSqlToDb().
Entonces, abra el símbolo del sistema o la ventana de su terminal y navegue hasta la raíz de su proyecto, luego escribe:
complemento de cordova agregar uk.co.workingedge.cordova.plugin.sqliteporter
Eso es todo: el complemento está listo para nosotros.
Administrar archivos: archivo-plugin-cordova
Pero los archivos deben administrarse: tenemos que crearlos a ellos y sus directorios, debemos poder leer su contenido y escribir contenido en archivos. Para ello, vamos a instalar un importante plugin cordova que se utiliza para leer y escribir archivos dentro del sistema operativo host. Todavía deberías tener tu terminal (o símbolo del sistema) abrir en el directorio raíz de su proyecto (si no, luego ábrelo y ve allí). Escribe esto:
Los complementos de cordova agregan el archivo cordova-plugin-file
Exportar la base de datos a un archivo de respaldo
Está bien! Finalmente podemos escribir un código, ahora! Primero escribiremos la función que realmente exporta nuestra base de datos y escribiremos un archivo de volcado mysql: poner el siguiente código antes de la función principal de jQuery.
Si desea profundizar en la API del sistema de archivos, Sugiero leer, además de lo obligatorio Página de manual de Cordova, dos grandes artículos https://www.html5rocks.com/en/tutorials/file/filesystem/ y https://www.neontribe.co.uk/cordova-file-plugin-examples/. |
función exportBackup() { var successFn = función (.sql) { window.resolveLocalFileSystemURL(cordova.file.dataDirectory, función (dirEntry) { dirEntry.getDirectory('/ dropboxTestBackup', {crear: cierto}, función (dirEntry) { dirEntry.getFile('dropboxTestBackup.sql', {crear: cierto}, función (fileEntry) { alerta("El archivo " + fileEntry.name + 'se ha creado en el siguiente directorio: Android / data / com.example.dropboxTest / files / dropboxTestBackup / '); writeFile(fileEntry, .sql); }); }, onErrorCreateFile); }, onErrorCreateDir); }; cordova.plugins.sqlitePorter.exportDbToSql(.db, { successFn: successFn }); } función onErrorCreateFile(mi) { consola.log('Error al crear el archivo: ' + mi); } función onErrorCreateDir(mi) { consola.log('Error al crear el directorio: ' + mi); }
Analicemos este código línea por línea. Como puedes ver, la función en la que se divide 2 secciones: la primera es la función de devolución de llamada, latetr es la función SQLite Porter que realmente exporta la base de datos y luego llama a la función de devolución de llamada. Esta segunda parte es bastante simple y no tenemos nada interesante que señalar al respecto.. Pero la función calback nos permite comprobar cómo Cordova gestiona el acceso y la manipulación de archivos y directorios.
Anatomía del código
Primero encontramos el resolveLocalFileSystemURL() (mira aquí: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/index.html#where-to-store-files). A partir de la versión 1.2, para cada directorio importante del sistema de archivos se proporciona una URL:
Cada URL tiene el formato archivo:///camino / a / lugar /, y se puede convertir en un
DirectoryEntry
utilizandowindow.resolveLocalFileSystemURL()
.
Pasamos a esta función el parámetro cordova.file.dataDirectory: le estamos diciendo a Cordova que queremos almacenar nuestro archivo en el Almacenamiento Interno. Este es el recomendado para almacenar cualquier dato persistente de la aplicación porque es accesible exclusivamente por nuestra aplicación.. Lo comprobaremos más adelante, cuando ya habremos creado nuestro archivo de copia de seguridad. Entonces cordova.file.dataDirectory es igual al camino /sdcardAndroid / data / com.codingfix.dropboxTest / y se convierte en un objeto de tipo DirectoryEntry hemos llamado dirEntry. dirEntry El objeto es devuelto por la función anónima de devolución de llamada que usamos en resolveLocalFileSystemURL(): window.resolveLocalFileSystemURL(cordova.file.dataDirectory, función (dirEntry) {
Examinemos nuestra función de devolución de llamada: inmediatamente vemos que usamos un método del objeto DirectoryEntry, el método getDirectory() y lo pasamos 2 parámetros y otra función de devolución de llamada anónima: dirEntry.getDirectory('/dropboxTestBackup', {crear: cierto}, función (dirEntry) {
El método getDirectory() aceptar cuatro parámetros (aquí solo usamos tres): una cadena que representa la ruta relativa de un directorio, un valor booleano que establece si el directorio debe crearse si no se encuentra y dos funciones de devolución de llamada para el éxito y el error (este no se usa en nuestro ejemplo). En otras palabras, nuestra aplicación le dice a Android que busque un directorio /sdcardAndroid / data / com.codingfix.dropboxTest / y crear en ese directorio un nuevo directorio llamado dropboxTestBackup dónde almacenaremos nuestros archivos de copia de seguridad.
La función de devolución de llamada usa el nuevo objeto de tipo DirectoryEntry creado por el método getDirectory() para crear el archivo de respaldo en sí: dirEntry.getFile('dropboxTestBackup.sql', {crear: cierto}, función (fileEntry) { . Esta vez usamos el método Obtener el archivo() que es casi idéntico al método getDirectory() usado anteriormente con la diferencia obvia de que crea un archivo en lugar de un directorio y devuelve una referencia a ese archivo. Usamos el objeto fileEntry en la última función de devolución de llamada donde alertamos al usuario de la aplicación de que el archivo se ha creado correctamente y escribimos nuestros datos en el archivo:
alerta("El archivo: " + fileEntry.name + 'se ha creado en el siguiente directorio: Android / data / com.example.dropboxTest / files / dropboxTestBackup / '); writeFile(fileEntry, .sql);
Oye, qué es eso?!? Nunca hablamos de un writeFile() función!!! – Te oigo decir. No te preocupes, Chicos: Vamos a ver eso ahora 🙂 mismo
Escritura de archivos
si, tenemos que escribir datos en un archivo, Lo sabíamos, No es? Fíjate en esta función (y mantenerte listo para saber sobre la lectura de archivos, más adelante en este artículo):
función writeFile(fileEntry, dataObj) { // Crear un objeto FileWriter para nuestro FileEntry. fileEntry.createWriter(función (fileWriter (Escritor de archivos)) { fileWriter.onwriteend = función () { consola.log("Escritura exitosa de archivos..."); readFile(fileEntry); }; fileWriter.write(dataObj); }, onErrorWriteFile); } función onErrorWriteFile(mi) { consola.log('Error al escribir el archivo: ' + e.toString()); } función readFile(fileEntry) { fileEntry.file(función (archivo) { var reader = nuevo FileReader(); reader.onloadend = función () { consola.log("Lectura correcta del archivo: " + fileEntry.fullPath + " - contenido: " + this.result); return this.result; }; reader.readAsText(archivo); }, onErrorReadFile); } función onErrorReadFile(mi) { consola.log('Error al leer el archivo: ' + mi); }
La función es bastante simple: simplemente acepta 2 Parámetros, el objeto file que apunta al archivo físico creado en nuestro sistema de archivos y los datos que se van a escribir en el archivo: writeFile(fileEntry, .sql); A continuación, esta función utiliza internamente el método readFile() para leer el archivo recién creado y poner su contenido en la consola. Como hemos notado anteriormente, almacenar el archivo en el almacenamiento interno (ya que se recomienda por razones de seguridad) no nos permite encontrar este archivo utilizando ninguna aplicación de terceros. Ni su administrador de archivos preinstalado ni uno de terceros pueden ver este archivo (dropboxTestBackup.sql) ni el directorio donde se crea el archivo en (/dropboxTestBackup), así que esta es la única forma que tenemos de comprobar si todo salió bien.
Si desea crear un archivo público, accesible por su administrador de archivos de Android o incluso por su computadora cuando su dispositivo Android está conectado con un cable USB, tienes que usar externalDataDirectory en lugar de directorio de datos, pero esto expone sus archivos al acceso de software de terceros. Así que siéntete libre de usar externalDataDirectory mientras está en desarrollo, para facilitar la depuración de su aplicación, pero ten en cuenta que debes reemplazarlo con directorio de datos cuando en producción. |
Bueno. Hasta ahora hemos aprendido cómo exportar nuestra base de datos en formato sql y cómo escribir estos datos en un archivo dentro de nuestro sistema de archivos.. Ahora tenemos que importar estos datos a nuestra base de datos. (si algo inadvertidamente borró nuestros datos).
Importar un archivo de respaldo a nuestra base de datos
Entonces ahora queremos realizar la operación opuesta, leer datos de un archivo y usarlos para restaurar la base de datos de nuestra aplicación. El código es fácilmente comprensible considerando lo que hemos aprendido antes..
función importBackup(desdeDropbox) { var rutaToArchivo = cordova.archivo.datosDirectorio + '/dropboxTestBackup/dropboxTestBackup.sql'; window.resolveLocalFileSystemURL(pathToFile, función (fileEntry) { fileEntry.file(función (archivo) { var reader = nuevo FileReader(); reader.onloadend = función (mi) { var successFn = función () { alerta('Base de datos restaurada con éxito!'); loadPaíses(); loadUsers(); }; cordova.plugins.sqlitePorter.importSqlToDb(.db, this.result, { successFn: successFn }); }; reader.readAsText(archivo); }, onErrorLoadFile); }, onErrorLoadFs); } función onErrorLoadFile(mi){ consola.log('Error al leer el archivo: ' + e.toString()); } función onErrorLoadFs(mi) { consola.log('Error al cargar el sistema de archivos: ' + mi); }
Primero establecemos la ruta a nuestro archivo de respaldo, entonces usamos resolveLocalFileSystemURL() para obtener el fileEntry para leer el contenido del archivo y usarlo en la función de devolución de llamada onloadend() como parámetro para dar a cordova.plugins.sqlitePorter.importSqlToDb(). Una vez que se carga el archivo, alertamos al usuario y llamamos a nuestras dos funciones para completar nuestros controles. Listo, los juegos estan hechos!
Haz que los botones funcionen!
¿Recuerdas el código que habíamos escrito en nuestro índice.js archivo para adjuntar el controlador de eventos a nuestros botones? Se veía de esta manera:
$('#createDB').hacer clic(función (mi) { e.preventDefault(); createTables(); }); $('#exportDB').hacer clic(función (mi) { e.preventDefault(); }); $('#emptyDB').hacer clic(función (mi) { e.preventDefault(); dropTables(); }); $(«#importDB»).hacer clic(función (mi) { e.preventDefault(); });
Ahora tenemos que agregar una llamada a exportCopia de seguridad() y importCopia de seguridad() funciones para que este bloque de código se vea ligeramente diferente:
$('#createDB').hacer clic(función (mi) { e.preventDefault(); createTables(); }); $('#exportDB').hacer clic(función (mi) { e.preventDefault(); exportCopia de seguridad(falso); }); $('#emptyDB').hacer clic(función (mi) { e.preventDefault(); dropTables(); }); $(«#importDB»).hacer clic(función (mi) { e.preventDefault(); importCopia de seguridad(falso); });
Te muestro como todo índice.js el archivo debería verse tan lejos:
era aplicación = { inicializar: función () { document.addEventListener('Deviceready', this.onDeviceReady.bind(esta), falso); }, onDeviceReady: función () { this.receivedEvent('Deviceready'); }, recibidoEvento: función (carné de identidad) { var parentElement = document.getElementById(carné de identidad); var listeningElement = parentElement.querySelector('.escuchando'); var receivedElement = parentElement.querySelector('.recibido'); listeningElement.setAttribute('estilo', 'monitor:ninguna;'); receivedElement.setAttribute('estilo', 'monitor:bloquear;'); consola.log('Evento recibido: ' + carné de identidad); } }; app.initialize(); var db = window.openDatabase("dropbox_test", "1.0", "Prueba de importación / exportación de proceso de datos con Dropbox", 200000); función createCountryTable() { db.transaction(función (Tx) { tx.executeSql("DROP TABLE SI EXISTE países"); tx.executeSql("CREAR TABLA SI NO EXISTE países (ID AUTOINCREMENTO DE LLAVE PRIMARIA INTEGER, país INTEGER, código TEXT)", [], paísCreadoÉxito, countryCreatedError); tx.executeSql("INSERTAR EN países (carné de identidad, país, código) VALORES (1, 'Afganistán', 'DE'),(2, «Albania», 'ALABAMA'),(3, 'Argelia', 'DZ'),(4, 'Andorra', 'ANUNCIO'),(5, «Angola», 'PARA'),(6, 'Antigua y Barbuda', «AG»),(7, 'Argentina', 'CON'),(8, 'Armenia', 'SOY'),(9, 'Australia', 'PARA'),(10, «Austria», 'AT'), (11, 'Azerbaiyán', 'AZ'),(12, «Bahamas, El', 'BS'),(13, 'Bahréin', 'BH'),(14, 'Bangladesh', 'BD'),(15, 'Barbados', 'BB'),(16, 'Bielorrusia', 'POR'),(17, 'Bélgica', 'SER'),(18, 'Belice', 'BZ'), (19, 'Benín', 'BJ'),(20, 'Bután', 'BT'),(21, 'Bolivia', 'BO'),(22, 'Bosnia y Herzegovina', 'LICENCIADO EN LETRAS'),(23, «Botsuana», 'BW'),(24, 'Brasil', 'BR'),(25, 'Brunéi', 'BN'),(26, «Bulgaria», 'BG'),(27, «Burkina Faso», 'BF'),(28, «Burundi», 'CON UN'),(29, 'Camboya', 'KH'),(30, 'Camerún', 'CM'),(31, 'Canadá', 'ESE'),(32, 'Cabo Verde', 'CV'),(33, 'República Centroafricana', 'CF'),(34, 'Chad', 'TD'),(35, 'Chile', 'CL'),(36, 'Porcelana, República Popular de, «CN»),(37, 'Colombia', 'CO'),(38, 'Comoras', 'KM'),(39, Congo, (Congo ? Kinshasa)', 'CD'),(40, Congo, (Congo ? Brazzaville)', 'CG'),(41, 'Costa Rica', 'CR'), (42, 'Costa de Marfil (Costa de Marfil)', 'ALLÍ'), (43, 'Croacia', 'HORA'), (44, 'Cuba', 'CON'), (45, 'Chipre', 'CY'), (46, 'República Checa', 'CZ'),(47, 'Dinamarca', 'DK'), (48, «Yibuti», 'DJ'), (49, «Dominica», 'DM'), (50, 'República Dominicana', 'HACER'), (51, 'Ecuador', 'CE'), (52, 'Egipto', 'P.EJ'), (53, 'El Salvador', 'SV'), (54, 'Guinea Ecuatorial', 'GQ'), (55, 'Eritrea', 'ES'), (56, «Estonia», 'SÍ'), (57, 'Etiopía', 'Y'), (58, 'Fiyi', 'FJ'), (59, 'Finlandia', 'SER'), (60, 'Francia', 'FR'), (61, 'Gabón', 'GEORGIA'),(62, «Gambia, El', 'GM'),(63, «Georgia», 'DAR'),(64, 'Alemania', 'DE'), (65, 'Ghana', 'GH'), (66, 'Grecia', 'GRAMO'), (67, 'Granada', 'GD'), (68, 'Guatemala', 'GT'), (69, 'Guinea', 'GN'), (70, «Guinea-Bissau», 'GW'), (71, 'Guayana', 'GY'), (72, 'Haití', 'HT'), (73, 'Honduras', 'HN'), (74, 'Hungría', 'HU'), (75, 'Islandia', 'ES'), (76, 'India', 'EN'), (77, «Indonesia», 'IDENTIFICACIÓN'), (78, 'Irán', 'IR'), (79, 'Irak', 'IQ'), (80, 'Irlanda', 'ES DECIR'), (81, 'Israel', 'LOS'), (82, 'Italia', 'ESO'),(83, 'Jamaica', 'JM'), (84, 'Japón', 'JP'), (85, 'Jordán', 'YA'), (86, 'Kazajstán', 'KZ'), (87, 'Kenia', 'KE'), (88, 'Kiribati', 'KI'), (89, 'Corea, Norte', 'KP'), (90, 'Corea, Sur', 'KR'), (91, 'Kuwait', 'KW'),(92, 'Kirguistán', 'KG'), (93, 'Laos', 'LA'), (94, 'Letonia', «VI»), (95, 'Líbano', 'LB'), (96, 'Lesoto', 'LS'), (97, 'Liberia', 'LR'), (98, 'Libia', 'LY'), (99, «Liechtenstein», 'EN EL'), (100, 'Lituania', 'LT'), (101, 'Luxemburgo', 'LU'), (102, 'Macedonia', 'MK'), (103, «Madagascar», 'MG'), (104, 'Malaui', 'MW'), (105, 'Malasia', 'MI'), (106, 'Maldivas', 'MV'), (107, 'Malí', 'ML'), (108, «Malta», 'MONTE'), (109, 'Islas Marshall', 'MH'), (110, «Mauritania», 'SEÑOR'), (111, 'Mauricio', 'MU'), (112, 'México', 'MX'), (113, 'Micronesia', 'FM'), (114, 'Moldavia', 'MARYLAND'), (115, 'Mónaco', 'MC'), (116, «Mongolia», 'MINNESOTA'), (117, «Montenegro», 'YO'), (118, 'Marruecos', 'MAMÁ'), (119, «Mozambique», 'MZ'), (120, Myanmar (Birmania)', 'MM'), (121, «Namibia», 'N / A'), (122, 'Nauru', 'NO'), (123, 'Nepal', 'P.EJ'), (124, 'Países Bajos', «NL»), (125, 'Nueva Zelanda', 'NUEVA ZELANDA'), (126, 'Nicaragua', 'NI'), (127, 'Níger', 'NACIÓ'), (128, 'Nigeria', 'NG'), (129, 'Noruega', 'NO'), (130, 'Omán', 'SI'), (131, 'Pakistán', 'PAQUETE'), (132, 'Palau', 'PW'), (133, 'Panamá', 'PENSILVANIA'), (134, 'Papúa Nueva Guinea', 'PG'), (135, 'Paraguay', 'PY'), (136, 'Perú', 'SOBRE'), (137, 'Filipinas', 'PH'), (138, 'Polonia', 'PL'), (139, «Portugal», 'PT'), (140, 'Katar', 'Control de calidad'), (141, 'Rumania', 'RO'), (142, 'Rusia', 'RU'), (143, 'Ruanda', 'RW'), (144, 'Saint Kitts y Nevis', 'KN'), (145, 'Santa Lucía', 'LC'), (146, 'San Vicente y las Granadinas', 'USTED'), (147, 'Samoa', 'WS'), (148, 'San Marino', 'SM'), (149, 'Santo Tomé y Príncipe', 'S T'), (150, 'Arabia Saudita', 'PARA'), (151, 'Senegal', 'SN'), (152, 'Serbia', 'RS'), (153, «Seychelles», 'CAROLINA DEL SUR'), (154, 'Sierra Leona', 'SL'), (155, 'Singapur', «SG»), (156, 'Eslovaquia', 'SK'), (157, 'Eslovenia', 'Y'), (158, 'Islas Salomón', 'SB'), (159, 'Somalia', 'ASI QUE'), (160, 'Sudáfrica', 'POR'), (161, 'España', 'ES'), (162, «Sri Lanka», 'PÁGINA'), (163, 'Sudán', 'DAKOTA DEL SUR'), (164, 'Surinam', 'SR'), (165, 'Swazilandia', 'SZ'), (166, 'Suecia', 'SE'), (167, 'Suiza', 'CH'), (168, 'Siria', 'SU'), (169, 'Tayikistán', 'TJ'), (170, 'Tanzania', 'TZ'), (171, 'Tailandia', 'TH'), (172, «Timor-Leste (Timor Oriental)', 'TL'), (173, 'Ir', 'TG'), (174, 'Tonga', 'PARA'), (175, 'Trinidad y Tobago', 'TT'), (176, 'Túnez', 'TENNESSE'), (177, 'Pavo', 'TR'), (178, 'Turkmenistán', 'TM'), (179, 'Tuvalu', 'TELEVISOR'), (180, 'Uganda', 'UG'), (181, 'Ucrania', 'UA'), (182, 'Emiratos Árabes Unidos', 'AE'), (183, 'Reino Unido', 'GB'), (184, 'Estados Unidos', 'NOSOTROS'), (185, 'Uruguay', 'U'), (186, 'Uzbekistán', 'PARA'), (187, Vanuatu, 'VISTO'), (188, 'Ciudad del Vaticano', 'VIRGINIA'), (189, 'Venezuela', 'Y'), (190, 'Vietnam', 'VN'), (191, 'Yemen', 'S.M'), (192, «Zambia», 'ZM'), (193, 'Zimbabue', 'ZW'), (194, 'Abjasia', 'DAR'), (195, 'Porcelana, Republica de (Taiwán)', 'TW'), (196, 'Nagorno-Karabaj', 'AZ'), (197, 'El norte de Chipre', 'CY'), (198, Pridnestrovie (Transnistria)', 'MARYLAND'), (199, 'Somalilandia', 'ASI QUE'), (200, 'Osetia del Sur', 'DAR'), (201, 'Islas Ashmore y Cartier', 'PARA'), (202, 'Isla de Navidad', 'CX'), (203, «Cocos (Keeling) Islas ', 'CC'), (204, 'Islas del Mar de Coral', 'PARA'), (205, 'Isla Heard e Islas McDonald', 'HM'), (206, 'Isla Norfolk', 'NF'), (207, 'Nueva Caledonia', 'CAROLINA DEL NORTE'), (208, 'Polinesia francés', 'PF'), (209, 'Mayotte', 'YT'), (210, 'San Bartolomé', 'GP'), (211, 'San Martín', 'GP'), (212, 'San Pedro y Miquelón', 'PM'), (213, 'Wallis y Futuna', 'WF'), (214, 'Tierras Australes y Antárticas Francesas', 'TF'), (215, 'Isla Clipperton', 'PF'), (216, 'Isla Bouvet', 'BV'), (217, 'Islas Cook', 'CK'), (218, 'Niue', 'NO'), (219, 'Tokelau', 'CC.TT.'), (220, 'Guernsey', 'GG'), (221, 'Isla del hombre', 'SOY'), (222, 'Jersey', 'JE'), (223, 'Anguila', 'AL'), (224, 'Islas Bermudas', 'BM'), (225, 'Territorio Británico del Océano Índico', 'I'), (226, 'Áreas de base soberana británica', ''), (227, 'Islas Vírgenes Británicas', 'VG'), (228, 'Islas Caimán', 'KENTUCKY'), (229, 'Islas Malvinas (Islas Malvinas)', 'FK'), (230, 'Gibraltar', 'DAR'), (231, 'Montserrat', 'SRA'), (232, 'Islas Pitcairn', 'PN'), (233, 'Santa Elena', 'SH'), (234, Georgia del Sur & Islas Sandwich del Sur, 'GS'), (235, 'Islas Turcas y Caicos', 'TC'), (236, 'Islas Marianas del Norte', 'MP'), (237, 'Puerto Rico', 'Relaciones públicas'), (238, 'Samoa Americana', 'COMO'), (239, 'Isla Baker', 'A'), (240, 'Guam', 'GU'), (241, 'Isla Howland', 'A'), (242, 'Isla Jarvis', 'A'), (243, 'Atolón Johnston', 'A'), (244, 'Arrecife Kingman', 'A'), (245, 'Islas Midway', 'A'), (246, 'Isla de Navassa', 'A'), (247, 'Atolón de Palmyra', 'A'), (248, 'NOSOTROS. Islas Virgenes', 'NOSOTROS'), (249, 'Isla Wake', 'A'), (250, 'Hong Kong', 'HK'), (251, 'Macao', 'MES'), (252, 'Islas Faroe', 'FO'), (253, 'Groenlandia', 'GL'), (254, 'Guayana Francesa', 'GF'), (255, 'Guadalupe', 'GP'), (256, 'Martinica', 'SQM'), (257, 'Reunión', 'RE'), (258, 'Una tierra', 'HACHA'), (259, 'Aruba', 'AW'), (260, 'Antillas Holandesas', 'UN'), (261, 'Svalbard', 'SJ'), (262, 'Ascensión', 'C.A'), (263, 'Tristán da Cunha', 'EJÉRCITO DE RESERVA'), (268, 'Territorio Antártico Australiano', 'AQ'), (269, 'Dependencia de Ross', 'AQ'), (270, 'Isla Pedro I', 'AQ'), (271, 'Tierra de la Reina Maud', 'AQ'), (272, 'Territorio Antártico Británico', 'AQ');", [], countryFilledSuccess, countryFilledError); función countryCreatedSuccess() { consola.log('Tabla de países creada correctamente!'); } function countryCreatedError(Tx, error) { consola.log(mensaje de error); } función countryFilledSuccess() { consola.log('Tabla de países completada correctamente!'); loadPaíses(); } function countryFilledError(Tx, error) { consola.log(mensaje de error); } }); } función createUsersTable() { db.transaction(función (Tx) { tx.executeSql("DROP TABLE SI EXISTE usuarios"); tx.executeSql("CREAR TABLA SI NO EXISTE usuarios (ID AUTOINCREMENTO DE LLAVE PRIMARIA INTEGER, first_name TEXTO, last_name TEXTO, email_address TEXTO, TEXTO del país)", [], userCreatedSuccess, userCreatedError); tx.executeSql("INSERT INTO usuarios (carné de identidad, primer nombre, apellido, dirección de correo electrónico, país) VALORES (1, 'Juan', 'Gama', «john.doe@email.com», 'ESTADOS UNIDOS'), (2, 'Miguel', 'Olivares', 'miguel.olivares.Doe@email.es', 'España'), (3, 'Franz', 'Kuttermeyer', 'frankut@email.de', 'Alemania'), (4, 'Marianne', 'Jolie', 'mariannejolie@email.fr', 'Francia')", [], userFilledSuccess, userFilledError); función userCreatedSuccess() { consola.log('Tabla de usuarios creada correctamente!'); } función userCreatedError(Tx, error) { consola.log(mensaje de error); } función userFilledSuccess() { consola.log('Tabla de usuarios completada correctamente!'); loadUsers(); } función userFilledError(Tx, error) { consola.log(mensaje de error); } }); } función createTables() { createCountryTable(); createUsersTable(); } función dropCountriesTable() { db.transaction(función (Tx) { tx.executeSql("DROP TABLE SI EXISTE países", [], dropPaíses Éxito, dropCountriesError); función dropCountriesSuccess() { consola.log('Tabla de países eliminada con éxito!'); loadPaíses(); } función dropCountriesError(Tx, error) { consola.log(mensaje de error); } }); } función dropUsersTable() { db.transaction(función (Tx) { tx.executeSql("DROP TABLE SI EXISTE usuarios", [], dropUsersSuccess, dropUsersError); función dropUsersSuccess() { consola.log('Tabla de usuarios eliminada correctamente!'); loadUsers(); } función dropUsersError(Tx, error) { consola.log(mensaje de error); } }); } función dropTables() { dropUsersTable(); dropCountriesTable(); } función loadCountries() { var qry = "SELECCIONAR ID, país de países"; db.transaction(función (Tx) { tx.executeSql(qry, [], querySuccess, queryError); función querySuccess(Tx, datos) { $('seleccionar # países').niños().retirar(); var paises = {}; por (var i = 0; yo < data.rows.length; yo ++) { $('seleccionar # países').adjuntar('<valor de la opción ="' + data.rows[yo].carné de identidad + '">' + data.rows[yo].país + '</opción>'); } } función queryError(transacción, error) { consola.log('Query errorHandler' + mensaje de error + 'en consulta' + qry); //usamos la función de devolución de llamada de error para vaciar los controles de la página $('seleccionar # países').niños().retirar(); $('seleccionar # países').adjuntar('<opción>No se encontraron datos de países!</opción>'); } }); } función loadUsers() { var qry = "SELECCIONE first_name, apellido, dirección de correo electrónico, país de los usuarios"; db.transaction(función (Tx) { tx.executeSql(qry, [], querySuccess, queryError); función querySuccess(Tx, datos) { $('#usuarios').niños().retirar(); por (var i = 0; yo < data.rows.length; yo ++) { $('#usuarios').adjuntar('<= Li class"desplegable">' + data.rows[yo].primer nombre + '' + data.rows[yo].apellido + '<= Ul class"submenú"><en>' + data.rows[yo].dirección de correo electrónico + '</en><en>' + data.rows[yo].país + '</en></la></en>'); } } función queryError(transacción, error) { consola.log('Query errorHandler' + mensaje de error + 'en consulta' + qry); //usamos la función de devolución de llamada de error para vaciar los controles de la página $('#usuarios').niños().retirar(); $('#usuarios').adjuntar('<opción>No se encontraron datos de usuario!</opción>'); } }); } función exportBackup() { var successFn = función (.sql) { window.resolveLocalFileSystemURL(cordova.file.dataDirectory, función (dirEntry) { dirEntry.getDirectory('/ dropboxTestBackup', {crear: cierto}, función (dirEntry) { dirEntry.getFile('dropboxTestBackup.sql', {crear: cierto}, función (fileEntry) { alerta("El archivo " + fileEntry.name + 'se ha creado en el siguiente directorio: Android / data / com.example.dropboxTest / files / dropboxTestBackup / '); writeFile(fileEntry, .sql); }); }, onErrorCreateFile); }, onErrorCreateDir); }; cordova.plugins.sqlitePorter.exportDbToSql(.db, { successFn: successFn }); } función onErrorCreateFile(mi) { consola.log('Error al crear el archivo: ' + mi); } función onErrorCreateDir(mi) { consola.log('Error al crear el directorio: ' + mi); } función writeFile(fileEntry, dataObj) { // Crear un objeto FileWriter para nuestro FileEntry. fileEntry.createWriter(función (fileWriter (Escritor de archivos)) { fileWriter.onwriteend = función () { consola.log("Escritura exitosa de archivos..."); readFile(fileEntry); }; fileWriter.write(dataObj); }, onErrorWriteFile); } función onErrorWriteFile(mi) { consola.log('Error al escribir el archivo: ' + e.toString()); } función readFile(fileEntry) { fileEntry.file(función (archivo) { var reader = nuevo FileReader(); reader.onloadend = función () { consola.log("Lectura correcta del archivo: " + fileEntry.fullPath + " - contenido: " + this.result); return this.result; }; reader.readAsText(archivo); }, onErrorReadFile); } función onErrorReadFile(mi) { consola.log('Error al leer el archivo: ' + mi); } función importBackup(desdeDropbox) { var rutaToArchivo = cordova.archivo.datosDirectorio + '/dropboxTestBackup/dropboxTestBackup.sql'; window.resolveLocalFileSystemURL(pathToFile, función (fileEntry) { fileEntry.file(función (archivo) { var reader = nuevo FileReader(); reader.onloadend = función (mi) { var successFn = función () { alerta('Base de datos restaurada con éxito!'); loadPaíses(); loadUsers(); }; cordova.plugins.sqlitePorter.importSqlToDb(.db, this.result, { successFn: successFn }); }; reader.readAsText(archivo); }, onErrorLoadFile); }, onErrorLoadFs); } función onErrorLoadFile(mi){ consola.log('Error al leer el archivo: ' + e.toString()); } función onErrorLoadFs(mi) { consola.log('Error al cargar el sistema de archivos: ' + mi); } $(documento).Listo(función () { loadPaíses(); loadUsers(); $('#createDB').hacer clic(función (mi) { e.preventDefault(); createTables(); }); $('#exportDB').hacer clic(función (mi) { e.preventDefault(); exportCopia de seguridad(falso); }); $('#emptyDB').hacer clic(función (mi) { e.preventDefault(); dropTables(); }); $(«#importDB»).hacer clic(función (mi) { e.preventDefault(); importCopia de seguridad(falso); }); $('#usuarios').en('hacer clic', 'li.dropdown', función (mi) { e.preventDefault(); consola.log($(esta).texto()); elementos var = $(esta).hermanos().encontrar('ul.submenú'); artículos cada uno(función () { Si ($(esta).es(':visible')) { $(esta).deslizar hacia arriba('lento'); } }); $(esta).encontrar('ul.submenú').slideToggle(); }); });
Ahora podemos exportar nuestra base de datos a un archivo local y si es necesario, restaurarlo desde el archivo de respaldo. Solo ejecuta la aplicación, y sigue estos pasos para probar la aplicación:
- Grifo Crear base de datos para crear la base de datos (si aún no lo hiciste)
- Exportarlo tocando Exportar base de datos botón
- Ahora toca Base de datos vacía botón para eliminar todos sus datos
- y luego toque Importar base de datos botón para ver sus datos en vivo de nuevo!
Excelente, No es?
Pero queremos asegurarnos de que nuestro usuario pueda recuperar sus datos incluso si ha desinstalado nuestra aplicación en un momento de trastorno mental y luego, una vez que ha vuelto a la razón, lo ha reinstalado. Así que tenemos que ofrecerle la opción de guardar su archivo de copia de seguridad en algún host externo.. Lo adivinas? sí, Dropbox! Y este será el argumento de la próxima, capítulo final de este tutorial.