PhoneGap Progress dialog per Android

Come realizzare un plug-in PhoneGap per richiamare il progress dialog nativo di android usato in applicazioni html5, css3, javascript.

PhoneGapQuando si sviluppano applicazioni mobili utilizzando HTLM5, CSS3 e JavaScript, magari impiegando framework quali PhoneGap, a volte risulta utile poter richiamare componenti nativi dell’interfaccia grafica del sistema operativo sottostante, nel caso in questione Android. In un’applicazione può capitare di avviare processi e richieste a server esterni che potrebbero impiegare molto tempo a terminare,  spesso in queste situazioni vi è la necessità di segnalare all’utente cosa stia accadendo ed impedirgli di eseguire ulteriori azioni che potrebbero portare l’applicazione a trovarsi in uno stato inconsistente.  È questo il caso in cui possiamo avvalerci di un progress dialog.

Nel momento in cui si realizza un app con tecnologia web la logica applicativa viene gestita in una WebView (CordovaWebView nel caso di PhoneGap) e il codice verrà eseguito sul thread WebCore e non sull’UI thread (User Interface thread), aspetto molto importante che bisogna tenere sempre presente perchè il progress dialog che si intende realizzare deve interagire con l’UI thread e non bloccare il WebCore thread.
Il plug-in PhoneGap che premette la gestione di un progress dialog non è molto difficile da implementare e una volta stabilito il suo nome “simpleProgressDialog” di seguito si riporta il workflow per fare quanto detto:

  • Settare i riferimenti al plug-in PhoneGap nel config.xml
  • Costruire la classe Java che richiama il Progress Dialog nativo di Android
  • Costruire l’interfaccia Javascript che useremo per richiamare il plug-in PhoneGap

Settare i riferimenti al plug-in PhoneGap 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.

Questo file xml contiene un tag plugins all’interno del quale sono presenti un insieme di tag plugin che rappresentano tutti i vari elementi del framework PhoneGap e di terze parti che sono attualmente attivi nella propria applicazione. In sostanza bisogna aggiungere un nuovo tag plugin come di seguito:

1
<plugin name="simpleProgressDialog" value="it.nacios.app.dialog.SimpleProgressDialog" />

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 componente nativo voluto. 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 richiama il Progress Dialog nativo di Android
Nel codice di seguito si procede alla creazione della classe SimpleProgressDialog che estende CordovaPlugin e sovrascrive il metodo execute che è quello che verrà richiamato dal javascript engine. Nel metodo execute viene controllata quale sia l’action richiesta show oppure hide che rispettivamente creano o distruggono il progress dialog. Nel caso l’action sia show viene valutato se l’array JSON args contiene un valore che rappresenta il messaggio, se questo valore non è impostato nel progress dialog verrà visualizzato un messaggio di default “Attendere prego…”.
In questo plugin dato che occorre interagire con l’UI thread si deve dapprima ottenere il contesto dell’applicazione con l’istruzione:

1
cordova.getActivity();

Di seguito occorre creare un nuovo thread grafico che possa operare su tale contesto così come riportato nelle linee di codice dalla 19 alla 32.

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
//PACKAGE IN CUI SI TROVA LA CLASSE DEL PLUGIN CHE RICHIAMA IL PROGRESS DIALOG 
package it.nacios.app.dialog;
 
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
 
import android.app.ProgressDialog;
import android.content.Context;
 
public class SimpleProgressDialog extends CordovaPlugin {
	//RIFERIMENTO ALL'ISTANZA DEL PROGRESS DIALOG
        private ProgressDialog spd = null;
	@Override
	public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
	  if("show".equals(action)){
	    final Context currentCtx = cordova.getActivity();
            //OTTENIAMO IL CONTESTO E AVVIAMO UN UI THREAD
	    cordova.getActivity().runOnUiThread(new Runnable() {	
	      @Override
	      public void run() {
	        String msg = null;
		try{
		  msg = args.getString(0);
		}
		catch(Exception e){
		  msg = "Attendere prego...";		
		}
		spd = ProgressDialog.show(currentCtx, "", msg);
		callbackContext.success();
	      }
	    });
	    return true;
	  }
	  else if("hide".equals(action)){
	    cordova.getActivity().runOnUiThread(new Runnable() {	
	      @Override
	      public void run() {
	        if(spd != null){
	          spd.dismiss();
		  spd = null;
	        }
	        callbackContext.success();
	      }
            });
	    return true;
          }
          return false;
        }	
    }

Costruire l’interfaccia Javascript che useremo per richiamare il plug-in PhoneGap
A questo punto si è giunti all’ultimo passo cioè la costruzione dell’interfaccia javascript che permetterà di richiamare il codice Java appena creato. Si definisce dapprima un nuovo modulo a cui viene associato il nome simpleProgressDialog dopo di che si crea una classe SimpleProgressDialog avente due metodi show e hide. Il metodo show prende in input il messaggio da visualizzare quando il progress dialog è azionato e richiama l’action show della classe Java SimpleProgressDialog attraverso il metodo cordova.exec(), mentre il metodo hide deve essere semplicemente chiamato senza alcun parametro ed andrà ad azionare l’action hide. Alla fine la classe appena creata viene esportata 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
21
22
cordova.define("cordova/plugin/simpleProgressDialog", function(require, exports, module) {
	var exec = require("cordova/exec");
	var SimpleProgressDialog = function () {};
 
	SimpleProgressDialog.prototype.show = function(values) {
	    cordova.exec(null,null,"simpleProgressDialog","show",[values]);    
	};
 
	SimpleProgressDialog.prototype.hide = function(){
		cordova.exec(null,null,"simpleProgressDialog","hide",[]);
	};
 
	var spDialog  = new SimpleProgressDialog();
	module.exports = spDialog;
});
 
if (!window.plugins) {
    window.plugins = {};
}
if (!window.plugins.spDialog) {
    window.plugins.spDialog = cordova.require("cordova/plugin/simpleProgressDialog");
}

Il plugin denominato simpleProgressDialog è ora pronto per essere impiegato all’interno dell’applicazione.
La prima cosa da fare è creare il riferimento al plugin richiamando il comando cordova.exec():

1
var spd = cordova.require("cordova/plugin/simpleProgressDialog");

Dopo di che per visualizzare il progress dialog con un determinato messaggio bisogna chiamare il metodo show(“messaggio da visualizzare”) dell’oggetto SimpleProgressDialog:

1
spd.show("Attendere prego...");

Nel momento in cui occorre dismettere il progress dialog basta richiamare il seguente comando:

1
spd.hide();

Nel caso in cui ci fossero una serie di operazioni in sequenza che si intende segnalare è opportuno richiamare il metodo show() più volte e soltanto alla fine il metodo hide(). Questo accorgimento migliora sensibilmente le prestazioni.

Il plugin PhoneGap appena descritto è utile nel caso si debbano avviare dei processi o richieste che richiedano una lunga elaborazione durante le quali si voglia vietare all’utente qualsiasi tipo di interazione con l’applicazione.

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/simpleprogressdialog

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 *