WebViewリダイレクトの判断



Webview Redirection Judgment



序文

この種の要求が発生したかどうかはわかりません。WebViewを使用してWebページをロードし、Webページの上にあるリンクをクリックして別のページにジャンプするか、ブラウザを開きます。これは、WebViewがページの一部にすぎない場合に特に当てはまります。

遭遇問題

上記の要件は簡単に実装できます。



  • WebViewを使用してWebページをロードする
webView.loadUrl(url)
  • WebViewのリンクをクリックして、次のページにジャンプします
webView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { Uri uri = Uri.parse(url) Intent intent = new Intent(Intent.ACTION_VIEW, uri) try { view.getContext().startActivity(intent) } catch (ActivityNotFoundException e) { e.printStackTrace() } return true } })

しかし、これを行った後、問題が見つかります。 webViewが最初にロードするURLが別のアドレスにリダイレクトされる場合、shouldOverrideUrlLoadingのコールバックも取得されます。このように、WebViewが空であるという現象は、ブラウザを直接開きます。

問題を解く

この問題を解決するために、WebViewにリダイレクトを決定する方法があるかどうかを確認するための解決策を考えるのは簡単です。その場合、リダイレクトされたコールバックを個別に処理できます。
残念ながら、WebViewは対応するメソッドを提供していません。それに対処する方法はありませんか?もちろん違います。



解決策1

このプログラムはブロガーによって提供されています:

WebViewにはgetHitTestResult()があります。HitTestResultを返します。通常、開いているリンクのタイプに応じて追加情報を返します。オープンリンクがURLでない場合、またはオープンリンクがJavaScript URLの場合、そのタイプはUNKNOWN_TYPEです。このURLは、requestFocusNodeHref(Message)を介して非同期にリダイレクトされます。返されるエクストラはnullであるか、エクストラを返しません。このメソッドの戻り値に従って、nullかどうかが判断され、Webページのリダイレクトを解決するために使用できます。

詳細を見る 元のブロガー 、コードに編成されているのは次のとおりです。



webView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { / / Determine the way to redirect one WebView.HitTestResult hitTestResult = view.getHitTestResult() if(hitTestResult == null) { return false } if(hitTestResult.getType() == WebView.HitTestResult.UNKNOWN_TYPE) { return false } Uri uri = Uri.parse(url) Intent intent = new Intent(Intent.ACTION_VIEW, uri) try { view.getContext().startActivity(intent) } catch (ActivityNotFoundException e) { e.printStackTrace() } return true } })

このソリューションの欠点の1つは、発生した要件が序文で説明されているとおりである場合、2回目のクリックのリダイレクトされたリンクが別のページではなく、現在のWebViewで直接開かれることです。
この欠陥を回避するために、2番目のソリューションが作成されました。

解決策2

WebViewは、ページのロード時にonPageStartedメソッドをコールバックし、ページのロード後にonPageFinishedメソッドを呼び出します。また、リンクがリダイレクトされた場合、コールバックshouldOverrideUrlLoadingはコールバックonPageFinishedの前になります。
この前提で、mIsPageLoadingタグを追加し、onPageStartedコールバックでtrueに設定し、onPageFinishedコールバックでfalseに設定できます。フラグはshouldOverrideUrlLoadingで判断できます。 trueの場合、コールバックはリダイレクトされます。それ以外の場合、ブラウザは直接開かれます。コードは次のように表示されます。

private boolean mIsPageLoading / / Code omitted webView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { / / Determine the way to redirect two if(mIsPageLoading) { return false } if(url != null && url.startsWith('http')) { webView.loadUrl(url) return true } else { Uri uri = Uri.parse(url) Intent intent = new Intent(Intent.ACTION_VIEW, uri) try { view.getContext().startActivity(intent) } catch (ActivityNotFoundException e) { e.printStackTrace() } return true } } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon) mIsPageLoading= true Log.d(TAG, 'onPageStarted') } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url) mIsPageLoading= false Log.d(TAG, 'onPageFinished') } })

完璧な解決策はありません。プログラムには別の問題があります。ロードされたページの一部のリンクは、ページがすべてロードされる前にクリック可能です。このようにして、shouldOverrideUrlLoadingのリンクをクリックすると、現在のWebViewのリダイレクトリンクとしても開かれます。
これを回避するには、ページが完全に読み込まれるまでWebViewのクリックのみを無効にできます。

webView.setOnTouchListener(new WebViewTouchListener()) / / Code omitted private class WebViewTouchListener implements View.OnTouchListener { @Override public boolean onTouch(View v, MotionEvent event) { return !mIsLoading } }

結論

上記の両方の解決策でいくつかの問題を解決できますが、すべて欠陥があります。完璧な解決策はなく、需要を満たす計画だけが存在すると言えます。

川と湖のルール、ソースコードを参照 github