2016-10-11 3 views
9

Проблема довольно проста. В приложении мы хотим отслеживать отображение текущего URL-адреса. Для этого мы используем обратный вызов shouldOverrideUrlLoading из WebViewClient, сохраняя URL-адрес в поле класса для каждого обновления. Вот соответствующий код:WebViewClient не вызывает shouldOverrideUrlLoading

mWebView.getSettings().setJavaScriptEnabled(true); 
    mWebView.getSettings().setDomStorageEnabled(true); 
    mWebView.setWebViewClient(new WebViewClient() { 
     @Override 
     public boolean shouldOverrideUrlLoading(WebView view, String url) { 
      mCurrentUrl = url; 

      // If we don't return false then any redirect (like redirecting to the mobile 
      // version of the page) or any link click will open the web browser (like an 
      // implicit intent). 
      return false; 
     } 



     @Override 
     public void onPageFinished(WebView view, String url) { 
      super.onPageFinished(view, url); 
      ... 
     } 
    }); 
    mWebView.loadUrl(mInitialUrl); 

Однако, есть по крайней мере один сценарий, при котором обратный вызов не сработал и поле mCurrentUrl оленья кожа обновляется.

URL-адрес: https://m.pandora.net/es-es/products/bracelets/556000

Последнее обновление URL (shouldOverrideUrlLoading никогда не вызывается при нажатии на продукт): https://m.pandora.net/es-es/products/bracelets

Я попытался с обратными вызовами, как onPageStarted(), но URL также фильтруется и там Безразлично Кажется, что он является доступным вверх по течению после его защищенного кода.

Чтение андроида документации о WebView я нашел это:

https://developer.android.com/guide/webapps/migrating.html#URLs

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

Но все еще не имеет смысла, поскольку вышеуказанный URL-адрес является общим и должен соответствовать стандарту.

Любая альтернатива или решение этой проблемы?

+0

ничего особенного в URL, как это запрос с использованием 'Post' метод? – Swordsman

+0

Вы пытались переопределить метод onReceivedError в своем пользовательском WebViewClient? Возможно, вы можете проверить параметры запроса и ошибки из этого обратного вызова, чтобы узнать, что происходит. Кроме того, попробуйте ввести этот URL-адрес в браузер своего устройства, чтобы убедиться, что что-то не так с фактической загрузкой веб-страницы. – w3bshark

+0

Эта страница работает нормально, и ошибки не получено. Я думаю, что ответ лежит в API истории HTML5, который может изменить URL-адрес, отображаемый в браузере, без фактического запуска запроса (поскольку контент работает в рамке сценария) – SuppressWarnings

ответ

7

При нажатии продукта на этой веб-странице он загружает новое содержимое с помощью JavaScript и обновляет видимый URL-адрес в адресной строке, используя HTML5 History APIs.

Из приведенных выше статей MDN:

Это заставит бар URL для отображения http://mozilla.org/bar.html, но не будет вызывать браузер для загрузки bar.html или даже проверить, что bar.html существует.

Их иногда называют single-page applications. Поскольку фактическая загруженная страница не изменяется, обратный вызов WebView для загрузки страниц не вызывается.

Если вы точно знаете, какой HTTP-запрос вы хотите перехватить, вы можете использовать обратный вызов shouldInterceptRequest, который вызывается для каждого запроса. Вероятно, веб-приложение загружает некоторые данные из API, например, когда отображается продукт, который вы могли бы обнаружить.

Если обнаружить это невозможно, но вы контролируете веб-приложение, вы можете использовать Android JavaScript interface для вызова методов в приложении Android непосредственно с веб-страницы.

Если вы не контролируете загруженную страницу, вы можете попытаться установить inject a local JavaScript file на веб-страницу и observe when the history APIs are used, а затем вызвать методы в приложении Android через интерфейс JS. Я пробовал наблюдать за этими событиями в Chrome с помощью метода, описанного в предыдущей ссылке, и, похоже, он работает нормально.

3

Пожалуйста опускаем mWebView.getSettings().setDomStorageEnabled(true);

Затем попробуйте еще раз, если новый URL найден, то будет вызывать shouldOverrideUrl()

1
public class AndroidMobileAppSampleActivity extends Activity { 
/** Called when the activity is first created. */ 
String mCurrentUrl=""; 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    WebView mWebView = (WebView) findViewById(R.id.mainWebView); 

    WebSettings webSettings = mWebView.getSettings(); 
    webSettings.setJavaScriptEnabled(true); 

    mWebView.setWebViewClient(new MyCustomWebViewClient()); 
    mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); 

    mWebView.loadUrl("https://m.pandora.net/es-es/products/bracelets/556000"); 

} 

private class MyCustomWebViewClient extends WebViewClient { 
    @Override 
    public boolean shouldOverrideUrlLoading(WebView view, String url) { 
     mCurrentUrl = url; 
     Log.i("mCurrentUrl",""+mCurrentUrl); 
     view.loadUrl(url); 

     return true; 
    } 
} 
} 

попробовать это ...

1

Другой подход, вы можете попробовать: поймать url со стороны javascript. Инициализировать ваш WebView с этим:

webView.addJavascriptInterface(new WebAppInterface(getActivity()), "Android"); 

После страница полностью загружена (Вы можете использовать алгоритм, чтобы проверить это, как этот https://stackoverflow.com/a/6199854/4198633), то:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 
    webView.evaluateJavascript("(function() {return window.location.href;})", new ValueCallback<String>() { 
     @Override 
     public void onReceiveValue(String url) { 
      //do your scheme with variable "url" 
     } 
    }); 
} else { 
    webView.loadUrl("javascript:Android.getURL(window.location.href);"); 
} 

И объявить WebAppInterface:

public class WebAppInterface { 
    Activity mContext; 

    public WebAppInterface(Activity c) { 
     mContext = c; 
    } 

    @JavascriptInterface 
    public void getURL(final String url) { 
     mContext.runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       //do your scheme with variable "url" in UIThread side. Over here you can call any method inside your activity/fragment 
      } 
     }); 

    } 

} 

Вы можете сделать что-то подобное, чтобы получить URL-адрес или что-то еще внутри страницы.

2

У меня была такая же проблема, как вы, и я закончил с продлением из WebViewChromeClient с прослушивания для обратного вызова для

public void onReceivedTitle(WebView view, String title) 

mWebView.setWebChromeClient(mSWWebChromeClient); 

private WebChromeClient mSWWebChromeClient = new WebChromeClient() { 

     @Override 
     public void onReceivedTitle(WebView view, String title) { 
      super.onReceivedTitle(view, title); 
      if (!view.getUrl().equals(mCurrentUrl)) { 
       mCurrentUrl = view.getUrl(); 
       //make something 
      } 
     } 

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