Я'м пытаюсь использовать новые evaluateJavascript способ в Android 4.4, но все, что я когда-нибудь снова-нулевой результат:
webView1.evaluateJavascript("return \"test\";", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Log is written, but s is always null
}
});
Как мне вернуть результат этого метода?
Обновление: немного подробнее:
возвращение 'тест';
,возвращение { тест: 'Это' }
консоли.журнал('тест');
выполняется нормально.Устройства: как Nexus 7 и Nexus 5 (Сток)
Есть пример метода evaluateJavascript используется в данном примере:
https://github.com/GoogleChrome/chromium-webview-samples/tree/master/jsinterface-example
По сути, если JavaScript выполняется в WebView возвращает значение, она'll быть принят в обратного вызова.
Главное, обратите внимание, что строка, возвращаемая в OnReceiveValue либо значение в JSON, JSON-объект или массив JSON в зависимости от того, что вы вернетесь.
Вещи, чтобы отметить об этом, если вы вернуть одно значение, вы должны использовать setLenient(правда) на читателя JSON для того, чтобы работать.
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// In KitKat+ you should use the evaluateJavascript method
mWebView.evaluateJavascript(javascript, new ValueCallback<String>() {
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onReceiveValue(String s) {
JsonReader reader = new JsonReader(new StringReader(s));
// Must set lenient to parse single values
reader.setLenient(true);
try {
if(reader.peek() != JsonToken.NULL) {
if(reader.peek() == JsonToken.STRING) {
String msg = reader.nextString();
if(msg != null) {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
}
}
} catch (IOException e) {
Log.e("TAG", "MainActivity: IOException", e);
} finally {
try {
reader.close();
} catch (IOException e) {
// NOOP
}
}
}
});
}
Причина, по которой вы можете захотеть использовать парсер для ответа строка преобразуется в значение в формате JSON, который означает, что он будет обернут в кавычки.
Например, если вы пошли:
mWebView.evaluateJavascript("(function() { return 'this'; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints: "this"
}
});
Он будет печатать строку этот, завернутый в двойные кавычки:"эта " и;.
Другие примеры стоит отметить:
mWebView.evaluateJavascript("(function() { return null; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints the string 'null' NOT Java null
}
});
mWebView.evaluateJavascript("(function() { })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); //s is Java null
}
});
mWebView.evaluateJavascript("(function() { return ''; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints "" (Two double quotes)
}
});
ОК, так получается результат
вот результат вызову JavaScript - как если бы нужно было ввести команду в консоль JavaScript.
Поэтому для того, чтобы получить результат, он должен быть обернут в функцию:
webView1.evaluateJavascript("(function() { return \"this\"; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints 'this'
}
});
Это также будет работать:
webView1.evaluateJavascript("window.variable = \"asd\";", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints asd
}
});
Метод также обрабатывает объекты в JavaScript:
webView1.evaluateJavascript("(function() { return { var1: \"variable1\", var2: \"variable2\" }; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // Prints: {"var1":"variable1","var2":"variable2"}
}
});
AndroidJSCore является хорошей альтернативой для оценки JavaScript, который не использовать объект WebView.
Если вы хотите придерживаться с WebView и нужно оценивать JavaScript на более ранних версиях Android (4+), здесь немного библиотеки:
https://github.com/evgenyneu/js-evaluator-for-android
jsEvaluator.evaluate("put your JavaScript code", new JsCallback() {
@Override
public void onResult(final String result) {
// get result here (optional)
}
});
Обобщить ответы @GauntFace и обеспечить альтернативное решение без использования парсера JSON:
Если ваша функция JS возвращает просто строку, и вы'вновь гадает о том, почему строка исковеркали в Java, это's, потому что он'ы в формате JSON-убежал.
mWebView.evaluateJavascript("(function() { return 'Earvin \"Magic\" Johnson'; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.d("LogName", s);
// expected: s == Earvin "Magic" Johnson
// actual: s == "Earvin \"Magic\" Johnson"
}
});
(обратите внимание, что onReceiveValue
всегда строка
, а функция JS может возвращать значение null, количество литералов и т. д.)
Для получения строкового значения такие же, как в JS, если вы'вэ 100% уверен, что вы'вновь ждет правильная "строка" вернулся, Вы'd нужен в JSON-раскодировал его, например так:
String unescaped = s.substring(1, s.length() - 1) // remove wrapping quotes
.replace("\\\\", "\\") // unescape \\ -> \
.replace("\\\"", "\""); // unescape \" -> "
Однако, обратите внимание, что S
может быть строкой в "нуль"
в случае, если в JS возвращает правильное значение null, так что вы, очевидно, нужно проверить, что в качестве самого первого шага.
if ("null".equals(s)) {
...
} else {
// unescape JSON
}
Все'ы ответ велик. Я просто добавить еще один пункт. Дон'т положить evaluateJavascript внутри метода с @JavascripInterface аннотации такой способ
@JavascripInterface общественного недействительными onData(){ mWebView.evaluateJavascript("на языке JavaScript:executeNext()" но,значение null); }
Потому что это будет блокировать поток JavaBridge.
если вы хотите положить evaluateJavascript внутри него. Сделать это с таким образом
``
@JavascripInterface
общественного недействительными onData(){
mWebView.пост(новый Runnable() {
@Переопределить
общественного недействительными Run() {
mWebView.evaluateJavascript("на языке JavaScript:executeNext()" но,значение null);
}
});
} ``