Android Phonegap: Notificar a javascript cuando se termina un AsyncTask
En mi aplicación, cuando el usuario haga clic en un botón en webview, un complemento phonegap se llamará para activar un asynctask para descargar el archivo de Internet. Ahora quiero enviar una señal de nuevo a la parte javascript cuando el asynctask está terminado. Pero no sé cómo hacerlo, porque mi complemento ya había enviado algo antes de que el asynctask se haya terminado. ¿Alguien sabe cómo puedo notificar mi parte javascript sin complemento en Phonegap?
- Google Analytics interfiere con history.back () en el navegador android?
- Jquery móvil - keydown keydown en dispositivos móviles
- Angularjs Phonegap Android usando Websockets
- Cordova 3.6.3 Plugin de archivos - obtenga archivos de video locales en android
- En Android, ¿cómo puedo establecer el valor de un cuadro de edición en WebView mediante JavaScript?
- Cordova Barcodescanner - Utilizar cámara frontal
- Técnica fiable para el seguimiento de invitaciones a instalaciones móviles
- KeyCode en android es siempre 229
- Phonegap: Mientras arrastra la pantalla se borra en Android Jelly bean
- Cómo cargar un archivo js de los elementos en la vista web después de cargar html
- Android- usando addJavaScriptInterface para devolver un valor de Javascript
- Cómo evitar eventos de clic en el cuerpo del documento (quizás un error en Córdoba?)
- JQuery Autocompletar trabajando en Chrome pero no en android usando phonegap
También hice esta pregunta en Phonegap Grupo de Google, aquí está la respuesta de Simon Mac Donald. Funciona perfectamente para mí:
Puede manejar esta situación utilizando la API de complemento con bastante facilidad. Se implementa en los elementos básicos del API Conexión y batería. Lo que debe hacer es:
1) En su método execute () de su plugin, guarde el callbackId que obtiene.
2) Devolver un resultado de plugin NO_RESULT y establecer keep callback id a true.
PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT); pluginResult.setKeepCallback(true); return pluginResult;
3) Cuando termina el método async java devolver otro resultado de plugin como este:
PluginResult result = new PluginResult(PluginResult.Status.OK, data); result.setKeepCallback(false); this.success(result, this.myCallbackId);
Como he dicho, usted puede mirar el código en GitHub para ver cómo estamos utilizando esto para la conexión y la batería.
Así es como resuelvo problemas como tu.
1) Cree y asocie un JavascriptInterface a su WebView. A JavascriptInterface es simplemente una clase dentro de la cual puede declarar algún método Java que desee utilizar de JS.
public class JSInterface() { private final CountDownLatch latch = new CountDownLatch(1); public void waitForProceed() { try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } public void canProceed() { latch.countDown(); } }
2) En su AsyncTask, al final del método onPostExecute()
, tiene que llamar al método canProceed()
para notificar a JSInterface que puede salir del método waitForProceed()
.
public class MyAsyncTask extends AsyncTask<.......> { private JSInterface jsi; ... // other class property public MyAsyncTask(JSInterface jsi) { ... //do what you want with other class property this.jsi = jsi; } @Override public ... doInBackground(...) { ... //do something } @Override public void onPostExecute(...) { ... //do something jsi.canProceed(); } }
3) En su actividad tiene que asociar el objeto JSInterface a su WebView:
WebView mWebView; ... mWebView.getSettings().setJavaScriptEnabled(true); mWebView.addJavascriptInterface(new JSInterface(), "JSIface");
4) Finalmente, en JS, puedes llamar a AsyncTask (no sé cómo lo llamas, pero supongo que usas somthing como un JSInterface) y después del método waitForProceed()
llamada:
startAsyncTask(); //somehow JSIface.waitForProceed();
Espero que resuelva su problema;)
He aquí un ejemplo detallado:
Permite crear alguna interfaz que se debe llamar cuando AsyncTask
terminará las cosas, ae cuando onPostExecute
llamado.
En mi caso, obtenemos algunos datos de JSONArray
MyTaskListenerItf.java
public interface GroupTaskListenerItf { public void onTaskDone(JSONArray groupArray); }
La plantilla AsyncTask
ve así:
MyBuildTask.java
public class MyBuildTask extends AsyncTask<Void, Void, SomeData>{ private MyTaskListenerItf mTl = null; public MyBuildTask(Context context, MyTaskListenerItf tl) { super(); this.mContext = context; this.mTl = tl; } @Override protected SomeData doInBackground(Void... params) { /* ... */ } @Override protected void onPostExecute(WmTransferItem transferItem) { // ... if(this.mTl != null){ JSONArray data = new JSONArray(""); this.mTl.onTaskDone(data); } // .. } }
Así que ahora nuestra clase CordovaPlugin
debería verse así:
MyCordovaPlugin.java
public class MyCordovaPlugin extends CordovaPlugin implements GroupTaskListenerItf { // we need this callback when Task will finish private CallbackContext mMyCallbackContext = null; @Override public boolean execute(String action, JSONArray args,CallbackContext callbackContext) throws JSONException { if("runMe".equals(action)){ final GroupTaskListenerItf gt = this; mMyCallbackContext = callbackContext; // pass our 'GroupTaskListenerItf' interface to async class MyBuildTask task = new MyBuildTask(cordova.getActivity(), gt); task.execute(); PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT); pluginResult.setKeepCallback(true); callbackContext.sendPluginResult(pluginResult); } else{ this.cordova.getThreadPool().execute( new Runnable() { public void run() { // BTW, here you might run something else out of UI Thread } }); } } /* ... */ @Override public void onTaskDone(JSONArray data) { if (this.mGroupCallbackContext != null) { PluginResult result = new PluginResult(PluginResult.Status.OK, data); result.setKeepCallback(false); this.mMyCallbackContext.sendPluginResult(result); } }
Eso es todo.
Espero que ayude a alguien.
- Google Play Services versión 5.2.08 demasiado reciente para mi dispositivo
- Android Studio, de repente tiene problemas de controlador de GPU al ejecutar el emulador