Android Phonegap:AsyncTask完成后通知javascript

时间:2011-10-13 08:43:54

标签: javascript android cordova android-asynctask

在我的应用程序中,当用户点击webview中的按钮时,将调用phonegap插件来触发asynctask从Internet下载文件。现在我想在asynctask完成时将信号发送回javascript部分。但我不知道该怎么做,因为我的插件已经在asynctask完成之前发回了一些东西。有没有人知道如何在Phonegap中没有插件的情况下通知我的javascript部分?

3 个答案:

答案 0 :(得分:35)

我也在Phonegap Google Group中提出了这个问题,这是Simon Mac Donald的回应。它对我来说很完美:


您可以非常轻松地使用Plugin API来处理这种情况。它 在核心API项目Connection和Battery中实现。你是什​​么 需要做的是:

1)在你的插件的execute()方法中保存你得到的callbackId。

2)返回NO_RESULT插件结果并将keep call id设置为true。

    PluginResult pluginResult = new  PluginResult(PluginResult.Status.NO_RESULT); 
    pluginResult.setKeepCallback(true); 
    return pluginResult; 

3)当异步java方法完成后,返回另一个插件结果,如下所示:

    PluginResult result = new PluginResult(PluginResult.Status.OK, data); 
    result.setKeepCallback(false); 
    this.success(result, this.myCallbackId); 

正如我所说,您可以查看GitHub中的代码,了解我们如何将它用于Connection和Battery。


答案 1 :(得分:2)

这就是我解决像你这样的问题的方法。

1)创建JavascriptInterface并将其与WebView相关联。 JavascriptInterface只是一个类,你可以在其中声明一些你想从JS中使用的Java方法。

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)在您的Activity中,您必须将JSInterface对象与WebView关联:

WebView mWebView;

...

mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSInterface(), "JSIface");

4)最后,在JS中,您可以调用AsyncTask(我不知道您如何调用它,但我猜您使用的是类似JSInterface的东西)并且在调用waitForProceed()方法之后:

startAsyncTask(); //somehow
JSIface.waitForProceed();

我希望它能解决你的问题;)

答案 2 :(得分:0)

这是一个详细的例子:

让我们创建一些应该在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);
      }     
}

这就是全部。

希望它会对某人有所帮助。