問題はかなり単純です。アプリケーションでは、表示されている現在の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は一般的なものであり、標準を満たす必要があるため、依然として意味をなしません。
これの代替案または解決策はありますか?
その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 。
mWebView.getSettings().setDomStorageEnabled(true);
を省略してください
その後、もう一度試してください。新しいURLが見つかったら、shouldOverrideUrl()
を呼び出します
私はあなたと同じ問題を抱えていました。そして、コールバックをリッスンする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
}
}
};
あなたが試すことができる別のアプローチ: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、またはページ内の他の何かを取得できます。
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;
}
}
}
これを試して...
webView.getSetting().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
を追加すると、shouldOverrideUrl
がトリガーされます。
私にとって、問題は以下の線でした-
mWebView.getSettings().setSupportMultipleWindows(true);
削除した後、shouldOverrideUrlLoadingが呼び出されていました。
この問題につまずいて解決策を探した後、私にとって完璧に機能するものを見つけました
https://stackoverflow.com/a/56395424/10506087
override fun doUpdateVisitedHistory(view: WebView?, url: String?, isReload: Boolean) {
// your code here
super.doUpdateVisitedHistory(view, url, isReload)
}
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);
}
});
上記の解決策も試しましたが、ほとんどの場合、私の場合は問題があります。
doUpdateVisitedHistory
XmlHttpRequestによって作成された「#」の後、正しいURLを返せない場合があります。doUpdateVisitedHistory
は http://example.com/myapp//myapp/ を返しますonReceivedTitle
は機能しません。XMLHttpRequestによって取得された応答には<title></title>
鬼ごっこ。