Salva il database di Cordova su Dropbox

Come salvare il database a Dropbox (e come ripristinarlo) all'interno di un'applicazione Cordova – solo Android (parte 3)

In questa terza parte del nostro articolo tutorial su come salvare il database a Dropbox (qui abbreviato in DBX, in maiuscolo) dall'interno di un'applicazione mobile Cordova per dispositivi Android, we’ll concentrate on the specific steps needed to

  • connettiti a DBX e per salvare su Dropbox il nostro file di dump mysql
  • recuperalo da DBX e usalo per compilare il nostro database

questo può essere utile se il nostro utente ha disinstallato la nostra applicazione o se per qualche motivo il file di backup locale è stato perso o danneggiato.

Creazione di un'app Dropbox

La prima cosa che dobbiamo fare è creare un'app nella dashboard di Dropbox per accedere correttamente utilizzando Oauth2. È possibile trovare un ottimo tutorial Qui e ti incoraggio a leggerlo attentamente se hai qualche dubbio. Qui riassumo rapidamente i passaggi necessari:

  1. navigare verso https://www.dropbox.com/developers
  2. login into your account 😉
  3. creare una nuova app facendo clic su “Crea la tua app” link al centro della pagina
  4. scegli Dropbox API
  5. decidi se vuoi / hai bisogno dell'accesso completo a DBX o se devi solo accedere a una singola cartella creata appositamente per la tua app
  6. imposta un nome per la tua app e fai clic sull'icona blu “Crea app” pulsante
  7. prendi nota del tuo tasto app e il tuo segreto dell'app; nota e ricorda anche l'URI di reindirizzamento, che per Oauth2 deve essere https://www.dropbox.com/1/oauth2/redirect_receiver

Ora la tua app DBX è stata creata e ti permetterà di accedere a DBX dalla tua applicazione mobile ibrida.

Ottenere l'SDK Javascript di Dropbox

Per utilizzare l'API devi installare il Dropbox JavaScript SDK, un'interfaccia javascript per l'API Dropbox v2. Per installarlo, apri un prompt dei comandi o una finestra di terminale e digita il seguente comando:

npm install --save dropbox

Adesso, se hai familiarità con webpack o browserify, puoi semplicemente usare l'SDK come spiegato nel repository Github ufficiale. But if you don’t want or just don’t know how to use those tools, vai alla directory in cui è stato installato l'SDK, copia il file Dropbox-sdk.min.js dalla directory dist del pacchetto a www / js cartella della tua app e quindi collegala nel tuo file indice.html:

<script type ="text / javascript" src ="js/Dropbox-sdk.min.js"></copione>

Ora siamo finalmente pronti per il rock!

Torna all'app

Now it’s time to install the last plugin we need to go ahead, cordova-plugin-inappbrowser. Basta accedere alla directory principale del progetto con la CLI e digitare:

i plugin cordova aggiungono cordova-plugin-inappbrowser

Una volta installato, dobbiamo modificarlo un po '. Infatti, if we didn’t apply this little fix, dopo aver effettuato l'accesso all'account DBX, we would remain blocked on a blank page and we’d never be redirected to our app. Quindi apri il file nel tuo editor di codice piattaforme / android / platform_www / plugins / cordova-plugin-inappbrowser / www / inappbrowser.js. Vicino alla fine dello script, intorno alla linea 110 o così, subito dopo questa riga:

strWindowFeatures = strWindowFeatures || "";

Metti quanto segue 3 Linee:

Se (strUrl == 'https://www.dropbox.com/1/oauth2/redirect_receiver') {
	strWindowFeatures += "posizione=no,nascosto=sì";
}

This way we’re telling inappbrowser to hide itself if the url is the redirect url set in our DBX app.

Consenti origine?

Un altro problema in cui mi imbatto è il messaggio di errore restituito da Dropbox quando ho provato a salvare un file la prima volta. Questo era il messaggio:

