Ответ 1
Обновление
KitKat добавил публичный метод для непосредственного вызова javascript: оценитьJavascript()
Для более старой версии apis вы можете попробовать решение, как показано ниже, но если бы мне пришлось это сделать снова, я бы посмотрел только на создание метода совместимости, который в KitKat использует вышеуказанный метод и на более старых устройствах, использует отражение для детализации для внутреннего частного метода: BrowserFrame.stringByEvaluatingJavaScriptFromString()
Затем вы можете напрямую вызвать javascript, не имея дело с loadUrl и добавив "javascript: "
в script.
Старый ответ
В соответствии с просьбой Алока Кулкарни, я дам краткий обзор возможного обходного пути, о котором я думал об этом. Я на самом деле не пробовал, но теоретически он должен работать. Этот код будет грубым и просто служит примером.
Вместо того, чтобы отправлять вызовы через loadUrl(), вы ставите в очередь свои javascript-вызовы, а затем javascript вытаскивает их. Что-то вроде:
private final Object LOCK = new Object();
private StringBuilder mPendingJS;
public void execJS(String js) {
synchronized(LOCK) {
if (mPendingJS == null) {
mPendingJS = new StringBuilder();
mPendingJS.append("javascript: ");
}
mPendingJS
.append(js)
.append("; ");
}
}
Вместо вызова метода loadUrl() этот метод. (Для этого просто я использовал синхронизированный блок, но это может быть лучше подходит для другого маршрута. Поскольку javascript работает в своем потоке, это должно быть потокобезопасным в той или иной форме).
Тогда ваш WebView будет иметь такой интерфейс:
public class JSInterface {
public String getPendingJS() {
synchronized(LOCK) {
String pendingCommands = mPendingJS.toString();
mPendingJS.setLength(0);
mPendingJS.append("javascript: ");
return pendingCommands;
}
}
}
Это возвращает строку с ожидающими командами и очищает их, чтобы они не возвращались снова.
Вы бы добавили его в WebView следующим образом:
mWebView.addJavascriptInterface(new JSInterface(), "JSInterface");
Тогда в вашем javascript вы установили бы некоторый интервал, в который нужно сбросить отложенные команды. На каждом интервале он вызывал бы JSInterface.getPendingJS()
, который возвращал бы строку всех ожидающих команд, а затем вы могли бы их выполнить.
Вы можете улучшить это, добавив проверку метода execJS, чтобы узнать, существует ли в WebView поле EditText и находится в фокусе. Если он есть, то вы будете использовать этот метод очередности, но если его не было в фокусе, вы можете просто вызвать loadUrl(), как обычно. Таким образом, он использует это обходное решение, когда ему действительно нужно.