2011-12-20 10 views
10

Staram się wypracować custom browser z WebView używając Android API level 10 (SDK 2.3.3), niestety nie wiem jak przechwycić żądania od webpage do otwarty adres URL w nowym oknie przeglądarki, np. dotknięcie łączy z target="_blank".WebView + metoda WebChromeClient onCreateWindow nie wezwał do target = „_ blank”

Zgodnie z API Doc nadpisałem onCreateWindow z WebChromeClient, ale nie jest wywoływane, gdy takie łącze jest dotknięte. Czy może to być błąd tego poziomu interfejsu API? Nadpisuję też numer shouldOverrideUrlLoading, aby uniknąć kolejnych połączeń z wbudowaną przeglądarką.

Oto mój przykładowy kod, który otwiera się google.com. Aby przetestować, dotknij "Wiadomości", a następnie dotknij dowolnego tytułu wiadomości. Wbudowana przeglądarka systemu Android zwykle otwiera ją w nowej wersji 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"); 
    } 

} 

+0

Lotzy, onCreateWindow zostanie sprawdzony tylko jeśli zwróci true z shouldOverrideUrlLoading. Wygląda na błąd w przeglądarce internetowej, ponieważ w większości przypadków nie można zwrócić wartości false z shouldOverride ... – myself

+0

Cóż, jak widać, jest prawdziwy zwrot; w metodzie shouldOverrideUrlLoading. – Lotzy

Odpowiedz

5

Nie można znaleźć żadnego innego niż wstrzykiwanie kodu javascript rozwiązanie. Próbowałem nawet skompilować wbudowany kod przeglądarki Android pobrany z repozytorium źródeł google, ale nie skompiluję, ponieważ odkryłem, że używa jakiegoś niepublicznego API. Przeglądarka Dolphin korzysta również z własnego, rozszerzonego WebView, więc nie miałem szczęścia dowiedzieć się, w jaki sposób implementują nowe wykrywanie żądań otwartych okien.

Ten kod javascript pobiera wszystkie znaczniki odnośników na wczytanej stronie i analizuje, czy istnieje atrybut z target = "_ blank". Dla każdego z tych linków doda "newtab:" przed wartością url atrybutu href. Następnie w metodzie shouldOverrideUrlLoading() sprawdzam, czy URL zaczyna się ciągiem "newtab:", w którym to przypadku otwieram nową kartę.

Oto snipets kod:

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

Nie testowałem jeszcze wiele, ale jak na razie działa bardzo dobrze :) Wielkie dzięki! – myself

6

Trzeba spojrzeć na to:

webView.getSettings().setSupportMultipleWindows(true); 

Następnie onCreateWindow zostanie sprawdzony.

+0

Chłopaki, czy jesteś pewien, że wypróbowałeś mój kod z API 10 poziomem (sdk 2.3.3)? – Lotzy

+0

Ta odpowiedź była mi pomocna :-) –

23

Upewnij się, że parametr supportMultipeWindows jest ustawiony na true. Bez tego onCreateWindow z WebChromeClient nigdy nie zostanie wywołany.

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

Następnie zarejestrować WebChromeClient i zastąpić 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

fajnie mi pomogło :) – Akshat

+0

Dla mnie to nie działa, to Toast od metody onCreateWindow() nie jest pokazywany. Wprowadziłem również punkt przerwania w tej linii i uruchomiłem aplikację z debuggerem, ale wykonanie nie zatrzymuje się w tej linii. – Lotzy

+0

Awesome, wreszcie działa z tym! Jsut pytanie, dlaczego "addView (newWebView)"? Nie rozumiem tej linii. I też tego nie używam. Czy mógłbyś wyjaśnić punkt tej linii? thx – Seynorth

Powiązane problemy