2012-01-08 1 views
0

У меня есть WebView, в котором я хотел бы привязать теги с rel=external, чтобы открыть их в браузере Android, но все остальные ссылки, чтобы остаться в WebView.WebView ceding rel = внешние ссылки на Activity Manager

Таким образом, содержание будет загружаться в WebView, если пользователь вводит ссылку, разметка выглядит следующим образом:

<a href="http://example.com/">Whatever</a> 

Но содержание будет загружаться в Android браузер, если пользователь нажимает на ссылку, разметка выглядит это:

<a href="http://example.com/" rel="external">Whatever</a> 

Вот мой соответствующий код (с одним битым псевдокодом идентифицированного с комментарием) в WebViewClient коде:

@Override 
public boolean shouldOverrideUrlLoading(WebView view, String url) { 
    if (! rel=external) { // <-- That condition...how do I do that? 
     view.loadUrl(url); 
     return false; 
    } else { 
     Intent intent = new Intent(Intent.ACTION_VIEW); 
     intent.setData(Uri.parse(url)); 
     startActivity(intent); 
     return true; 
    } 

Был бы лучший способ определить, есть ли атрибут/значение rel=external, чтобы каким-то образом использовать addJavascriptInterface() и сообщить JavaScript Java, есть ли атрибут rel и каково его значение?

Или есть лучший способ?

(Я ищу решение, которое не включает проверку домена URL-адреса, поскольку существует произвольное количество доменов, которые должны рассматриваться как внутренние и которые я не могу знать заранее или легко определить, fly.)

ответ

2

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

Используйте addJavaScriptInterface, чтобы добавить класс для загрузки внешнего URL-адреса. Внутренний класс может выглядеть следующим образом:

public class JavaScriptInterface { 
    public void viewExternalUrl(String url) { 
     Intent intent = new Intent(Intent.ACTION_VIEW); 
     intent.setData(Uri.parse(url)); 
     startActivity(intent); 
     return true; 
    } 
} 

И, конечно же, добавив его:

webView.addJavascriptInterface(new JavaScriptInterface(), "Android"); 

Вводит JavaScript, чтобы добавить обработчик щелчка для вызова интерфейса JavaScript после загрузки страницы (с помощью JQuery для простоты) до loadUrl. Вы можете обнаружить завершение загрузки страницы, создав пользовательский WebViewClient и переопределяя onPageFinished.

webView.setWebViewClient(new WebViewClient() { 
    private static final String sJs = "javascript:" + 
     Uri.encode("$('a[@rel$='external']').click(function(){ Android.viewExternalUrl($(this).attr('href')); });"); 

    @Override 
    public void onPageFinished(WebView view, String url) { 
     webView.loadUrl(sJs); 
    } 
} 

Я не проверял любой из этого кода, но он должен работать, если вы JQuery загружены на странице. Если нет, вы можете, возможно, придумать какой-нибудь JavaScript для управления DOM без него, или вы можете использовать loadUrl для ручной загрузки JQuery сначала перед загрузкой JavaScript.

Обратите внимание, что этот подход полностью отказывается от любого использования shouldOverrideUrlLoading

+0

Это выглядит очень многообещающим. Не понял, что это будет означать, что я не смогу использовать 'shouldOverrideUrlLoading()', но для меня это совсем не проблема. – Trott

+0

Ну, вы все равно можете использовать 'shouldOverrideUrlLoading()' для других вещей, если хотите. Фактически, вы, вероятно, могли бы изменить его, чтобы вы сигнализировали интерфейс JavaScript из JavaScript, который вводит через 'loadUrl', чтобы сообщить вашему Java-коду, какой URL-адрес является внешним, сохранить его в какой-то таблице и затем выполнить поиск, когда' shouldOverrideUrlLoading' , но я нахожу, что излишне сложно и, возможно, подвержено ошибкам (что, если у вас есть две ссылки на один и тот же URL-адрес, но только один ref = внешний? Не могу понять, почему это произойдет, но если бы это произошло, ломать). – kabuko

1

Мое предложение состоит в том, чтобы использовать другой способ обозначения внешних URL-адресов ... тот, который вставляет эту информацию в URL-адрес и, следовательно, совместим с функцией shouldOverrideUrlLoading. В частности, создавать собственные схемы URL-адреса и передать реальную страницу в качестве параметра:

myappname: // внешнего URL = encoded_real_page_url

Тогда в чеке shouldOverrideUrlLoading функции, если это пользовательский схема URL, извлечь URL-адрес из параметров, расшифровать его, а затем перенаправить.

+0

В том, что я смотровой в WebView страниц должно быть доступно для просмотра с помощью стандартных браузеров тоже, так что я должен буду работать вокруг этого вопроса, если я пойдите по этому маршруту. Возможно, я смогу, чтобы приложение загрузило JavaScript на каждую страницу в качестве загружаемого файла, который будет переписывать URL-адреса с помощью специальной схемы. Если нет, то, возможно, я могу попытаться разобраться с ним на стороне сервера (например, обнюхать пользовательский агент для моего приложения и соответственно отобразить URL-адреса). Я бы предпочел, но это должно сработать. +1 – Trott

+0

Чтобы выяснить, находится ли HTML в веб-просмотре вашего приложения, вы можете добавить специальный интерфейс JS-маркера в веб-просмотр (с помощью функции bool для вызова, если вы лишний параноик относительно возможных ложных срабатываний) и реализовать проверку для что в JavaScript. Затем, если маркер присутствует, вы можете изменить все URL-адреса через JavaScript при загрузке. Или у каждой ссылки есть javascript :: link_fn (pageUrl) и используйте link_fn, чтобы проверить интерфейс маркера, а затем определить, как собрать URL. – Theo

1

Если у вас есть контроль над содержимым на стороне сервера, то обязательно соглашайтесь с предложением Тео. Поскольку вы указываете, что страницы также должны загружаться в стандартные браузеры, не используйте пользовательскую схему, но сделайте rel=external частью фактического URL-адреса, на который вы ссылаетесь/перенаправляетесь.

Делая это, вы можете легко проанализировать параметр url в shouldOverrideUrlLoading(WebView view, String url) и проверить выше пара ключ/значение. Я предлагаю вам разобрать его на Uri и использовать getQueryParameter(key), чтобы проверить соответствие rel. Если это external, сработайте намерение.

Это будет выглядеть примерно так:

@Override 
public boolean shouldOverrideUrlLoading(WebView view, String url) { 
    Uri uri = Uri.parse(url); 
    String relValue = uri.getQueryParameter("rel");  
    if (relValue != null && !relValue.equals("external")) { 
     view.loadUrl(url); 
     return false; 
    } 
    Intent intent = new Intent(Intent.ACTION_VIEW); 
    intent.setData(uri); 
    startActivity(intent); 
    return true; 
} 

На стороне записки: не нужно объявлять «еще», так как вы уже вернуться из метода в «если».

Если пользователи могут перейти на любой сайт с помощью вашего WebView, и если вы параноик относительно других сайтов, применяющих одну и ту же пару ключ/значение для своих целей, вы можете легко добавить еще одну проверку, чтобы определить, включен ли URL-адрес 'your' домен.

+0

Спасибо за ответ и образец кода (и боковое примечание, которое я ценю!). Что касается проверки предложения домена в конце, пожалуйста, обратите внимание на последний параграф вопроса: (Я ищу решение, которое не включает проверку домена URL-адреса, поскольку существует произвольное количество доменов, которые необходимо обработать как внутренний, и что я не могу заранее знать или легко определить на лету.) – Trott

Смежные вопросы