web-dev-qa-db-ja.com

WebViewClientはshouldOverrideUrlLoadingを呼び出していません

問題はかなり単純です。アプリケーションでは、表示されている現在のURLを追跡します。そのために、shouldOverrideUrlLoadingからのWebViewClientコールバックを使用して、更新ごとにURLをクラスフィールドに保存します。関連するコードは次のとおりです。

    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フィールドが更新されないシナリオが少なくとも1つあります。

URL: https://m.Pandora.net/es-es/products/bracelets/5560

最後に更新されたURL(製品をクリックしてもshouldOverrideUrlLoadingは呼び出されません): https://m.Pandora.net/es-es/products/bracelets

OnPageStarted()のようなコールバックを試しましたが、URLもフィルターされ、保護されたコードなので上流にアクセスできるものがないようです。

Android WebViewのドキュメントを読んで、これを見つけました:

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

新しいWebViewは、リソースを要求し、カスタムURLスキームを使用するリンクを解決するときに追加の制限を適用します。たとえば、shouldOverrideUrlLoading()やshouldInterceptRequest()などのコールバックを実装する場合、WebViewは有効なURLに対してのみそれらを呼び出します。

ただし、上記のURLは一般的なものであり、標準を満たす必要があるため、依然として意味をなしません。

これの代替案または解決策はありますか?

14

そのWebページで製品をクリックすると、JavaScriptで新しいコンテンツが読み込まれ、 HTML5 History APIs を使用してアドレスバーの表示URLが更新されます。

上記のMDN記事から:

これにより、URLバーに http://mozilla.org/bar.html が表示されますが、ブラウザがbar.htmlをロードしたり、bar.htmlが存在することを確認したりすることはありません。

これらは、 シングルページアプリケーション と呼ばれることもあります。実際に読み込まれたページは変更されないため、ページを読み込むためのWebViewコールバックは呼び出されません。

インターセプトするHTTPリクエストの種類を正確に知っている場合は、各リクエストに対して呼び出されるshouldInterceptRequestコールバックを使用できます。たとえば、製品が表示されたときに、WebアプリケーションがAPIからいくつかのデータを読み込んで、それを検出できる可能性があります。

これを検出できないが、Webアプリケーションを制御している場合は、 Android JavaScriptインターフェイス を使用してAndroidアプリケーション内のメソッドを直接呼び出すことができますWebページから。

ロードされたページを制御していない場合でも、Webページに ローカルJavaScriptファイルを挿入 および 履歴APIが使用されるタイミングを確認 を試みることができます。 Android JSインターフェースを介してアプリケーションでメソッドを呼び出します。前のリンクで説明したメソッドを使用して、これらのイベントをChrome 。

20
Leo Nikkilä

mWebView.getSettings().setDomStorageEnabled(true);を省略してください

その後、もう一度試してください。新しいURLが見つかったら、shouldOverrideUrl()を呼び出します

6
Jijo

私はあなたと同じ問題を抱えていました。そして、コールバックをリッスンする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
            }
        }

    }; 
5
Michael Katkov

あなたが試すことができる別のアプローチ:javascript sideでURLをキャッチします。これでwebViewを初期化します。

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

ページが完全に読み込まれた後(アルゴリズムを使用してこれを確認できます https://stackoverflow.com/a/6199854/41986 )、その後:

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
PMateus
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
Ganesh Pokale

webView.getSetting().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);を追加すると、shouldOverrideUrlがトリガーされます。

1

私にとって、問題は以下の線でした-

mWebView.getSettings().setSupportMultipleWindows(true);

削除した後、shouldOverrideUrlLoadingが呼び出されていました。

1

この問題につまずいて解決策を探した後、私にとって完璧に機能するものを見つけました

https://stackoverflow.com/a/56395424/10506087

 override fun doUpdateVisitedHistory(view: WebView?, url: String?, isReload: Boolean) {
    // your code here
    super.doUpdateVisitedHistory(view, url, isReload)
}
0
Christian K

onProgressChangedは、リロード、userclickまたはXmlHttpRequestでの新しいページのロード時に常にトリガーされます。以前のロードと現在のロードのURLを比較すると、それがリロードまたは新しいページをロードしていることがわかります。これは、単一ページのWebアプリで完璧に機能します。

最初に最後のURLを格納するグローバル変数を宣言します。

String strLastUrl = null;

次に、onProgressChanged(WebViewビュー、int progress)をオーバーライドします

mWebView.setWebChromeClient(new MyWebChromeClient(){

   @Override
   public void onProgressChanged(WebView view, int progress) {
            if (progress == 100) {
                //A fully loaded url will come here
                String StrNewUrl = view.getUrl();
                if(TextUtils.equals(StrNewUrl,strLastUrl)){
                   //same page was reloaded, not doing anything
                }else{
                   //a new page was loaded,write this new url to variable
                   strLastUrl = StrNewUrl;
                   //do your work here
                   Log.d("TAG", "A new page or xhr loaded, the new url is : " + strLastUrl);
                }
            }
            super.onProgressChanged(view, progress);
        }
});

上記の解決策も試しましたが、ほとんどの場合、私の場合は問題があります。

  1. doUpdateVisitedHistoryXmlHttpRequestによって作成された「#」の後、正しいURLを返せない場合があります。
  2. 私の場合、onReceivedTitleは機能しません。XMLHttpRequestによって取得された応答には<title></title> 鬼ごっこ。
  3. JavascriptInterfaceメソッドも機能しますが、javascriptでセキュリティ関連の問題が発生することを恐れています。
0
Lynch Chen