在我的应用程序中,当用户点击webview中的按钮时,将调用phonegap插件来触发asynctask从Internet下载文件。现在我想在asynctask完成时将信号发送回javascript部分。但我不知道该怎么做,因为我的插件已经在asynctask完成之前发回了一些东西。有没有人知道如何在Phonegap中没有插件的情况下通知我的javascript部分?
答案 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);
}
}
这就是全部。
希望它会对某人有所帮助。