Захват переадресации страниц через javascript в Android WebView

У меня есть WebView в моем приложении, которое отображает страницу, не принадлежащую мне. Мое желаемое поведение заключается в том, что если какая-либо ссылка используется пользователем, запускается приложение браузера устройств, и там загружается результирующая страница. К сожалению, эта страница делает некоторые странные вещи, поэтому shouldOverrideUrlLoading() не срабатывает.

Мое решение состоит в том, чтобы перехватить javascript в pushState и использовать интерфейс для запуска кода Android для запуска приложения-браузера.

Вот мой интерфейс:

public class LaunchExternalBrowserHack {
    Context mContext;

    LaunchExternalBrowserHack(Context c) {
        mContext = c;
    }

    @JavascriptInterface
    public void launchExternalBrowser(String url) {
        openUrl(url);
    }
}

Я ввожу некоторый javascript на страницу в onPageFinished():

public void onPageFinished(WebView view, String url) {
     mWebView.loadUrl(javascript);
}

Вот мой javascript:

private final String javascript = "javascript:history.pushState = function (state, title, url) { console.log(url); console.log(location.href); Uphoria.launchExternalBrowser(location.origin, url); };";

И, конечно же, я добавляю интерфейс к WebView:

mWebView.addJavascriptInterface(new LaunchExternalBrowserHack(getContext()), "Android");

Итак, это похоже на работу. Приложение Browser запускается, и открывается следующая страница.

Однако WebView также продвигается вперед. Я хочу предотвратить это, но я не могу найти способ предотвратить перемещение WebView, сохраняя при этом URL-адрес пересылки и запуска приложения Browser. Как я упоминал ранее, на этой веб-странице shouldOverrideUrlLoading срабатывает не.

Идеи?

Ответ 1

Пользователь пытается отойти от страницы. чтобы он не двигался, верните ложь. чтобы он отошел, не возвращай ничего, но вы можете выполнить любой код, который вы можете захотеть. Это событие запускается немедленно, когда происходит событие навигации, включая обновление страницы.

private final String javascript = "window.onbeforeunload = function(){ dosomething(); }; window.unload = function(){ dosomething(); }; function dosomething() { /* Write code here */  };"

Вам нужно включить весь код javascript выше, поскольку некоторые браузеры используют onbeforeunload, а некоторые используют unload

ИЗМЕНИТЬ

После тщательного изучения вашей проблемы я нашел, что мое решение малоэффективно.

Здесь другой подход с использованием history. Если ваша история пуста, это означает ее первую страницу. но если у вас есть некоторые элементы в истории, это означает, что навигация произошла.

Вы можете проверить это как

private final String javascript = "javascript:"+"if(window.history.length>=1 && document.referrer=='') Android.launchExternalBrowser(location.href);";

Ответ 2

Этот ответ неверен. Упоминается здесь, потому что у него есть важные релевантные комментарии.

Причина, по которой вы не получаете результат от вашего Javascript, заключается в том, что вы не вызываете функцию напрямую. Вы назначаете функцию в своем Javascript, которая возвращает значение, но оно не вернет это в ваш код, оно вернет это для любых вызовов history.pushState().

private final String javascript = "javascript:" + "var pushState = history.pushState; history.pushState = function () " +
        "{ pushState.apply(history, arguments); console.log(arguments); return location.href; " +
        "};";

Вместо этого вы можете проверить, возвращает ли что-то подобное значение:

private final String javascript = "(function() { return location.href; })();";