2011-12-20 37 views
10

Tôi đang cố gắng để phát triển một custom browser với WebView sử dụng Android API level 10 (sdk 2.3.3), tiếc là tôi không biết làm thế nào để ngăn chặn yêu cầu từ webpage để mở URL trong cửa sổ trình duyệt mới, như nhấn vào liên kết với target="_blank".WebView + Phương pháp WebChromeClient onCreateWindow không kêu gọi target = "_ blank"

Phù hợp với API Doc Tôi đã ghi đè số onCreateWindow của WebChromeClient, nhưng không được gọi khi liên kết đó được khai thác. Có thể là lỗi của cấp API này? Tôi cũng ghi đè shouldOverrideUrlLoading để tránh WebView mở các liên kết tiếp theo trong trình duyệt tích hợp sẵn.

Đây là mã mẫu của tôi mở ra google.com. Để kiểm tra, nhấn "Tin tức" và sau đó nhấn vào bất kỳ tiêu đề tin tức nào. Trình duyệt tích hợp Android thường mở nó trong một browser window mới.

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

} 

+0

Lotzy, onCreateWindow sẽ được gọi chỉ khi bạn trở thành sự thật từ shouldOverrideUrlLoading. Dường như là một lỗi xem web, bởi vì trong hầu hết các trường hợp, bạn không thể trả về false từ shouldOverride ... – myself

+0

Vâng, như bạn có thể thấy có sự trở lại đúng; trong phương thức shouldOverrideUrlLoading. – Lotzy

Trả lời

5

Không tìm thấy giải pháp nào khác ngoài việc tiêm mã javascript. Tôi thậm chí còn cố gắng biên dịch mã trình duyệt Android tích hợp được tải xuống từ kho lưu trữ nguồn google nhưng sẽ không biên dịch như tôi đã phát hiện ra rằng sử dụng một số API không công khai. Trình duyệt Dolphin cũng sử dụng WebView mở rộng của riêng nó vì vậy tôi không có may mắn tìm ra cách chúng triển khai phát hiện yêu cầu cửa sổ mới mở.

Mã javascript này nhận tất cả các thẻ liên kết trên trang được tải và phân tích xem có thuộc tính nào có target = "_ blank" hay không. Đối với mỗi liên kết này sẽ thêm "newtab:" ở phía trước giá trị url của thuộc tính href. Sau đó, trong phương thức shouldOverrideUrlLoading() tôi kiểm tra xem url có bắt đầu bằng chuỗi "newtab:" hay không, trong trường hợp này tôi mở một tab mới.

Sau đây là các snipets mã:

mWebView.setWebViewClient(new WebViewClient() {

@Override 
    public void onPageFinished(WebView view, String url) { 
     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;}}}"); 
    } 



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

+1

Đã không kiểm tra nhiều, nhưng hoạt động rất tốt cho đến nay :) Cảm ơn rất nhiều! – myself

6

Bạn cần phải có một cái nhìn lúc này:

webView.getSettings().setSupportMultipleWindows(true); 

Sau đó onCreateWindow sẽ được gọi.

+0

Các bạn, bạn có chắc bạn đã thử mã của tôi với API cấp 10 (sdk 2.3.3) không? – Lotzy

+0

Câu trả lời này rất hữu ích cho tôi :-) –

23

Đảm bảo bạn đã đặt supportMultipeWindows thành true. Nếu không có nó thì onCreateWindow của WebChromeClient sẽ không bao giờ được gọi.

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

Sau đó đăng ký một WebChromeClient và ghi đè 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; 
     } 
    }); 
+0

làm việc tuyệt vời cho tôi :) – Akshat

+0

Đối với tôi nó không hoạt động, rằng Bánh mì nướng từ phương thức onCreateWindow() không được hiển thị. Tôi cũng đặt một điểm ngắt trong dòng đó và khởi chạy ứng dụng bằng trình gỡ rối nhưng việc thực hiện không dừng lại ở dòng đó. – Lotzy

+0

Tuyệt vời, cuối cùng làm việc với điều này! Jsut một câu hỏi, tại sao "addView (newWebView)"? Tôi không nhận được dòng này. Và tôi cũng không sử dụng nó. Bạn có thể giải thích điểm của dòng này? thx – Seynorth

Các vấn đề liên quan