Utilizza WebView
per distribuire un'applicazione web
o una pagina web come parte di un'applicazione client. La classe WebView
è un'estensione della classe View
di Android che ti consente di visualizzare pagine web come parte del layout dell'attività. Non include le
funzionalità di un browser web completamente sviluppato, come i controlli di navigazione o una
barra degli indirizzi. Per impostazione predefinita, WebView
mostra solo una pagina web.
WebView
può aiutarti a fornire informazioni nella tua app che potresti dover aggiornare, ad esempio un contratto con l'utente finale o una guida per l'utente. All'interno della tua app per Android,
puoi creare un Activity
che contenga un
WebView
, quindi utilizzarlo per visualizzare il documento ospitato online.
WebView
può essere utile anche quando la tua app fornisce all'utente dati che richiedono una
connessione a internet per il recupero, ad esempio le email. In questo caso, potresti
trovare più semplice creare un WebView
nella tua app per Android che mostri una pagina web
con tutti i dati utente, anziché eseguire una richiesta di rete, quindi
analizzare i dati e visualizzarli in un layout Android. Puoi invece progettare
una pagina web personalizzata per i dispositivi Android e poi implementare un
WebView
nella tua app per Android che carichi la pagina web.
Questo documento descrive come iniziare a utilizzare WebView
, come associare
JavaScript dalla tua pagina web al codice lato client nella tua app per Android, come
gestire la navigazione delle pagine e come gestire le finestre quando utilizzi WebView
.
Utilizzare WebView nelle versioni precedenti di Android
Per utilizzare in modo sicuro le funzionalità più recenti di WebView
sul dispositivo su cui è in esecuzione la tua app, aggiungi la libreria AndroidX
Webkit. Si tratta di una libreria statica
che puoi aggiungere alla tua applicazione per utilizzare le API android.webkit
non
disponibili per le versioni precedenti della piattaforma.
Aggiungilo al tuo file build.gradle
come segue:
Kotlin
dependencies { implementation("androidx.webkit:webkit:1.8.0") }
Groovy
dependencies { implementation ("androidx.webkit:webkit:1.8.0") }
Per maggiori dettagli, esplora l'esempio WebView
su GitHub.
Aggiungere una WebView all'app
Per aggiungere un WebView
alla tua app, puoi includere l'elemento <WebView>
nel layout dell'attività o impostare l'intera finestra Activity
come WebView
in
onCreate()
.
Aggiungere una WebView nel layout dell'attività
Per aggiungere un WebView
all'app nel layout, aggiungi il seguente codice al file XML di layout dell'attività:
<WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" />
Per caricare una pagina web in WebView
, utilizza
loadUrl()
, come
mostrato nell'esempio seguente:
Kotlin
val myWebView: WebView = findViewById(R.id.webview) myWebView.loadUrl("http://www.example.com")
Java
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.loadUrl("http://www.example.com");
Aggiungere una WebView in onCreate()
Per aggiungere un WebView
alla tua app nel metodo onCreate()
di un'attività, utilizza
una logica simile alla seguente:
Kotlin
val myWebView = WebView(activityContext) setContentView(myWebView)
Java
WebView myWebView = new WebView(activityContext); setContentView(myWebView);
Quindi carica la pagina:
Kotlin
myWebView.loadUrl("http://www.example.com")
Java
myWebView.loadUrl("https://www.example.com");
Oppure carica l'URL da una stringa HTML:
Kotlin
// Create an unencoded HTML string, then convert the unencoded HTML string into // bytes. Encode it with base64 and load the data. val unencodedHtml = "<html><body>'%23' is the percent code for ‘#‘ </body></html>"; val encodedHtml = Base64.encodeToString(unencodedHtml.toByteArray(), Base64.NO_PADDING) myWebView.loadData(encodedHtml, "text/html", "base64")
Java
// Create an unencoded HTML string, then convert the unencoded HTML string into // bytes. Encode it with base64 and load the data. String unencodedHtml = "<html><body>'%23' is the percent code for ‘#‘ </body></html>"; String encodedHtml = Base64.encodeToString(unencodedHtml.getBytes(), Base64.NO_PADDING); myWebView.loadData(encodedHtml, "text/html", "base64");
La tua app deve avere accesso a internet. Per ottenere l'accesso a internet, richiedi l'autorizzazione
INTERNET
nel file manifest, come mostrato nell'esempio seguente:
<manifest ... > <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
Puoi personalizzare il tuo WebView
in uno dei seguenti modi:
- Attivazione del supporto dello schermo intero tramite
WebChromeClient
. Questa classe viene chiamata anche quando unWebView
ha bisogno dell'autorizzazione per modificare la UI dell'app host, ad esempio per creare o chiudere finestre o inviare finestre di dialogo JavaScript all'utente. Per scoprire di più sul debug in questo contesto, leggi Eseguire il debug delle app web. - Gestione di eventi che influiscono sul rendering dei contenuti, ad esempio errori nell'invio di moduli o nella navigazione tramite
WebViewClient
. Puoi anche utilizzare questa sottoclasse per intercettare il caricamento degli URL. - Attivazione di JavaScript modificando
WebSettings
. - Utilizzo di JavaScript per accedere agli oggetti del framework Android che hai inserito
in un
WebView
.
Utilizzare JavaScript in WebView
Se la pagina web che vuoi caricare in WebView
utilizza JavaScript, devi
attivare JavaScript per WebView
. Dopo aver attivato JavaScript, puoi
creare interfacce tra il codice dell'app e il codice JavaScript.
Attiva JavaScript
JavaScript è disattivato per impostazione predefinita in un WebView
. Puoi attivarlo tramite
WebSettings
collegato al tuo WebView
. Recupera WebSettings
con
getSettings()
, poi attiva
JavaScript con
setJavaScriptEnabled()
.
Vedi il seguente esempio:
Kotlin
val myWebView: WebView = findViewById(R.id.webview) myWebView.settings.javaScriptEnabled = true
Java
WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setJavaScriptEnabled(true);
WebSettings
fornisce l'accesso a una serie di altre impostazioni che potresti trovare
utili. Ad esempio, se stai sviluppando un'applicazione web progettata
specificamente per WebView
nella tua app per Android, puoi definire una stringa
user agent personalizzata con
setUserAgentString()
,
quindi eseguire una query sull'user agent personalizzato nella tua pagina web per verificare che il client
che richiede la tua pagina web sia la tua app per Android.
Associare il codice JavaScript al codice Android
Quando sviluppi un'applicazione web progettata specificamente per WebView
nella tua app per Android, puoi creare interfacce tra il codice JavaScript e
il codice Android lato client. Ad esempio, il codice JavaScript può chiamare un metodo nel codice Android per visualizzare un Dialog
, anziché utilizzare la funzione alert()
di JavaScript.
Per associare una nuova interfaccia tra il codice JavaScript e quello Android, chiama
addJavascriptInterface()
,
passando un'istanza di classe da associare a JavaScript e un nome di interfaccia
che JavaScript può chiamare per accedere alla classe.
Ad esempio, puoi includere la seguente classe nella tua app per Android:
Kotlin
/** Instantiate the interface and set the context. */ class WebAppInterface(private val mContext: Context) { /** Show a toast from the web page. */ @JavascriptInterface fun showToast(toast: String) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show() } }
Java
public class WebAppInterface { Context mContext; /** Instantiate the interface and set the context. */ WebAppInterface(Context c) { mContext = c; } /** Show a toast from the web page. */ @JavascriptInterface public void showToast(String toast) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); } }
In questo esempio, la classe WebAppInterface
consente alla pagina web di creare un messaggio Toast
utilizzando il metodo showToast()
.
Puoi associare questa classe al codice JavaScript eseguito in WebView
con
addJavascriptInterface()
, come mostrato nell'esempio seguente:
Kotlin
val webView: WebView = findViewById(R.id.webview) webView.addJavascriptInterface(WebAppInterface(this), "Android")
Java
WebView webView = (WebView) findViewById(R.id.webview); webView.addJavascriptInterface(new WebAppInterface(this), "Android");
Viene creata un'interfaccia denominata Android
per JavaScript in esecuzione in
WebView
. A questo punto, la tua applicazione web ha accesso alla classe
WebAppInterface
. Ad esempio, ecco alcuni codici HTML e JavaScript che
creano un messaggio di notifica utilizzando la nuova interfaccia quando l'utente tocca un pulsante:
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /> <script type="text/javascript"> function showAndroidToast(toast) { Android.showToast(toast); } </script>
Non è necessario inizializzare l'interfaccia Android
da JavaScript. WebView
lo rende automaticamente disponibile per la tua pagina web. Quindi, quando un utente
tocca il pulsante, la funzione showAndroidToast()
utilizza l'interfaccia Android
per chiamare il metodo WebAppInterface.showToast()
.
Gestire la navigazione nelle pagine
Quando l'utente tocca un link da una pagina web nel tuo WebView
, per impostazione predefinita Android
avvia un'app che gestisce gli URL. Di solito, il browser web predefinito si apre e
carica l'URL di destinazione. Tuttavia, puoi ignorare questo comportamento per il tuo
WebView
in modo che i link si aprano all'interno di WebView
. Puoi quindi consentire all'utente
di navigare avanti e indietro nella cronologia delle pagine web gestita
dal tuo WebView
.
Per aprire i link toccati dall'utente, fornisci un WebViewClient
per il tuo WebView
utilizzando
setWebViewClient()
.
Tutti i link toccati dall'utente vengono caricati in WebView
. Se vuoi avere un maggiore controllo
sul caricamento di un link su cui è stato fatto clic, crea un WebViewClient
personalizzato che esegua l'override del metodo
shouldOverrideUrlLoading()
. Il seguente esempio presuppone che MyWebViewClient
sia una classe interna
di Activity
.
Kotlin
private class MyWebViewClient : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { if (Uri.parse(url).host == "www.example.com") { // This is your website, so don't override. Let your WebView load // the page. return false } // Otherwise, the link isn't for a page on your site, so launch another // Activity that handles URLs. Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply { startActivity(this) } return true } }
Java
private class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { if ("www.example.com".equals(request.getUrl().getHost())) { // This is your website, so don't override. Let your WebView load the // page. return false; } // Otherwise, the link isn't for a page on your site, so launch another // Activity that handles URLs. Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl()); startActivity(intent); return true; } }
Quindi crea un'istanza di questo nuovo WebViewClient
per WebView
:
Kotlin
val myWebView: WebView = findViewById(R.id.webview) myWebView.webViewClient = MyWebViewClient()
Java
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.setWebViewClient(new MyWebViewClient());
Ora, quando l'utente tocca un link, il sistema chiama il metodo
shouldOverrideUrlLoading()
, che controlla se l'host dell'URL corrisponde
a un dominio specifico, come definito nell'esempio precedente. Se la corrispondenza viene trovata, il metodo restituisce false e non esegue l'override del caricamento dell'URL. Consente a
WebView
di caricare l'URL come di consueto. Se l'host URL non corrisponde, viene creato un
Intent
per avviare l'Activity
predefinito
per la gestione degli URL, che viene risolto nel browser web predefinito dell'utente.
Gestire gli URL personalizzati
WebView
applica limitazioni quando richiede risorse e risolve link
che utilizzano uno schema URL personalizzato. Ad esempio, se implementi callback come
shouldOverrideUrlLoading()
o
shouldInterceptRequest()
,
WebView
li richiama solo per gli URL validi.
Ad esempio, WebView
potrebbe non chiamare il metodo shouldOverrideUrlLoading()
per link come questo:
<a href="showProfile">Show Profile</a>
Gli URL non validi, come quello mostrato nell'esempio precedente, vengono gestiti
in modo incoerente in WebView
, pertanto ti consigliamo di utilizzare un URL ben formato.
Puoi utilizzare uno schema personalizzato o un URL HTTPS per un dominio controllato dalla tua organizzazione.
Anziché utilizzare una semplice stringa in un link, come nell'esempio precedente, puoi utilizzare uno schema personalizzato come il seguente:
<a href="example-app:showProfile">Show Profile</a>
Puoi quindi gestire questo URL nel tuo metodo shouldOverrideUrlLoading()
in questo modo:
Kotlin
// The URL scheme must be non-hierarchical, meaning no trailing slashes. const val APP_SCHEME = "example-app:" override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { return if (url?.startsWith(APP_SCHEME) == true) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length), "UTF-8") respondToData(urlData) true } else { false } }
Java
// The URL scheme must be non-hierarchical, meaning no trailing slashes. private static final String APP_SCHEME = "example-app:"; @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith(APP_SCHEME)) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length()), "UTF-8"); respondToData(urlData); return true; } return false; }
L'API shouldOverrideUrlLoading()
è pensata principalmente per lanciare intent per URL specifici. Quando la implementi, assicurati di restituire false
per gli URL gestiti da WebView
. Tuttavia, non sei limitato all'avvio di intent. Puoi sostituire gli intent di avvio con qualsiasi comportamento personalizzato negli esempi di codice precedenti.
Navigare nella cronologia delle pagine web
Quando WebView
esegue l'override del caricamento degli URL, accumula automaticamente una
cronologia delle pagine web visitate. Puoi navigare avanti e indietro nella cronologia con goBack()
e goForward()
.
Ad esempio, di seguito viene mostrato come il tuo Activity
può utilizzare il pulsante Indietro
del dispositivo per spostarsi indietro:
Kotlin
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { // Check whether the key event is the Back button and if there's history. if (keyCode == KeyEvent.KEYCODE_BACK && myWebView.canGoBack()) { myWebView.goBack() return true } // If it isn't the Back button or there isn't web page history, bubble up to // the default system behavior. Probably exit the activity. return super.onKeyDown(keyCode, event) }
Java
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { // Check whether the key event is the Back button and if there's history. if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) { myWebView.goBack(); return true; } // If it isn't the Back button or there's no web page history, bubble up to // the default system behavior. Probably exit the activity. return super.onKeyDown(keyCode, event); }
Se la tua app utilizza AndroidX AppCompat
1.6.0 o versioni successive, puoi semplificare ulteriormente lo snippet precedente:
Kotlin
onBackPressedDispatcher.addCallback { // Check whether there's history. if (myWebView.canGoBack()) { myWebView.goBack() } }
Java
onBackPressedDispatcher.addCallback { // Check whether there's history. if (myWebView.canGoBack()) { myWebView.goBack(); } }
Il metodo canGoBack()
restituisce true se esiste una cronologia delle pagine web che l'utente può visitare. Allo stesso modo, puoi utilizzare canGoForward()
per verificare se esiste una cronologia in avanti. Se non esegui questo controllo, dopo che l'utente raggiunge la fine della cronologia, goBack()
e goForward()
non fanno nulla.
Gestire le modifiche alla configurazione del dispositivo
Durante l'esecuzione, le modifiche dello stato di attività si verificano quando la configurazione di un dispositivo cambia, ad esempio quando gli utenti ruotano il dispositivo o chiudono un editor del metodo di input (IME). Queste modifiche causano l'eliminazione dell'attività di un oggetto WebView
e la creazione di una nuova attività, che crea anche un nuovo oggetto WebView
che carica l'URL dell'oggetto eliminato. Per modificare il comportamento predefinito dell'attività, puoi
modificare la gestione delle modifiche di orientation
nel manifest. Per scoprire di più
sulla gestione delle modifiche alla configurazione durante l'runtime, leggi Gestire le modifiche
alla configurazione.
Gestisci finestre
Per impostazione predefinita, le richieste di apertura di nuove finestre vengono ignorate. Questo vale sia che vengano aperti da JavaScript sia dall'attributo target in un link. Puoi personalizzare
il tuo WebChromeClient
per fornire un comportamento personalizzato per l'apertura di più
finestre.
Per proteggere al meglio la tua app, è consigliabile impedire l'apertura di popup e nuove finestre. Il modo più sicuro per implementare questo comportamento è passare "true"
a
setSupportMultipleWindows()
ma non eseguire l'override del
metodo onCreateWindow()
, da cui dipende setSupportMultipleWindows()
. Questa logica impedisce il caricamento di qualsiasi
pagina che utilizza target="_blank"
nei suoi link.