WebView ceding rel= внешние ссылки на Activity Manager
У меня есть WebView
где я хотел бы привязать теги с rel=external
открыть в браузере Android, но все остальные ссылки, чтобы остаться в WebView
,
Таким образом, контент будет загружен в пределах 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-адреса, поскольку существует произвольное количество доменов, которые необходимо рассматривать как внутренние, и которые я не могу знать заранее или легко определить на лету.)
3 ответа
Я думаю, что вариант вашего исходного предложения, вероятно, лучше, если вы не хотите изменять существующий 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
Если у вас есть контроль над содержимым на стороне сервера, то, безусловно, согласитесь с предложением Тео. Поскольку вы указываете, что страницы должны также загружаться в стандартных браузерах, не используйте пользовательскую схему, но сделайте 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;
}
На заметку: нет необходимости объявлять 'else', так как вы уже вернулись из метода в 'if'.
Если пользователи могут перейти на любой сайт, используя ваш WebView, и если вы не уверены, что другие сайты используют ту же пару ключ / значение для своих целей, вы можете легко добавить еще одну проверку, чтобы определить, находится ли URL-адрес в "вашем" домене.
Я предлагаю использовать другой способ обозначения внешних URL-адресов... тот, который встраивает эту информацию в URL-адрес и, следовательно, совместим с shouldOverrideUrlLoading
функция. В частности, создайте собственные URL-адреса схемы и передайте реальную страницу в качестве параметра:
myappname: // внешний URL = encoded_real_page_url
Тогда в shouldOverrideUrlLoading
Функция проверяет, является ли URL-адрес пользовательской схемы, извлекает параметр url, декодирует его и затем перенаправляет.