Errore: La richiesta è stata terminata Possibili cause: la rete è offline, L'origine non è consentita da Access-Control-Allow-Origin, la pagina è in fase di scaricamento, eccetera.

Riassumere, basta sostituire il meta della tua Content-Security-Policy nel tuo file indice.html con questo (o aggiungilo, se manca):

<meta http-equiv ="Content-Security-politica" = contenuto"default-src *; style-src 'sé' http://* 'Insicuro-inline'; script src 'sé' http://* 'Insicuro-inline' 'non sicuro-eval'; media-src *" />

L'errore è sparito,e l'app viene eseguita. grande!

Configurazione della connessione Dropbox

Come detto sopra, L'API DBX utilizza OAuth2 per gestire l'autenticazione. Quindi la prima cosa che dobbiamo fare è preparare alcune cose per consentire alla nostra app di accedere a DBX:

var ID_Cliente = 'xxxxxxxxxxxxxxx';//we use App key as our client id 
var dbxt; //an object to store our Dropbox connection and its access token 
var dbx = new Dropbox({Identificativo cliente: IDENTIFICATIVO CLIENTE}); //l'oggetto Dropbox iniziale

Metti le righe sopra immediatamente dopo app.initialize chiamata, prima delle altre funzioni abbiamo già scritto per operare sul nostro database. Questo non è obbligatorio, ovviamente: you can put everywhere you’re most comfortable with 🙂

Modifiche all'interfaccia utente

Per andare avanti con il nostro piccolo progetto, ora dobbiamo cambiare leggermente la nostra interfaccia utente. Questo è, we’ll modify the behavior of the buttons which export and import respectively the database: invece di eseguire effettivamente queste azioni, renderanno visibile solo un altro div con 2 pulsanti per consentire all'utente di scegliere

  • se esporta il database solo localmente o anche su DBX
  • se importa il database da un file locale o da DBX

Modifiche al markup

Let’s go to change our indice.html primo: basta sostituire la sezione dei pulsanti con il seguente markup:

		<div class ="centrato">
			<h3>Seleziona un Paese:</h3>
			<seleziona id="Paesi">
			</Selezionare>
			<a href ="#" id ="createDB" class ="btn btn-primario">Crea tabelle</un'>
			<a href ="#" id ="DB vuoto" class ="btn btn-primario">Database vuoto</un'>
			<a href ="#" id ="setExportOptions" class ="btn btn-primario">Esporta database</un'>
			<div id ="esportazioneOpzioni" class ="ImpexpOpzioni">
				<il>
					<in>
						<a href ="#" id ="exportDB" class ="btn btn-inline btn-primario">Salva localmente</un'>
					</in>
					<in>
						<a href ="#" id ="exportDbToDropbox" class ="btn btn-inline btn-primario">Salva in Dropbox</un'>
					</in>
				</il>
			</Div>
			<a href ="#" id ="setImportOptions" class ="btn btn-primario">Importa database</un'>
			<div id ="importOptions" class ="ImpexpOpzioni">
				<il>
					<in>
						<a href ="#" id ="importDB" class ="btn btn-inline btn-primario">Ripristina dal dispositivo</un'>
					</in>
					<in>
						<a href ="#" id ="importDbFromDropbox" class ="btn btn-inline btn-primario">Ripristina da Dropbox</un'>
					</in>
				</il>
			</Div>
		</Div>

Nella tua indice.css file aggiungiamo alcune regole:

.btn-inline{
    margine: 10Px 0 !importante;
    imbottitura: 5px 10px !importante;
}
.ImpexpOpzioni{
	Schermo: nessuna;
}
.impexpOptions ul{
	imbottitura: 0;
}
.impexpOptions ul li{
	Schermo: blocco-inline;
}

Modifiche alla logica

