9 votes

WebViewClient n'appelle pas shouldOverrideUrlLoading

Le problème est assez simple. Dans l'application, nous voulons garder la trace de l'url actuelle affichée. Pour cela, nous utilisons shouldOverrideUrlLoading de l'appel de la WebViewClient en sauvegardant l'url dans un champ de classe pour chaque mise à jour. Voici le code correspondant :

    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);

Toutefois, il existe au moins un scénario dans lequel la fonction de rappel n'est jamais déclenchée et le champ mCurrentUrl n'est pas mis à jour.

L'url : https://m.pandora.net/es-es/products/bracelets/556000

Dernière url mise à jour (shouldOverrideUrlLoading n'est jamais appelé lorsque l'on clique sur le produit) : https://m.pandora.net/es-es/products/bracelets

J'ai essayé avec des callbacks comme onPageStarted(), mais l'url est aussi filtrée et il ne semble pas y avoir d'url accessible en amont puisque c'est du code protégé.

En lisant la documentation Android sur WebView, j'ai trouvé ceci :

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

Le nouveau WebView applique des restrictions supplémentaires lors de la demande de ressources et de la résolution de liens qui utilisent un schéma URL personnalisé. Par exemple, si vous implémentez des callbacks tels que shouldOverrideUrlLoading() ou shouldInterceptRequest(), le WebView ne les invoque que pour les URL valides.

Mais cela n'a toujours pas de sens puisque l'url ci-dessus est générique et devrait répondre à la norme.

Une alternative ou une solution à ce problème ?

14voto

Leo Nikkilä Points 1169

Lorsque vous cliquez sur un produit sur cette page Web, elle charge le nouveau contenu à l'aide de JavaScript et met à jour l'URL visible dans la barre d'adresse à l'aide de l'attribut API d'histoire HTML5 .

Extrait de l'article MDN ci-dessus :

La barre d'URL s'affichera alors http://mozilla.org/bar.html mais ne fera pas en sorte que le navigateur charge bar.html ou même vérifie que bar.html existe.

Ils sont parfois appelés applications monopages . Puisque la page chargée ne change pas, le rappel WebView pour le chargement des pages n'est pas appelé.

Dans le cas où vous savez précisément quel type de requête HTTP vous voulez intercepter, vous pouvez utiliser la fonction shouldInterceptRequest qui est appelé pour chaque demande. Il est probable que l'application web charge certaines données à partir d'une API, par exemple lors de l'affichage d'un produit, que vous pourriez ensuite détecter.

Si cette détection n'est pas possible, mais que vous avez le contrôle de l'application web, vous pouvez utiliser la commande Interface Android JavaScript pour invoquer des méthodes dans l'application Android directement à partir de la page web.

Si vous n'avez pas le contrôle de la page chargée, vous pouvez toujours essayer de injecter un fichier JavaScript local dans la page web et observer quand les API d'histoire sont utilisées puis appeler des méthodes dans votre application Android via l'interface JS. J'ai essayé d'observer ces événements dans Chrome avec la méthode décrite dans le lien précédent et cela semble fonctionner correctement.

5voto

Jijo Points 1

Veuillez omettre mWebView.getSettings().setDomStorageEnabled(true);

Ensuite, essayez à nouveau, si une nouvelle url est trouvée, alors nous invoquerons shouldOverrideUrl()

3voto

Michael Katkov Points 1832

J'ai eu le même problème que vous, et j'ai terminé l'extension de WebViewChromeClient en écoutant le callback à

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
            }
        }

    };

1voto

Ganesh Pokale Points 799
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;
    }
}
}

Essayez celui-là...

1voto

PMateus Points 150

Une autre approche que vous pouvez essayer : Attraper l'url par le côté javascript . Initialiser votre webView avec ceci :

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

Après le chargement complet de la page (vous pouvez utiliser un algorithme pour vérifier cela comme ceci https://stackoverflow.com/a/6199854/4198633 ), alors :

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);");
}

Et déclarez votre 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
            }
        });

    }

}

Vous pouvez faire quelque chose comme ça pour obtenir l'url, ou n'importe quoi d'autre à l'intérieur de la page.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X