Android WebView (4.4) преобразует пользовательский URL-адрес

У меня есть приложение, которое интенсивно использует Android WebView для отображения пользовательского HTML-контента. Последнее обновление Android (4.4/Kit-Kat/SDK-19) содержит переработанный файл WebView.

Один из моих пользователей с Nexus 5 сообщил о проблеме, когда некоторые ссылки приводят к сбою приложения. Я запустил эмулятор 4.4 и отладил метод shouldOverrideUrlLoading() моего WebViewClient. Во всех ранее протестированных версиях Android (2.2-4.3) URL-адрес String, переданный в метод, содержал мой собственный URL-адрес с символами «/». В 4.4 точно такая же ссылка теперь имеет символы «\» вместо них.

Это не имеет для меня никакого смысла. Я загружаю HTML точно так же, поэтому каким-то образом новый WebView преобразовал все мои косые черты в обратные косые черты.

Почему новый WebView делает это?


person Jon    schedule 11.11.2013    source источник


Ответы (4)


Изменения в обработке URL — известная проблема. Дополнительные сведения см. в руководстве по миграции.

Поведение в этом конкретном случае будет зависеть от схемы вашего базового URL-адреса, из того, что вы описываете, я предполагаю, что схема вашего базового URL-адреса - «http (s)://», и в этом случае Chromium WebView выполняет нормализация URL.

Возможно, вы захотите использовать класс URI для обработки несоответствия между Классические и Chromium WebView в этом случае.

person marcin.kosiba    schedule 13.11.2013
comment
Первоначально я принял свой собственный ответ, потому что это был немедленный ответ на мою проблему, но этот ответ помог мне в нескольких других местах, где у меня были некоторые пользовательские значения href, которые испортились из-за того, как 4.4 обрабатывал мои пользовательские URL-адреса. Так что спасибо! - person Jon; 10.12.2013

Я сделал больше отладки и обнаружил, что на самом деле у меня обратный вопрос. Оказывается, старые версии WebView преобразовывали URL, а не новую.

Я загружаю HTML в формате, подобном этому, в WebView:

    <a href="this\\is\\my\\custom\\path">link</a>

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

Новая версия WebView оставляет мой пользовательский URL нетронутым, давая мне ту же самую строку, что и исходный HTML. Получается, что проблема в старом WebView, а не в новом.

person Jon    schedule 11.11.2013
comment
Не могли бы вы помочь мне с этим, stackoverflow.com/questions/20582282/ - person Shakti Malik; 14.12.2013

Новый WebView применяет дополнительные ограничения при запросе ресурсов и разрешении ссылок, использующих пользовательскую схему URL-адресов. Например, если вы реализуете обратные вызовы, такие как shouldOverrideUrlLoading() или shouldInterceptRequest(), тогда WebView вызывает их только для допустимых URL-адресов.

Если вы используете настраиваемую схему URL-адресов или базовый URL-адрес и заметили, что ваше приложение получает меньше вызовов для этих обратных вызовов или не может загрузить ресурсы на Android 4.4, убедитесь, что в запросах указаны допустимые URL-адреса, соответствующие RFC 3986.

Например, новый WebView может не вызывать ваш метод shouldOverrideUrlLoading() для таких ссылок:

Показать профиль Результат перехода пользователя по такой ссылке может быть разным:

Если вы загрузили страницу, вызвав loadData() или loadDataWithBaseURL() с недопустимым или пустым базовым URL-адресом, вы не получите обратный вызов shouldOverrideUrlLoading() для этого типа ссылки на странице. Примечание. Если вы используете loadDataWithBaseURL(), а базовый URL-адрес недействителен или имеет значение null, все ссылки в загружаемом контенте должны быть абсолютными.

Если вы загрузили страницу, вызвав loadUrl(), или предоставили допустимый базовый URL-адрес с помощью loadDataWithBaseURL(), то вы получите обратный вызов shouldOverrideUrlLoading() для этого типа ссылки на странице, но URL-адрес, который вы получите, будет абсолютным относительно текущая страница. Например, URL-адрес, который вы получите, будет "http://www.example.com/showProfile". просто "showProfile". Вместо использования простой строки в ссылке, как показано выше, вы можете использовать пользовательскую схему, например следующую:

<a href="example-app:showProfile">Show Profile</a>

Затем вы можете обработать этот URL-адрес в методе shouldOverrideUrlLoading() следующим образом:

// The URL scheme should be non-hierarchical (no trailing slashes)
  private static final String APP_SCHEME = "example-app:";

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (url.startsWith(APP_SCHEME)) {
        urlData = URLDecoder.decode(url.substring(APP_SCHEME.length()), "UTF-8");
       respondToData(urlData);
        return true;
    }
    return false;
}

Если вы не можете изменить HTML, вы можете использовать loadDataWithBaseURL() и установить базовый URL-адрес, состоящий из пользовательской схемы и действительного хоста, например «example-app:///». Например:

webView.loadDataWithBaseURL("example-app://example.co.uk/", HTML_DATA,
    null, "UTF-8", null);

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

person Community    schedule 14.04.2016

чтобы избежать веб-просмотра ниже 4.4, преобразуйте обратную косую черту в прямую косую черту, я просто экранирую свой URL-адрес, затем в коде Java используйте URI.decode, чтобы получить реальный URL-адрес. Это работает для меня.

person Bruce    schedule 05.05.2015