Nella tua indice.js file cerca i gestori di eventi del nostro pulsante e sostituiscili con quelli seguenti:

	$('#creaDB').clic(funzione (e) {
		e.preventDefault();
		creare tabelle();
	});

	$('#DB vuoto').clic(funzione (e) {
		e.preventDefault();
		dropTables();
	});

	$('#setExportOptions').clic(funzione (e) {
		e.preventDefault();
		$('#opzioni di esportazione').slideToggle(400, funzione(){
			$("html", corpo').animare({
				scrollTop: $('#opzioni di esportazione').compensare().superiore
			}, 600);
		});
	});

	$('#exportDB').clic(funzione (e) {
		e.preventDefault();
		exportBackup(falso);
	});

	$('#exportDbToDropbox').clic(funzione (e) {
		e.preventDefault();
		exportBackup(vero);
	});

	$('#setImportOptions').clic(funzione (e) {
		e.preventDefault();
		$('#importOptions').slideToggle(400, funzione () {
			$("html", corpo').animare({
				scrollTop: $('#importOptions').compensare().superiore
			}, 600);
		});
	});

	$('#importDB').clic(funzione (e) {
		e.preventDefault();
		importBackup(falso);
	});

	$('#importDbFromDropbox').clic(funzione (e) {
		e.preventDefault();
		importBackup(vero);
	});

Wow, molte cose sono cambiate qui! Così, let’s summarize the changes:

  • abbiamo aggiunto 2 gestori di eventi per pulsanti con id setExportOptions e setImportOptions: qui mostriamo solo div nascosti con pulsanti per eseguire effettivamente azioni (notare che abbiamo aggiunto una richiamata per scorrere la pagina e ottenere sempre il file 2 nuovi pulsanti visibili)
  • oltre ai pulsanti con ID exportDB e importDB abbiamo aggiunto 2 nuovi pulsanti con ID exportDbToDropbox e importDbFromDropbox
  • chiamando exportBackup() e importBackup() funzioni, we have used a boolean parameter we didn’t use before: questo parametro è impostato su false per esportare il database solo localmente e per importare il database da un file di backup locale; it’s set to true, anziché, se vogliamo salvare il nostro backup sul nostro account DBX o se vogliamo ripristinare il nostro database da un file di backup remoto salvato nel nostro account DBX

Infatti, we’re going to modify our exportBackup() e importBackup() funzioni per accettare come parametro e agire di conseguenza al suo valore.

Connessione a Dropbox

Prima di riscrivere le nostre funzioni per integrare il codice DBX, let’s see examine how we manage the connection through Oauth2. Prima il codice (estratto da exportBackup() funzione):

