2016-03-30 20 views
11

Ho una visualizzazione Web nella mia app che visualizza una pagina che non mi appartiene. Il mio comportamento desiderato è che, se un utente tocca un collegamento, viene avviata l'app Browser del dispositivo e lì viene caricata la pagina risultante. Sfortunatamente, questa pagina sta facendo alcune cose strane, quindi shouldOverrideUrlLoading() non si attiva.Cattura reindirizzamenti di pagine tramite javascript nella WebView di Android

La mia tentata soluzione è di agganciare alcuni javascript in pushState e utilizzare un'interfaccia per eseguire il codice Android per avviare l'app browser.

Ecco la mia interfaccia:

public class LaunchExternalBrowserHack { 
    Context mContext; 

    LaunchExternalBrowserHack(Context c) { 
     mContext = c; 
    } 

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

sto iniettando un javascript nella pagina in onPageFinished():

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

Ecco il mio javascript:

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

E, Ovviamente, aggiungo l'interfaccia allo WebView:

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

Quindi questo sembra funzionare. L'app Browser sta per essere avviata e la pagina successiva si sta aprendo.

Tuttavia, anche la visualizzazione Web si sta spostando in avanti. Voglio evitare questo, ma non riesco a trovare un modo per impedire che il WebView si muova mentre mi consente comunque di catturare l'url di inoltro e avviare l'app Browser. Come accennato in precedenza, con questa pagina Web, shouldOverrideUrlLoading è non.

Idee?

+0

Non parlare di ottenere un risultato in 'onReceiveValue (...)'. Riesci a vedere se la modifica del javascript in una chiamata di funzione potrebbe funzionare? Come [questa risposta] (http://stackoverflow.com/a/19790911/503508) suggerisce. Nello specifico, in questo stile: '(function() {return {var1: \" variable1 \ ", var2: \" variable2 \ "};})();' – Knossos

risposta

1

Questa risposta è errata. Tenuto qui perché ha importanti commenti rilevanti.

La ragione per cui non si ottiene un risultato dal proprio Javascript, è che non si sta chiamando direttamente una funzione. Stai assegnando una funzione nel tuo Javascript che restituisce un valore, ma non lo restituirà al tuo codice, lo restituirà a qualsiasi chiamata history.pushState().

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

Invece, è possibile verificare se qualcosa di simile si restituisce un valore:

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

Non verrà restituito subito? Voglio che il gestore si attivi quando l'utente tocca qualcosa che lo fa allontanare. – Andrew

+0

Sì, tornerebbe subito. Non penso che tu possa eseguire una richiamata nello stile che stai pensando. Stai valutando direttamente Javascript attraverso quella funzione. Invierai immediatamente il JS, verrà valutato e verrà restituito un valore (se specificato). Tuttavia, nel tuo codice stai valutando l'impostazione di una funzione, e questo è quanto. Si potrebbe in teoria utilizzare 'webView.addJavascriptInterface'. Lo hai studiato? – Knossos

+0

Sì, ma la mia interfaccia non sembra funzionare su Android 4.4+. Funziona bene pre-4.4. – Andrew

5

L'utente sta cercando di allontanarsi dalla pagina. per impedirgli di uscire, restituire false. per lasciarlo andare via, non restituire nulla, ma puoi eseguire qualsiasi codice che desideri. Questo evento viene attivato immediatamente quando si verifica l'evento di navigazione, incluso l'aggiornamento della pagina.

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

è necessario includere l'intero codice javascript sopra, dal momento che alcuni browser usano onbeforeunload e un certo uso unload

EDIT

Dopo un'attenta lettura del problema che ho trovato la mia soluzione per essere di scarsa utilità .

Ecco un altro approccio utilizzando history. Se la tua cronologia è vuota, significa che è la prima pagina.ma se hai alcuni elementi nella cronologia, significa che la navigazione è avvenuta.

È possibile controllare come segue

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