2016-03-30 9 views
11

Ich habe ein WebView in meiner App, die eine Seite anzeigt, die mir nicht gehört. Mein gewünschtes Verhalten ist, dass, wenn ein Link vom Benutzer angeklickt wird, die Browser-App des Geräts gestartet wird und die resultierende Seite dort geladen wird. Leider macht diese Seite einige seltsame Dinge, so dass shouldOverrideUrlLoading() nicht feuert.Erfassen von Seitenumleitungen über JavaScript in Android WebView

Meine versuchte Lösung ist, ein paar Javascript in pushState zu haken und eine Schnittstelle zu verwenden, um Android-Code zum Starten der Browser-App auszuführen.

Hier ist meine Schnittstelle:

public class LaunchExternalBrowserHack { 
    Context mContext; 

    LaunchExternalBrowserHack(Context c) { 
     mContext = c; 
    } 

    @JavascriptInterface 
    public void launchExternalBrowser(String url) { 
     openUrl(url); 
    } 
} 

ich einige Javascript in die Seite in onPageFinished() Injektion:

public void onPageFinished(WebView view, String url) { 
    mWebView.loadUrl(javascript); 
} 

Hier ist mein javascript:

private final String javascript = "javascript:history.pushState = function (state, title, url) { console.log(url); console.log(location.href); Uphoria.launchExternalBrowser(location.origin, url); };"; 

Und, Natürlich füge ich die Schnittstelle zu WebView hinzu:

mWebView.addJavascriptInterface(new LaunchExternalBrowserHack(getContext()), "Android"); 

Das scheint also zu funktionieren. Die Browser-App wird gestartet und die nächste Seite wird geöffnet.

Aber auch das WebView geht voran. Ich möchte das verhindern, aber ich kann keine Möglichkeit finden, die Weiterleitung des WebView zu verhindern, während ich gleichzeitig die Weiterleitungs-URL erfassen und die Browser-App starten kann. Wie ich bereits erwähnt habe, ist shouldOverrideUrlLoading mit dieser Webseite nicht feuern.

Ideen?

+0

folgende Sie erwähnen kein Ergebnis in 'onReceiveValue (...)' bekommen. Können Sie sehen, ob das Ändern des Javascript in einen Funktionsaufruf funktionieren würde? Wie [diese Antwort] (http://stackoverflow.com/a/19790911/503508) schlägt vor. Insbesondere in diesem Stil: '(function() {return {var1: \" variable1 \ ", var2: \" variable2 \ "};})();' – Knossos

Antwort

1

Diese Antwort ist falsch. Hier gehalten, weil es wichtige relevante Kommentare hat.

Der Grund, dass Sie kein Ergebnis von Ihrem Javascript erhalten, ist, dass Sie eine Funktion nicht direkt aufrufen. Sie weisen Ihrem JavaScript eine Funktion zu, die einen Wert zurückgibt, aber den Code nicht an den Code zurückgibt, sondern an alle Aufrufe history.pushState().

private final String javascript = "javascript:" + "var pushState = history.pushState; history.pushState = function() " + 
     "{ pushState.apply(history, arguments); console.log(arguments); return location.href; " + 
     "};"; 

Stattdessen können Sie testen, ob so etwas wie dieses gibt Ihnen einen Wert:

private final String javascript = "(function() { return location.href; })();"; 
+0

Wird das nicht sofort zurückkommen? Ich möchte, dass der HF ausschaltet, wenn der Benutzer auf etwas tippt, mit dem er/sie weg navigiert. – Andrew

+0

Ja, es würde sofort zurückkehren. Ich denke nicht, dass Sie einen Callback in dem Stil ausführen können, an den Sie denken. Sie bewerten Javascript direkt über diese Funktion. Sie senden das JS sofort, es wird ausgewertet und ein Wert wird zurückgegeben (falls angegeben). In Ihrem Code bewerten Sie jedoch die Einstellung einer Funktion, und das ist es. Sie könnten "webView.addJavascriptInterface" verwenden. Hast du das untersucht? – Knossos

+0

Ja, aber meine Schnittstelle scheint nicht auf Android 4.4 + zu feuern. Es funktioniert gut vor 4.4. – Andrew

5

Der Benutzer versucht, von der Seite zu entfernen. um ihn davon abzuhalten, auszuziehen, kehren Sie falsch zurück. um ihn wegzuziehen, gib nichts zurück, aber du kannst jeden Code ausführen, den du willst. Dieses Ereignis wird sofort ausgelöst, wenn ein Navigationsereignis einschließlich Seitenaktualisierung auftritt.

private final String javascript = "window.onbeforeunload = function(){ dosomething(); }; window.unload = function(){ dosomething(); }; function dosomething() { /* Write code here */ };" 

Sie müssen den gesamten JavaScript-Code oben schließen, da einige Browser onbeforeunload und einige Verwendung verwenden unload

EDIT

Nach sorgfältiger Lektüre des Problems ich meine Lösung gefunden wenig hilfreich zu sein .

Hier ist ein anderer Ansatz mit history. Wenn Ihr Verlauf leer ist, bedeutet dies, dass es sich um die erste Seite handelt.Wenn Sie jedoch einige Elemente in der Historie haben, bedeutet dies, dass die Navigation stattgefunden hat.

Sie können es als

private final String javascript = "javascript:"+"if(window.history.length>=1 && document.referrer=='') Android.launchExternalBrowser(location.href);"; 
Verwandte Themen