2013-03-21 16 views
5

Ho creato un plug-in molto semplice PhoneGap per iniziare a testare il modo in cui sto per creare alcune azioni native su Android.Acquisisci il valore restituito da PhoneGap Plugin

JavaScript:

function callNativePlugin() { 
      cordova.exec(nativePluginResultHandler, nativePluginErrorHandler, "Database", "saveAdvertencia", [ 1, "TesteAdv" ]); 
     } 

    function nativePluginResultHandler(result) { 
     alert("SUCCESS: \r\n" + result); 
    } 

    function nativePluginErrorHandler(error) { 
     alert("ERROR: \r\n" + error); 
    } 

Java:

@Override 
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { 
    if (action.equals("saveAdvertencia")) { 
     advertenciaDS = new AdvertenciaDS(cordova.getActivity()); 
     callbackContext.sendPluginResult(new PluginResult(Status.OK, new JSONArray("test"))); 
     return true; 
    } 
    return false; 
} 

cosa ho bisogno è un modo per recuperare il risultato dall'azione con lo stesso metodo. È molto complicato gestire sempre 3 metodi (1 per eseguire l'azione 1 per definire quale sarà l'azione di successo 1 per definire quale sarà l'azione dell'errore) quando non controlli realmente quando vengono chiamati, poiché PhoneGap li chiama dopo che l'azione è stata completata.

Se ho bisogno di recuperare alcuni dati dal database nativo Android:

  1. chiamata in JavaScript del "cordova.exec".
  2. PhoneGap chiamerà il tuo plug-in.
  3. Il tuo plug-in restituirà 2 elementi: Un booleano per PhoneGap che definisce che tutto ha funzionato come previsto o meno. I dati che verranno passati ai metodi sucessfull.
  4. Ecco la parte difficile per me. In caso di esito positivo o negativo, è necessario creare 2 metodi per i quali non si ha il controllo di quando verranno chiamati, poiché PhoneGap lo deciderà. Come posso cambiare questo?
+0

@mafutrct Grazie per la correzione formato di testo! – MBarni

+0

Tutto il merito va a @Real, ho appena corretto un piccolo dettaglio – mafu

risposta

5

utilizzare questo modello per avere solo un callback per le funzioni previste dal plugin:

function callNativePlugin(callback) { 
    cordova.exec(function(result) { 
     callback(null, result); 
    }, function(result) { 
     callback("myerror"); 
    }, "Database", "saveAdvertencia", [ 1, "TesteAdv" ]) 
}; 

questo modo si ottiene callback stile Node.JS in cui il primo argomento è l'errore e secondo è il risultato:

//define the callback function 
var callbackFunction = function(err, result) { 
    if (err) { 
     console.log("there was an error"); 
    } else { 
     console.log("success", result); 
    } 
}; 

//call the plugin 
callNativePlugin(callbackFunction); 

non si può evitare di avere due funzioni di callback nel vostro plug-in, in quanto questo è obbligatorio per l'API Cordova, ma non c'è bisogno di esporre che agli utenti di plugin.

+0

Vuoi dire callNativePlugin? –

+0

Mi dispiace ... Mi manca il codice. Ha già funzionato ora. – MBarni

+0

È sbagliato? (nuova versione) http://pastebin.com/MTAH3MZN – MBarni

0

All'interno JavaScript, sono stato in grado di recuperare il valore plug PhoneGap con un solo metodo ricorsivo facilmente controllabile:

function callNativePlugin(result, error, service, action, json) { 
    if (result != null) { 
     //alert("SUCCESS: \r\n" + result); 
     return result; 
    } else if (error != null) { 
     //alert("ERROR: \r\n" + error); 
     return error; 
    } 
    return cordova.exec(function(result) {callNativePlugin(result, null, null, null);}, function(error) {callNativePlugin(null, error, null, null);}, service, action, json); 
} 
+0

Qual è il valore di questo su un insieme di 3 funzioni che ancora non funzionano? Essenzialmente si ha una funzione che si comporta in tre modi e non funziona ancora perché non è possibile restituire un valore in modo sincrono da una chiamata asincrona come cordova.exec() (o almeno non così semplicemente e non si dovrebbe). Cioè, il ritorno dalla funzione di callback non influisce sul valore di ritorno di cordova.exec, e probabilmente si verifica dopo che cordova.exec ritorna. Meglio solo per usarlo in modo asincrono come progettato: funzione callback (valore) {console.log (valore); } cordova.exec (callback, callback, "Foo", "bar", []); –

+0

Funziona e viene utilizzato nella mia app. Perché declassare un aswer che funziona? Fai la tua risposta e se è davvero migliore e ben spiegata, la voterò come corretta. – MBarni

+0

Quando dico che non funziona, voglio dire che non restituisce un risultato o un errore, anche se chiamerà la funzione nativa. È solo una versione più complicata di quella che hai avuto nella domanda. Suggerirò anche un'altra risposta. –

2

Se stai chiedendo un modo per trasformare cordova.exec() da una chiamata asincrona in una chiamata sincrona che restituisce un valore, la risposta breve è che non è possibile. (La lunga risposta è che puoi fingere usando un loop o un timeout ma non dovresti.)

Come spiega Vlad, è possibile creare la propria interfaccia in modo da avere solo una funzione da chiamare, ma io uso qualcosa di simile a questa versione più semplice (in http://htmlpresenter.com/api.html):

var Database = { 
    saveAdvertencia: function(args, callback) { 
    cordova.exec(callback, 
     function(error) { console.log("Error calling Database.saveAdvertencia: " + error); }, 
     "Database", "saveAdvertencia", args) 
    } 
} 

Poi chiamare in questo modo fornendo la linea richiamata se è necessario il risultato:

Database.Advertencia([1, "TesteAdv"], function(result) { alert(result); }); 

Naturalmente se (come sembra essere il caso) non è necessario il risultato a tutti, si può semplicemente utilizzare questa versione:

function saveAdvertencia() { 
    log = function(message) { console.log(message) }; 
    cordova.exec(log, log, "Database", "saveAdvertencia", arguments); 
} 

saveAdvertencia(1, "TesteAdv"); 

(Edit :) Inoltre, questa sfida può essere correlato a questo, meglio domanda: