Подтвердить что ты не робот

Android Phonegap: уведомлять javascript при завершении работы AsyncTask

в моем приложении, когда пользователь нажимает кнопку в веб-браузере, будет вызываться плагин phonegap для запуска асинтезы для загрузки файла из Интернета. Теперь я хочу отправить сигнал обратно в часть javascript, когда асинтеза закончена. Но я не знаю, как это сделать, потому что мой плагин уже отправил что-то еще до завершения асинтез. Кто-нибудь знает, как я могу уведомить свою часть javascript без плагина в Phonegap?

4b9b3361

Ответ 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);
      }     
}

Что все.

Надеюсь, это поможет кому-то.