14

我正在尝试使用 Android (sdk 2.3.3) 开发一个custom browserWebView不幸API level 10的是我不知道如何拦截来自webpage在新浏览器窗口中打开 URL 的请求,例如点击带有target="_blank".

根据API DocI 已覆盖onCreateWindowof WebChromeClient,但在点击此类链接时不会调用。可能是这个 API 级别的错误?我还重写shouldOverrideUrlLoading以避免WebView在内置浏览器中打开后续链接。

这是我打开的示例代码google.com。要对其进行测试,请点击“新闻”,然后点击任何新闻标题。Android 内置浏览器通常以新的browser window.

package com.myexample;

import android.app.Activity;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

public class HelloAndroidActivity extends Activity {

  private static String TAG = "WebViewTest";
  private WebView mWebView;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.i(TAG, "onCreate");
    setContentView(R.layout.main);

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

    mWebView.setWebViewClient(new WebViewClient() {
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;
      }
    });

    mWebView.setWebChromeClient(new WebChromeClient() {
      @Override
      public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture, Message resultMsg) {
        Toast.makeText(getApplicationContext(), "OnCreateWindow", Toast.LENGTH_LONG).show();
        return true;
      }
    });
    mWebView.loadUrl("http://www.google.com");
  }

}

4

4 回答 4

28

确保将 supportMultipeWindows 设置为 true。没有它,WebChromeClient 的 onCreateWindow 将永远不会被调用。

WebSettings settings = webView.getSettings();
settings.setSupportMultipleWindows(true);

然后注册一个 WebChromeClient 并覆盖 onCreateWindow

 webView.setWebChromeClient(new WebChromeClient() {
        @Override public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture, Message resultMsg)
        {
            WebView newWebView = new WebView(getContext());
            addView(newWebView);
            WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
            transport.setWebView(newWebView);
            resultMsg.sendToTarget();
            return true;
        }
    });
于 2012-07-01T09:10:03.787 回答
8

除了注入 javascript 代码之外,找不到任何解决方案。我什至尝试编译从谷歌源代码库下载的内置 android 浏览器代码,但由于我发现它使用了一些非公共 API,所以无法编译。Dolphin 浏览器也使用自己的扩展 WebView,所以我没有找到他们如何实现打开新窗口请求检测的运气。

此 javascript 代码获取加载页面上的所有链接标签,并分析是否有 target="_blank" 的属性。对于这些链接中的每一个,都会在 href 属性的 url 值前面添加“newtab:”。然后在 shouldOverrideUrlLoading() 方法中检查 url 是否以“newtab:”字符串开头,在这种情况下我打开一个新选项卡。

以下是代码片段:

    mWebView.setWebViewClient(new WebViewClient() {

        @Override
        public void onPageFinished(WebView view, String url) {
            // Find all <a> with target="_blank" and append "newtab:" at the beginning. 
            // Make sure a null is at the end to avoid displaying a blank page
            view.loadUrl("javascript: var allLinks = document.getElementsByTagName('a'); if (allLinks) {var i;for (i=0; i<allLinks.length; i++) {var link = allLinks[i];var target = link.getAttribute('target'); if (target && target == '_blank') {link.setAttribute('target','_self');link.href = 'newtab:'+link.href;}}} null");
        }



        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String urls) {
            if (urls.startsWith("newtab:")) {
                addTab(); //add a new tab or window
                loadNewURL(urls.substring(7)); //strip "newtab:" and load url in the webview of the newly created tab or window
            }
            else {
                view.loadUrl(urls); //load url in current WebView
            }
            return true;
        }
    }

于 2012-01-25T12:02:38.510 回答
6

你需要看看这个:

webView.getSettings().setSupportMultipleWindows(true);

然后onCreateWindow会被调用。

于 2012-02-01T07:19:56.753 回答
0

从 WebChromeClient 覆盖 onCreateWindow 的所有答案对我都不起作用。有时它会在浏览器中打开图像,而不是像预期的那样打开 url。

唯一完全有效的解决方案是@Lotzy 结合@Vaughn Armada 添加的答案(将 null 添加到 javascript 片段的末尾)。使用此代码,所有带有 target="_blank" 的链接都将在新的浏览器窗口中打开,如果没有该目标,它们将在同一个 WebView 中打开。

webView.webViewClient = object : WebViewClient() {
    override fun onPageFinished(view: WebView, url: String) {
        // Check all <a>'s with target="_blank" so that it opens in browsers when it's supposed to.
        // Make sure a null is at the end to avoid displaying a blank page
        view.loadUrl("javascript: var allLinks = document.getElementsByTagName('a'); if (allLinks) {var i;for (i=0; i<allLinks.length; i++) {var link = allLinks[i];var target = link.getAttribute('target'); if (target && target == '_blank') {link.setAttribute('target','_self');link.href = 'newtab:'+link.href;}}} null");
    }

    override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
        if (url.startsWith("newtab:")) {
            // Open browser with the url, removing the added "newtab:"
            view.context.startActivity(Intent(Intent.ACTION_VIEW).setData(Uri.parse(url.removePrefix("newtab:"))))
        } else {
            // Load inside webview
            view.loadUrl(url)
        }
        return true
    }
}
于 2021-06-22T19:56:47.133 回答