WebView ceding rel = внешние ссылки на Activity Manager - PullRequest
0 голосов
/ 09 января 2012

У меня есть 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 ]

2 голосов
/ 20 января 2012

Я думаю, что вариант вашего исходного предложения, вероятно, будет лучше, если вы не хотите изменять существующий 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

1 голос
/ 14 января 2012

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

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

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

@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 в «вашем» домене.

1 голос
/ 09 января 2012

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

myappname: // внешний URL = encoded_real_page_url

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

...