Android Phonegap:当 AsyncTask 完成时通知 javascript
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7751522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android Phonegap: Notify javascript when an AsyncTask is finished
提问by Peacemoon
in my app, when user click on a button in webview, a phonegap plugin will be called to trigger an asynctask to download file from internet. Now i want to send a signal back to javascript part when the asynctask is finished. But i don't know how to do it, because my plugin had already send something back before the asynctask is finished. Does anyone know how i can notify my javascript part without plugin in Phonegap?
在我的应用程序中,当用户单击 webview 中的按钮时,将调用 phonegap 插件以触发 asynctask 从 Internet 下载文件。现在我想在异步任务完成时将信号发送回 javascript 部分。但我不知道该怎么做,因为我的插件在异步任务完成之前已经发回了一些东西。有谁知道我如何在没有 Phonegap 插件的情况下通知我的 javascript 部分?
回答by Peacemoon
I also asked this question in Phonegap Google Group, here is response of Simon Mac Donald. It works perfectly for me:
我也在 Phonegap Google Group 中问过这个问题,这是 Simon Mac Donald 的回应。它非常适合我:
You can handle this situation by using the Plugin API quite easily. It is implemented in the core API items Connection and Battery. What you need to do is:
您可以通过使用插件 API 轻松处理这种情况。它在核心 API 项 Connection 和 Battery 中实现。你需要做的是:
1) In your execute() method of your plugin save the callbackId you get.
1) 在您的插件的 execute() 方法中保存您获得的 callbackId。
2) Return a NO_RESULT plugin result and set keep callback id to true.
2) 返回一个 NO_RESULT 插件结果并将保持回调 id 设置为 true。
PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
pluginResult.setKeepCallback(true);
return pluginResult;
3) When you async java method finishes return another plugin result like this:
3)当你异步java方法完成返回另一个插件结果是这样的:
PluginResult result = new PluginResult(PluginResult.Status.OK, data);
result.setKeepCallback(false);
this.success(result, this.myCallbackId);
As I said, you can look at the code in GitHub to see how we are using this for Connection and Battery.
正如我所说,您可以查看 GitHub 中的代码,了解我们如何将其用于连接和电池。
回答by Vito Gentile
This is how I solve problems like your.
这就是我如何解决像你这样的问题。
1) Create and associate a JavascriptInterface to your WebView. A JavascriptInterface is simply a class inside which you can declare some Java method you want to use from JS.
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) In your AsyncTask, at the end of onPostExecute()
method, you have to call the canProceed()
method to notify to JSInterface that it can exit from waitForProceed()
method.
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) In your Activity you have to associate the JSInterface object to your WebView:
3) 在您的 Activity 中,您必须将 JSInterface 对象与您的 WebView 相关联:
WebView mWebView;
...
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSInterface(), "JSIface");
4) Finally, in JS, you can call AsyncTask (I don't know how you call it, but I guess you use somthing like a JSInterface) and after call waitForProceed()
method:
4)最后,在JS中,你可以调用AsyncTask(我不知道你是怎么调用的,但我猜你使用了像JSInterface这样的东西)和after callwaitForProceed()
方法:
startAsyncTask(); //somehow
JSIface.waitForProceed();
I hope it solves your problem ;)
我希望它能解决你的问题;)
回答by Maxim Shoustin
Here is a detailed example:
下面是一个详细的例子:
Lets create some interface that should be called when AsyncTask
will finish the stuff, a.e when onPostExecute
called.
让我们创建一些应该在AsyncTask
完成这些东西时onPostExecute
调用的接口,即在调用时调用。
In my case we fetch some JSONArray
data
就我而言,我们获取一些JSONArray
数据
MyTaskListenerItf.java
MyTaskListenerItf.java
public interface GroupTaskListenerItf {
public void onTaskDone(JSONArray groupArray);
}
The AsyncTask
template of looks like:
的AsyncTask
模板看起来像:
MyBuildTask.java
我的构建任务.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);
}
// ..
}
}
So now our CordovaPlugin
class should look like:
所以现在我们的CordovaPlugin
类应该是这样的:
MyCordovaPlugin.java
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);
}
}
That's all.
就这样。
Hope it will help to someone.
希望它会帮助某人。