в моем приложении, когда пользователь нажимает кнопку в веб-браузере, будет вызываться плагин phonegap для запуска асинтезы для загрузки файла из Интернета. Теперь я хочу отправить сигнал обратно в часть javascript, когда асинтеза закончена. Но я не знаю, как это сделать, потому что мой плагин уже отправил что-то еще до завершения асинтез. Кто-нибудь знает, как я могу уведомить свою часть javascript без плагина в Phonegap?
Android Phonegap: уведомлять javascript при завершении работы AsyncTask
Ответ 1
Я также задал этот вопрос в Phonegap Google Group, вот ответ Саймона Мак Дональда. Он отлично работает для меня:
Вы можете справиться с этой ситуацией, используя API плагинов довольно легко. Это реализован в основных элементах API Connection и Battery. Что ты вам нужно сделать следующее:
1) В вашем методе execute() вашего плагина сохраните обратный вызов, который вы получите.
2) Верните результат плагина NO_RESULT и установите для идентификатора обратного вызова значение true.
PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
pluginResult.setKeepCallback(true);
return pluginResult;
3) Когда вы закончите метод async java, верните другой результат плагина следующим образом:
PluginResult result = new PluginResult(PluginResult.Status.OK, data);
result.setKeepCallback(false);
this.success(result, this.myCallbackId);
Как я уже сказал, вы можете посмотреть код в GitHub, чтобы узнать, как мы это используем для подключения и батареи.
Ответ 2
Вот как я решаю такие проблемы, как ваш.
1) Создайте и сопоставьте JavascriptInterface с вашим WebView. JavascriptInterface - это просто класс, внутри которого вы можете объявить некоторый Java-метод, который вы хотите использовать из 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) В вашей AsyncTask, в конце метода onPostExecute()
, вы должны вызвать метод canProceed()
, чтобы уведомить JSInterface о том, что он может выйти из метода 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) В вашей деятельности вам нужно связать объект JSInterface с вашим WebView:
WebView mWebView;
...
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSInterface(), "JSIface");
4) Наконец, в JS вы можете вызвать AsyncTask (я не знаю, как вы это называете, но я думаю, вы используете что-то вроде JSInterface) и после вызова метода waitForProceed()
:
startAsyncTask(); //somehow
JSIface.waitForProceed();
Я надеюсь, что он решает вашу проблему;)
Ответ 3
Вот подробный пример:
Позволяет создать некоторый интерфейс, который должен вызываться, когда AsyncTask
закончит материал, a.e при вызове onPostExecute
.
В моем случае мы получаем некоторые данные JSONArray
MyTaskListenerItf.java
public interface GroupTaskListenerItf {
public void onTaskDone(JSONArray groupArray);
}
Шаблон AsyncTask
выглядит так:
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);
}
// ..
}
}
Итак, теперь наш класс CordovaPlugin
должен выглядеть так:
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);
}
}
Что все.
Надеюсь, это поможет кому-то.