Обновление
KitKat добавил публичный метод для непосредственного вызова javascript: valuJavascript ()
Для более старых apis вы можете попробовать решение, подобное приведенному ниже, но если бы мне пришлось сделать это снова, я бы посмотрел просто на создание метода совместимости, который на KitKat использует вышеупомянутый метод, а на старых устройствах использует отражение для детализации. к внутреннему приватному методу: BrowserFrame.stringByEvaluatingJavaScriptFromString ()
Тогда вы можете напрямую вызывать javascript, не имея дело с loadUrl и добавляя "javascript: "
к сценарию.
Старый ответ
По просьбе Алока Кулькарни я дам приблизительный обзор возможного обходного пути, о котором я подумал. Я на самом деле не пробовал, но в теории это должно работать. Этот код будет грубым и приведен только в качестве примера.
Вместо того, чтобы отправлять вызовы через 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, чтобы увидеть, существует ли поле EditText в WebView и находится ли оно в фокусе. Если он есть, вы бы использовали этот метод организации очередей, но если бы его не было в фокусе, вы могли бы просто вызвать loadUrl () как обычно. Таким образом, он использует этот обходной путь только тогда, когда это действительно необходимо.