Se (dbxt == null) {
	dbx.authenticateWithCordova(funzione (token di accesso) {
		dbxt = nuovo Dropbox({token di accesso: token di accesso});
                //la tua roba qui
} altro {
        //la tua roba qui
}

Let’s analyze this code. Primo, controlliamo se dbxt è zero. Cosa è dbxt? È una connessione DBX tokenizzata, questo è l'oggetto che usiamo una volta autenticati in DBX. Come ricordi, abbiamo dichiarato questo oggetto immediatamente dopo la chiamata a app .. inizializzata metodo. E subito dopo aver dichiarato questo oggetto abbiamo impostato un altro oggetto che utilizziamo per eseguire il login a DBX, il dbx oggetto:

var dbxt;
var dbx = nuovo Dropbox({Identificativo cliente: IDENTIFICATIVO CLIENTE})

Così, if we didn’t already established a valid connection to DBX (dbxt è zero), quindi usiamo il authenticateWithCordova() metodo dell'oggetto dbx per eseguire il login e ottenere un accessToken che identificherà la nostra connessione come connessione autorizzata. Questo token di accesso sarà una proprietà di dbxt oggetto che ci consentirà di eseguire le azioni che dobbiamo fare. Se abbiamo già stabilito una connessione a DBX, we just go ahead with our stuff 🙂

Caricamento di file

Per esportare il nostro database in DBX dobbiamo utilizzare il file filesUpload() e filesDownload() metodi del nostro dbxt oggetto. Let’s see our new exportBackup() funzione:

funzione exportBackup(a Dropbox) {
	var successFn = funzione (SQL) {
		window.resolveLocalFileSystemURL(cordova.file.dataDirectory, funzione (dirEntry) {
			dirEntry.getDirectory("/ dropboxTestBackup", {creare: vero}, funzione (dirEntry) {
				dirEntry.getFile("dropboxTestBackup.sql", {creare: vero}, funzione (fileEntry) {
					mettere in guardia("Crea il file: " + fileEntry.name + '. Puoi trovarlo nella tua memoria interna al seguente percorso: Android/data/com.example.dropboxTest/files/dropboxTestBackup/');
					writeFile(fileEntry, SQL);
					Se (a Dropbox) {
						Se (dbxt == null) {
							dbx.authenticateWithCordova(funzione (token di accesso) {
								dbxt = nuovo Dropbox({token di accesso: token di accesso});
								dbxt.filesUpload({
									sentiero: '/' + fileEntry.name,
									Contenuti: SQL,
									modalità: 'sovrascrivi',
									muto: vero
								}).poi(funzione (risposta) {
									mettere in guardia('Il tuo backup è stato caricato con successo nel tuo Dropbox!')
									console.log(risposta);
								}).catturare(funzione (errore) {
									mettere in guardia('Errore durante il salvataggio del file nel tuo Dropbox! Puoi riprovare o copiare manualmente il file Android/data/com.webintenerife.qbook/files/qbookBackup/qbook.sql nella cartella Dropbox o in un altro luogo sicuro.')
									console.error(messaggio di errore);
								});
							}, funzione (e) {
								console.log("autenticazione Dropbox fallita");
								console.log(e.messaggio);
							});
						} altro {
							console.log('esportare: user already authenticated');
							dbxt.filesUpload({
								sentiero: '/' + fileEntry.name,
								Contenuti: SQL,
								modalità: 'sovrascrivi',
								muto: vero
							}).poi(funzione (risposta) {
								mettere in guardia('Il tuo backup è stato caricato con successo nel tuo Dropbox!')
								console.log(risposta);
							}).catturare(funzione (errore) {
								mettere in guardia('Errore durante il salvataggio del file nel tuo Dropbox! Puoi riprovare o copiare manualmente il file Android/data/com.webintenerife.qbook/files/qbookBackup/qbook.sql nella cartella Dropbox o in un altro luogo sicuro.')
								console.log(messaggio di errore);
							});
						}
					}
				});
			}, onErrorCreateFile);
		}, onErrorCreateDir);
	};
	cordova.plugins.sqlitePorter.exportDbToSql(Db, {
		successoFn: successoFn
	});
}

filesUpload() la funzione è abbastanza semplice. Lo passiamo seguendo i parametri:

  • sentiero: il percorso del file che vogliamo
  • soddisfare: i dati da scrivere nel file (questo viene passato alla funzione di callback successoFn() di cordova.plugins.sqlitePorter.exportDbToSql() funzione)
  • modalità: seleziona cosa fare se il file esiste già (i valori possibili vengono aggiunti, sovrascrivi e aggiorna: http://dropbox.github.io/dropbox-sdk-js/global.html#FilesWriteMode).
  • muto: un valore booleano da impostare se vogliamo ricevere una notifica da DBX quando il file è stato modificato (per quanto ne so, a luglio 21, 2017 this doesn’t work)

Al termine del caricamento, avvisiamo l'utente che il lavoro è terminato.

Download di file

E ora vai a vedere il importBackup() funzione:

funzione importBackup(daDropbox) {
	Se (!daDropbox) {
		var percorsoToFile = cordova.file.dataDirectory + '/dropboxTestBackup/dropboxTestBackup.sql';
		window.resolveLocalFileSystemURL(percorsoAFile, funzione (fileEntry) {
			fileEntry.file(funzione (file) {
				var reader = nuovo FileReader();
				reader.onloadend = funzione (e) {
					var successFn = funzione () {
						mettere in guardia('Database ripristinato con successo!');
						caricaPaesi();
						caricaUtenti();
					};
					cordova.plugins.sqlitePorter.importSqlToDb(Db, questo.risultato, {
						successoFn: successoFn
					});
				};
				lettore.leggereAsTesto(file);
			}, onErrorLoadFile);
		}, onErrorLoadFs);
	} altro {
		Se (dbxt == null) {
			dbx.authenticateWithCordova(funzione (token di accesso) {
				dbxt = nuovo Dropbox({token di accesso: token di accesso});
				dbxt.filesDownload({
					sentiero: "/dropboxTestBackup.sql"
				}).poi(funzione (risposta) {
					var reader = nuovo FileReader();
					lettore.leggereAsTesto(response.fileBlob);
					reader.onloadend = funzione () {
						var successFn = funzione () {
							mettere in guardia('Database ripristinato con successo!');
							caricaPaesi();
							caricaUtenti();
						};
						var errorFn = function (e) {
							console.log('error importing db');
							console.log(e.messaggio);
						};
						cordova.plugins.sqlitePorter.importSqlToDb(Db, questo.risultato, {
							successoFn: successoFn,
							errorFn: errorFn
						});
					};
				}).catturare(funzione (errore) {
					mettere in guardia('Error reading file from your Dropbox!');
					console.error(messaggio di errore);
				});
			}, funzione () {
				console.log("Failed to login to your Dropbox.");
			});
		} altro {
			dbxt.filesDownload({
				sentiero: "/dropboxTestBackup.sql"
			}).poi(funzione (risposta) {
				var reader = nuovo FileReader();
				lettore.leggereAsTesto(response.fileBlob);
				reader.onloadend = funzione () {
					var successFn = funzione () {
						mettere in guardia('Database ripristinato con successo!');
						caricaPaesi();
						caricaUtenti();
					};
					var errorFn = function (e) {
						console.log('error importing db');
						console.log(e.messaggio);
					};
					cordova.plugins.sqlitePorter.importSqlToDb(Db, questo.risultato, {
						successoFn: successoFn,
						errorFn: errorFn
					});
				};
			}).catturare(funzione (errore) {
				mettere in guardia('Error reading file from your Dropbox!');
				console.error(messaggio di errore);
			});
		}
	}
}

It’s a bit longer but it’s as simple as the previous one. Dopo aver stabilito una connessione valida a DBX, possiamo scaricare il file che vogliamo e passarlo al nostro lettore per leggerlo e, se tutto va bene, per passarlo al plugin SQLite Porter per importare il contenuto del file nel nostro database. Tutto fatto!

Ti consiglio di seguire passo passo il tutorial per comprenderne meglio la logica. Ma per i più pigri ho preparato un piccolo archivio che possono scaricare facendo clic sul pulsante in basso. L'archivio contiene solo i tre file principali indice.html, indice.css, e indice.js: basta estrarlo nel tuo file www / directory e rispondere sì per sovrascrivere i file esistenti.

File principali dell'applicazione

Ricorda solo di sostituire la falsa chiave dell'app nella riga index.js 21 con la tua app_key DBX!

Conclusioni

L'app è grezza, lo so, ma spero che possa illustrare abbastanza chiaramente come puoi connetterti a DBX dall'interno della tua app Android Cordova e come salvare / ripristinare un database. Probabilmente potresti voler aggiungere uno spinner o qualcos'altro per notificare all'utente che l'app è in esecuzione mentre il database viene esportato o importato, but this was not crucial for our goal here so I didn’t cover that.

What’s I really don’t like is the way inappbrowser Il plugin rimane bloccato su una pagina vuota mentre si connette a DBX, but I still don’t have found a valid workaround. Ho pensato che fosse possibile aprire una pagina remota personalizzata su un server e utilizzare Php o ASP per fare il lavoro sporco prima di tornare all'app, ma questo inserirà un terzo elemento (un server esterno) Vorrei evitare. Hai qualche idea? Fammi sapere!

 


 

2 commenti su “Come salvare il database a Dropbox (e come ripristinarlo) all'interno di un'applicazione Cordova – solo Android (parte 3)”

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *