PhoneGap DBLoader per Android

androidRecentemente abbiamo dovuto eseguire il porting di alcune funzionalità presenti su una web application preesistente  in modo tale che alcune funzionalità in essa presenti potessero essere agevolmente fruibili su dispositivi mobili con sistema Android. Una delle specifiche che occorreva rispettare è quella che la web app potesse funzionare completamente offline e successivamente eseguire una sincronizzazione dei dati nel momento in cui la connessione fosse disponibile. A ben considerare le cose si è scelto di utilizzare SQLite come sistema di storage e abbiamo provveduto a creare un plug-in per Cordova (PhoneGap) che provvedesse ad eseguire l’importazione. Innanzitutto occorre creare il database che bisogna successivamente importare e questo può essere fatto in diversi modi a seconda dei casi, l’ideale sarebbe se il vostro attuale database server avesse un’utility che permettesse di eseguire l’esportazione della struttura e dei dati nel formato SQLite in alternativa ciò deve essere fatto in modo manuale. Alla fine di questo primo processo abbiamo un file che da ora in poi chiameremo database.db e che provvederemo a copiare nella cartela assets del progetto android.  Passiamo ora alla creazione del plug-in PhoneGap che realizza il caricamento del database e che chiameremo “dbLoader”. Il workflow per fare quanto detto consiste nei seguenti passaggi:

  • Settare i permessi nel file AndroidManifest.xml della nostra applicazione
  • Settare i riferimenti al plug-in nel config.xml
  • Costruire la classe Java che realizza nativamente la copia del database
  • Costruire l’interfaccia Javascript che useremo per richiamare il plug-in

Settare i permessi nel file AndroidManifest.xml della nostra applicazione
All’interno del file AndroidManifest.xml bisogna accertarsi di aver settato i seguenti permessi:

1
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Settare i riferimenti al plug-in nel config.xml All’interno del progetto Android nella cartella res/xml bisogna settare i riferimenti al nostro plug-in all’interno del file config.xml. All’interno del tag plugins sono presenti l’insieme di tag plugin che rappresentano tutti i vari elementi del framework PhoneGap che si stanno attualmente usando nella propria applicazione. In sostanza bisogna aggiungere un nuovo tag plugin come di seguito:

1
<plugin name="dbLoader" value="it.nacios.app.dbloader.DBLoader"/>

Il tag plugin contiene due attributi name che rappresenta il nome attraverso cui verrà referenziato il nostro plugin all’interno dell’engine javascript e value che invece costituisce il percorso completo della classe Java che realizza il comportamento nativo da noi voluto. Per chi è abituato ad usare java sa che i nomi dei file che rappresentano le classi terminano con l’estensione .java in questo caso non è necessaria.

Costruire la classe Java che realizza nativamente la copia del database
Nel codice di seguito creiamo la classe DBLoader che estende CordovaPlugin e sovrascrive il metodo execute che è quello che verrà richiamato dal javascript engine. Nel metodo execute controlliamo che l’action richiesta sia loadDB e in tal caso richiamiamo il metodo privato che esegue il caricamento del file contenente il database per l’applicazione. L’unico parametro da impostare in questa classe è il campo statico denominato DATA_FOLDER che rappresenta la cartella in cui verrà copiato il file database.db. Nel caso in cui si verifichino degli errori verranno segnalati attraverso la chiamata del metodo error di CallbackContext.

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
//PACKAGE IN CUI SI TROVA LA CLASSE DBLoader
package it.nacios.app.dbloader;
 
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
 
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
 
public class DBLoader extends CordovaPlugin {
        //PATH DEL DATABASE
	private static final String DATA_FOLDER = "/data/data/it.nacios.app/app_database";
 
	@Override
	public boolean execute(String action, JSONArray args,CallbackContext callbackContext) throws JSONException {
		if(action.equals("loadDB")){ 
			this.loadDB(args.getString(0),callbackContext);
			return true;
		}
		return false;
	}
 
	private void loadDB(String dbFileName,CallbackContext callbackContext){
		InputStream in = null;
		OutputStream out = null;
		if(dbFileName != null &amp;&amp; dbFileName.length()&gt;0){
			try {
				in = this.webView.getContext().getAssets().open(dbFileName);
				File file = new File(DATA_FOLDER+dbFileName);
				if(file.exists() &amp;&amp; file.isFile()){
					file.delete();
					file.createNewFile();
					out = new FileOutputStream(file);
					byte[] buffer = new byte[4096];
					int bytesRead;
					while ((bytesRead = in.read(buffer)) != -1)
						out.write(buffer, 0, bytesRead);
					in.close();
					out.close();
					callbackContext.success();
				}
 
			} catch (IOException e) {
				callbackContext.error("Error: "+e.getMessage());
			}
		}
		else{
			callbackContext.error("Error: dbFileName not defined");
		}			
	}
}

Costruire l’interfaccia Javascript che useremo per richiamare il plug-in A questo punto siamo giunti all’ultimo passo cioè la costruzione dell’interfaccia javascript che permetterà di richiamare il codice Java appena creato.  Definiamo dapprima un nuovo modulo a cui associamo il nome dbLoader dopo di che creiamo una classe DBLoader a cui associamo un metodo loadDB che prende in input il nome del file del database e richiama attraverso cordova.exec() l’action loadDB della classe DBLoader. Alla fine esportiamo la classe appena creata in modo che sia visibile nel namespace javascript.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cordova.define("cordova/plugin/dbLoader",
function(require, exports, module) {
  var exec = require("cordova/exec");
 
  var DBLoader = function () {};
 
  DBLoader.prototype.loadDB = function(dbFileName,success,fail) {
    cordova.exec(success,fail,"dbLoader","loadDB",[dbFileName]);    
  };
  var loaderDB = new DBLoader();
  module.exports = loaderDB;
});
 
if (!window.plugins) {
    window.plugins = {};
}
if (!window.plugins.dbLoader) {
    window.plugins.dbLoader = 
      cordova.require("cordova/plugin/dbLoader");
}

Una volta configurato il progetto Android come detto in precedenza e importato all’interno del progetto web il file javascript che realizza l’interfaccia per richiamare il plugin dbLoader possiamo usarlo all’interno dell’applicazione richiamandolo nel seguente modo:

1
2
var dbl = cordova.require("cordova/plugin/dbLoader");
dbl.loadDB('database.db',success,error);

success e error sono due callback che verranno usate per gestire i casi di successo e insuccesso dell’operazione richiesta e cioè la creazione di un database SQLite con un determinato nome che non è nient’altro che il primo parametro da passare al metodo loadDB della classe javascript creata in precedenza.

Il plugin appena creato è utile nel caso in cui il database da popolare risulti ricco di dati preesistenti infatti sarebbe difficile e soprattutto poco efficiente si in termini di memoria che di tempo richiederne il popolamento attraverso chiamate via web ad un servizio web atto a fare ciò.

P.S. Il codice descritto nell’articolo è stato testato con android 2.3.6 e 4.0.3 e versioni del framework PhoneGap 2.3.0 e 2.7.0

Per chi volesse scaricare il codice sorgente descritto nell’articolo può farlo a questo indirizzo:https://github.com/naciostechnologies/dbloader

0 commenti

Lascia un Commento

Vuoi partecipare alla discussione?
Fornisci il tuo contributo!

Lascia un commento

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