Android: перехватывать вызов AJAX из WebView - PullRequest
14 голосов
/ 15 октября 2010

Я хочу, чтобы приложение HTML/javascript, работающее в WebView, выполняло AJAX вызовы, которые обрабатываются кодом Java.
Идеально было бы просто перехватить вызов (просто, просто используйте shouldOverrideUrlLoading()) и «вернуть» некоторые данные.
Однако я не нахожу способа «вернуть» ответ на WebView, кроме вызова функции javascript с использованием loadUrl().
Это не будет работать для меня, так как приложение HTML/javascript представляет собой встроенное приложение, которое я не контролирую. Что касается приложения HTML / javascript, оно просто вызывает AJAX и получает обратно некоторые данные.

Есть мысли по этому поводу?

Ответы [ 3 ]

32 голосов
/ 21 апреля 2011

Хорошие новости для всех: с API уровня 11 они помещают метод shouldInterceptRequest в класс WebViewClient.Он также запускает запросы приложения внутри триггеров WebView.Вы можете переопределить его следующим образом:

@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url)
{
    if (magicallyMatch(url))
        return new WebResourceResponse("application/json", "utf-8", magicallyGetSomeInputStream());

    return null;
}

Из справочника Android :

public WebResourceResponse shouldInterceptRequest (представление WebView, Stringurl)

С тех пор: Уровень API 11

Уведомить приложение хоста о запросе ресурса и разрешить приложению вернуть данные.Если возвращаемое значение равно нулю, WebView продолжит загружать ресурс как обычно.В противном случае, ответный ответ и данные будут использованы.ПРИМЕЧАНИЕ. Этот метод вызывается сетевым потоком, поэтому клиенты должны соблюдать осторожность при доступе к частным данным.

Параметры

view WebView, запрашивающийresource.

url Необработанный URL-адрес ресурса.

Возвращает

A WebResourceResponse, содержащую информацию ответа, или ноль, если WebView должен загрузить сам ресурс.

Также проверьте WebResourceResponse .

Надеюсь, это поможет.

11 голосов
/ 10 августа 2014

Вы можете использовать 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
                            "});");

            });
    }
}

Основная идея взята из здесь и представлена ​​с некоторыми хитростями.
Хотя немного поздно представить ответ, но надеюсьэто помогает и другим!

2 голосов
/ 27 октября 2010

В конце концов я все равно использовал метод, описанный в вопросе;

Я перехватил некоторые конкретные запросы, например: foo://bar/get/1?callback=foobar, затем проанализировал URL и вызвал функцию обратного вызова javascript с фактическими данными.
Функция обратного вызова была определена в части запроса URL, поэтому в приведенном выше примере это будет: foobar();

Вызов этой функции был прост, просто используйте: yourWebView.loadUrl("javascript:foobar('somedata')");

...