Android의 Javascript에서 반환 값을 얻고 싶습니다. 아이폰으로는 할 수 있지만 안드로이드로는 할 수 없습니다. loadUrl을 사용했지만 개체 대신 void를 반환했습니다. 아무도 나를 도울 수 있습니까?
답변
과 동일 Keith
하지만 짧은 대답
webView.addJavascriptInterface(this, "android");
webView.loadUrl("javascript:android.onData(functionThatReturnsSomething)");
그리고 기능을 구현하십시오
@JavascriptInterface
public void onData(String value) {
//.. do something with the data
}
목록 onData
에서 제거하는 것을 잊지 마십시오 proguard
(proguard를 활성화 한 경우).
답변
이를 달성하는 방법에 대한 해킹이 있습니다.
이 클라이언트를 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;
}
}
이제 자바 스크립트 호출에서 다음을 수행하십시오.
webView.loadUrl("javascript:alert(functionThatReturnsSomething)");
이제 onJsAlert 호출에서 “message”에 반환 된 값이 포함됩니다.
답변
addJavascriptInterface()
Javascript 환경에 Java 개체를 추가하는 데 사용 합니다. Javascript가 해당 Java 개체에 대한 메서드를 호출하여 “반환 값”을 제공하도록합니다.
답변
오늘 제가 생각해 낸 것이 있습니다. 스레드로부터 안전하고 합리적으로 효율적이며 Android WebView 용 Java에서 동기식 Javascript 실행을 허용합니다 .
Android 2.2 이상에서 작동합니다. (Javascript 문자열로 eval ()에 전달 된 코드 조각이 필요하기 때문에 commons-lang이 필요합니다. 코드를 따옴표가 아니라에서 래핑하여이 종속성을 제거 할 수 있습니다. 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);
}
}
답변
API 19 이상에서이를 수행하는 가장 좋은 방법은 WebView에서 evaluationJavascript 를 호출 하는 것 입니다.
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
답변
@Felix Khazin이 제안한 솔루션이 작동하지만 한 가지 핵심 포인트가 누락되었습니다.
에서 웹 페이지 WebView
가로드 된 후 자바 스크립트 호출이 이루어져야합니다 . 이 추가 WebViewClient
받는 WebView
과 함께 WebChromeClient
.
전체 예 :
@Override
public void onCreate(Bundle savedInstanceState) {
...
WebView webView = (WebView) findViewById(R.id.web_view);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new MyWebViewClient());
webView.setWebChromeClient(new MyWebChromeClient());
webView.loadUrl("http://example.com");
}
private class MyWebViewClient extends WebViewClient {
@Override
public void onPageFinished (WebView view, String url){
view.loadUrl("javascript:alert(functionThatReturnsSomething())");
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
}
private class MyWebChromeClient extends WebChromeClient {
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
Log.d("LogTag", message);
result.confirm();
return true;
}
}
답변
사용자 지정 체계를 사용하는 대체 변형 :
주요 활동
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
final WebView webview = new CustomWebView(this);
setContentView(webview);
webview.loadUrl("file:///android_asset/customPage.html");
webview.postDelayed(new Runnable() {
@Override
public void run() {
//Android -> JS
webview.loadUrl("javascript:showToast()");
}
}, 1000);
}
}
CustomWebView
public class CustomWebView extends WebView {
public CustomWebView(Context context) {
super(context);
setup();
}
@SuppressLint("SetJavaScriptEnabled")
private void setup() {
setWebViewClient(new AdWebViewClient());
getSettings().setJavaScriptEnabled(true);
}
private class AdWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("customschema://")) {
//parse uri
Toast.makeText(CustomWebView.this.getContext(), "event was received", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
}
}
customPage.html (접힌 자산에 위치)
<!DOCTYPE html>
<html>
<head>
<title>JavaScript View</title>
<script type="text/javascript">
<!--JS -> Android-->
function showToast() {
window.location = "customschema://goto/";
}
</script>
</head>
<body>
</body>
</html>