我想從Android中的Javascript獲取返回值。我可以用iPhone來完成,但我無法使用Android。我使用loadUrl,但它返回void而不是一個對象。有誰能夠幫助我?謝謝。如何從android的webview的JavaScript中獲取返回值?
回答
使用addJavascriptInterface()
將Java對象添加到Javascript環境。讓您的Javascript調用該Java對象的方法來提供其「返回值」。
這裏是你如何能做到這一個黑客:在onJsAlert
webView.loadUrl("javascript:alert(functionThatReturnsSomething)");
現在:
此客戶端添加到您的WebView:
final class MyWebChromeClient extends WebChromeClient {
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
Log.d("LogTag", message);
result.confirm();
return true;
}
}
在javascript調用
現在做調用「消息」將包含返回的值。
這是一個非常有價值的破解;特別是當你正在構建一個應用程序時,你無法控制javascript並且不得不使用現有的功能。注意你可以使用'public boolean onConsoleMessage(ConsoleMessage consoleMessage)'而不是'onJsAlert'來攔截JS警報,然後在javascript調用中執行'webView.loadUrl(「javascript:console.log(functionThatReturnsSomething) 「);' - 這樣你就可以獨自留下JS警報。 – 2012-07-09 03:46:46
「WebChromeClient.onConsoleMessage」的解決方案似乎更清晰,但請注意,它不適用於某些HTC設備。看到[這個問題](http://stackoverflow.com/questions/4860021/android-problem-with-debugging-javascript-in-webview)瞭解更多信息。 – Piotr 2012-07-13 09:29:57
使用addJavascriptInterface的任何理由都不會更好? – Keith 2013-02-11 06:15:13
這是我今天想到的。它是線程安全的,相當高效,並且允許從Java的同步Javascript執行Android WebView。
適用於Android 2.2及更高。 (需要commons-lang,因爲我需要將我的代碼片段作爲Javascript字符串傳遞給eval(),您可以通過將代碼不包含在引號中來消除此依賴關係,但是在function(){}
)
首先,將此添加到您的Javascript文件:
function evalJsForAndroid(evalJs_index, jsString) {
var evalJs_result = "";
try {
evalJs_result = ""+eval(jsString);
} catch (e) {
console.log(e);
}
androidInterface.processReturnValue(evalJs_index, evalJs_result);
}
然後,將它添加到你的Android活動:
private Handler handler = new Handler();
private final AtomicInteger evalJsIndex = new AtomicInteger(0);
private final Map<Integer, String> jsReturnValues = new HashMap<Integer, String>();
private final Object jsReturnValueLock = new Object();
private WebView webView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
webView = (WebView) findViewById(R.id.webView);
webView.addJavascriptInterface(new MyJavascriptInterface(this), "androidInterface");
}
public String evalJs(final String js) {
final int index = evalJsIndex.incrementAndGet();
handler.post(new Runnable() {
public void run() {
webView.loadUrl("javascript:evalJsForAndroid(" + index + ", " +
"\"" + StringEscapeUtils.escapeEcmaScript(js) + "\")");
}
});
return waitForJsReturnValue(index, 10000);
}
private String waitForJsReturnValue(int index, int waitMs) {
long start = System.currentTimeMillis();
while (true) {
long elapsed = System.currentTimeMillis() - start;
if (elapsed > waitMs)
break;
synchronized (jsReturnValueLock) {
String value = jsReturnValues.remove(index);
if (value != null)
return value;
long toWait = waitMs - (System.currentTimeMillis() - start);
if (toWait > 0)
try {
jsReturnValueLock.wait(toWait);
} catch (InterruptedException e) {
break;
}
else
break;
}
}
Log.e("MyActivity", "Giving up; waited " + (waitMs/1000) + "sec for return value " + index);
return "";
}
private void processJsReturnValue(int index, String value) {
synchronized (jsReturnValueLock) {
jsReturnValues.put(index, value);
jsReturnValueLock.notifyAll();
}
}
private static class MyJavascriptInterface {
private MyActivity activity;
public MyJavascriptInterface(MyActivity activity) {
this.activity = activity;
}
// this annotation is required in Jelly Bean and later:
@JavascriptInterface
public void processReturnValue(int index, String value) {
activity.processJsReturnValue(index, value);
}
}
感謝上述代碼 - 我在Android項目中採用了它。但是,由於糟糕的Java API設計,它有一個陷阱。該行: jsReturnValueLock.wait(waitMs - (System.currentTimeMillis() - start)); wait()函數參數的值有時可能會發生評估爲0.這意味着「無限等待」 - 我偶爾會遇到「無響應」錯誤。我通過測試解決了這個問題: if(elapsed> = waitMS)break; 而不是再次調用System.currentTimeMillis(),但使用過去的值。最好編輯並修改上面的代碼。 – gregko 2013-03-30 21:01:03
非常感謝!我也看到了這一點,也從未想出它是從哪裏來的。 – Keith 2013-04-01 14:06:31
但是,如果我在button.click監聽器等中運行evalJS。 waitForJsReturnValue可能會導致evalJs()掛起。因此,handler.post()中的webView.loadUrl()可能沒有機會執行,因爲button.click監聽器沒有返回。 – victorwoo 2013-07-11 09:18:53
同Keith
但更短的答案
webView.addJavascriptInterface(this, "android");
webView.loadUrl("javascript:android.onData(functionThatReturnsSomething)");
並實現功能
@JavascriptInterface
public void onData(String value) {
//.. do something with the data
}
不要忘記從proguard
列表中刪除onData
(如果啓用了proguard的)
你能詳細介紹'proguard'部分嗎? – eugene 2014-07-10 13:51:22
@eugene如果你不知道它是什麼,你可能不會使用它。無論如何,它的東西,使反向工程,你的應用程序更難 – 2014-07-10 14:08:46
謝謝。我知道我在項目的根目錄下有proguard-project.txt,但沒有更多。我在問,因爲你的解決方案有效,但我得到了SIGSEGV。我正在評估'document.getElementById(「my-div」)。scrollTop'從SwipeRefreshLayout :: canChildScrollUp()獲取滾動位置。我懷疑這可能是由於在短時間內打了太多次電話。或'proguard'我懷疑是因爲我只是不知道它是什麼.. – eugene 2014-07-11 01:31:08
是@Felix Khazin建議工程的解決方案,但有一個關鍵點缺失。
在調用WebView
的網頁後,應該調用javascript調用。將此WebViewClient
與WebChromeClient
一起添加到WebView
。
完整的例子:
在API 19+,要做到這一點的最好方法是調用evaluateJavascript您的WebView:
webView.evaluateJavascript("foo.bar()", new ValueCallback<String>() {
@Override public void onReceiveValue(String value) {
// value is the result returned by the Javascript as JSON
}
});
有更詳細的相關答案:https://stackoverflow.com/a/20377857
- 1. 獲取從OnPostExecute Android的返回值
- 2. 如何從JavaScript中的Handler函數獲取返回值?
- 3. 如何從Android中的JSON獲取多個返回值
- 4. 從Javascript *可靠*返回值到Webview
- 5. 如何從android的webview文本框中獲取值?
- 6. 如何從包含jQuery.get()的JavaScript函數獲取返回值?
- 7. 如何從Html裏面獲取JavaScript函數的返回值?
- 8. 如何從javascript獲取返回值的.cs頁
- 9. 如何從WCF獲取,設置和返回值中獲取值?
- 10. 從javascript函數獲取返回值
- 11. 如何從IJavaScriptExecutor獲取返回值
- 12. 如何從c#中的回調方法獲取返回值
- 13. 從WebKit/JavaScriptCore中的Javascript中獲取返回值
- 14. 如何在fancybox2中獲取javascript函數的返回值?
- 15. 如何在Python中獲取此JavaScript函數的返回值?
- 16. 如何通過JSP從JavaScript獲取返回值?
- 17. 如何從JavaScript函數獲取多個返回值
- 18. 如何通過javaScript/jquery從php獲取多個返回值?
- 19. 如何從Laravel的返回數組中獲取密鑰的值
- 20. 如何從android中的webview中獲取選定的文本?
- 21. 如何從webview獲取結果值?
- 22. 如何獲取d3.ease的返回值?
- 23. 如何從PHP中獲取Android的值
- 24. 如何從Android中的plist獲取值?
- 25. 如何從QueryString返回的列表中獲取字符串值?
- 26. 如何從Toad中的函數獲取返回值
- 27. 如何從PDO中的存儲函數獲取返回值?
- 28. 如何從返回的延遲實例中獲取值
- 29. 如何從bash腳本中獲取matlab的返回值?
- 30. 如何從螞蟻腳本中的exec獲取返回值
我怎麼能在像http:// stackoverflow這樣的情況下做到這一點。com/questions/5521191 /返回值 - 從-javascript-function-in-android – vnshetty 2011-04-02 04:59:08
如果您的js不寫入此對象並且您無法觸摸js,則這並不起作用。 – 2014-02-04 09:14:42
@PacMani:使用'loadUrl(「javascript:...」)'(API Level 1-18)或'evaluateJavascript()'(API Level 19+)在當前加載的Web上下文中評估自己的JavaScript頁。 – CommonsWare 2014-02-04 12:34:04