Android: перехват вызова AJAX из WebView
Я хочу приложение HTML/javascript
, работающее в WebView
, чтобы сделать вызовы AJAX
, которые обрабатываются кодом Java
.
Идеальным было бы просто перехватить вызов (легко, просто использовать shouldOverrideUrlLoading()
) и "вернуть" некоторые данные.
Тем не менее, я не нахожу способ "вернуть" ответ на WebView
, кроме вызова функции javascript
, используя loadUrl()
.
Это не сработает для меня, так как приложение HTML/javascript
- это приложение, которое я не контролирую. Что касается приложения HTML/javascript, он просто выполняет вызов AJAX
и возвращает некоторые данные.
Любые мысли об этом?
Ответы
Ответ 1
В конце концов, я использовал метод, описанный в вопросе,
Я перехватил некоторые конкретные запросы, такие как: foo://bar/get/1?callback=foobar
, затем разобрал URL
и вызвал функцию обратного вызова javascript с фактическими данными.
Функция обратного вызова была определена в части запроса URL
, поэтому в приведенном выше примере это будет: foobar();
Вызов этой функции был простым, просто используйте: yourWebView.loadUrl("javascript:foobar('somedata')");
Ответ 2
Хорошая новость: С уровнем API уровня 11 они добавили метод shouldInterceptRequest
в класс WebViewClient
. Он также запускает запросы приложения внутри триггеров WebView
. Вы можете переопределить его следующим образом:
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url)
{
if (magicallyMatch(url))
return new WebResourceResponse("text/json", "utf-8", magicallyGetSomeInputStream());
return null;
}
Из Ссылка на Android:
public WebResourceResponse shouldInterceptRequest (представление WebView, строковый URL)
Так как: Уровень API 11
Уведомлять хост применение запроса ресурса и разрешить приложению возвращать данные. Если возвращаемое значение равно null, WebView
будет продолжать загружать ресурс как обычно. В противном случае обратный ответ и данные будут использоваться. ПРИМЕЧАНИЕ. Этот метод вызывается сетевой поток, чтобы клиенты проявляйте осторожность при доступе к частные данные.
Параметры
view
WebView
, запрашивающий ресурс.
url
Необработанный URL-адрес ресурса.
Возвращает
A WebResourceResponse
, содержащий ответную информацию или null, если WebView
должен загрузить ресурс сам по себе.
Также проверьте WebResourceResponse.
Надеюсь, что это поможет.
Ответ 3
Вы можете использовать JavascriptInterface для перехвата вызовов AJAX вместе с методами JQuery ajaxStart
и ajaxComplete
следующим образом:
// our JavascriptInterface
public class AjaxHandler {
private static final String TAG = "AjaxHandler";
private final Context context;
public AjaxHandler(Context context) {
this.context = context;
}
public void ajaxBegin() {
Log.w(TAG, "AJAX Begin");
Toast.makeText(context, "AJAX Begin", Toast.LENGTH_SHORT).show();
}
public void ajaxDone() {
Log.w(TAG, "AJAX Done");
Toast.makeText(context, "AJAX Done", Toast.LENGTH_SHORT).show();
}
}
И вот как AjaxHandler
используется в Activity
:
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private WebView webView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// get web view
webView = (WebView) findViewById(R.id.web);
// configure web view
final WebSettings webSettings = webView.getSettings();
webSettings.setBuiltInZoomControls(true);
webSettings.setJavaScriptEnabled(true);
webView.loadUrl("http://foo.com");
// add javascript interface
webView.addJavascriptInterface(new AjaxHandler(this), "ajaxHandler");
// override onPageFinished method of WebViewClient to handle AJAX calls
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.loadUrl("javascript:$(document).ajaxStart(function (event, request, settings) { " +
"ajaxHandler.ajaxBegin(); " + // Event called when an AJAX call begins
"});");
view.loadUrl("javascript:$(document).ajaxComplete(function (event, request, settings) { " +
"ajaxHandler.ajaxDone(); " + // Event called when an AJAX call ends
"});");
});
}
}
Основная идея взята из здесь и представлена некоторыми настройками.
Хотя его немного поздно представить ответ, но надеюсь, что это поможет и другим!