Crea app web in WebView

Utilizza WebView per pubblicare un'applicazione web o una pagina web come parte di un'applicazione client. La classe WebView è un'estensione della classe View di Android che consente di visualizzare le pagine web all'interno 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 nella tua app informazioni di cui potresti aver bisogno un aggiornamento, ad esempio un contratto con l'utente finale o una guida dell'utente. Nell'app per Android, puoi creare una Activity che contiene un WebView, quindi utilizzalo 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 scopri che è più facile creare un'WebView nella tua app per Android che mostra un con tutti i dati utente, invece di eseguire una richiesta di rete, analizzare i dati e eseguirne il rendering in un layout Android. In alternativa, puoi progettare una pagina web personalizzata per i dispositivi Android e implementare un WebView nella tua app per Android che carichi la pagina web.

Questo documento descrive come iniziare a utilizzare WebView, come eseguire il binding di JavaScript dalla pagina web al codice lato client nell'app per Android, come gestire la navigazione tra le pagine e come gestire le finestre quando si utilizza WebView.

Utilizzare WebView su versioni precedenti di Android

Per utilizzare in sicurezza le funzionalità di WebView più recenti sul dispositivo, la tua app è in esecuzione, aggiungi l'app AndroidX nella libreria Webkit. Si tratta di una biblioteca statica che puoi aggiungere alla tua applicazione per utilizzare le API android.webkit non disponibili per le versioni precedenti della piattaforma.

Aggiungilo al file build.gradle come segue:

dependencies {
    implementation("androidx.webkit:webkit:1.8.0")
}
dependencies {
    implementation ("androidx.webkit:webkit:1.8.0")
}

Per maggiori dettagli, consulta l'esempio WebView su GitHub.

Aggiungere un componente WebView all'app

Per aggiungere un WebView alla tua app, puoi includere l'elemento <WebView> nel tuo layout attività o imposta l'intera finestra Activity come WebView in onCreate().

Aggiungi una WebView nel layout dell'attività

Per aggiungere un WebView all'app nel layout, aggiungi il seguente codice al file XML del 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, usa loadUrl(), come come mostrato nell'esempio seguente:

KotlinJava
val myWebView: WebView = findViewById(R.id.webview)
myWebView.loadUrl("http://www.example.com")
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("http://www.example.com");

Aggiungi un componente WebView in onCreate()

Per aggiungere un WebView alla tua app nel metodo onCreate() di un'attività, utilizza una logica simile alla seguente:

KotlinJava
val myWebView = WebView(activityContext)
setContentView(myWebView)
WebView myWebView = new WebView(activityContext);
setContentView(myWebView);

Quindi carica la pagina:

KotlinJava
myWebView.loadUrl("http://www.example.com")
myWebView.loadUrl("https://www.example.com");

Oppure carica l'URL da una stringa HTML:

KotlinJava
// 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")
// 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");

L'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 a schermo intero con WebChromeClient Questo corso viene chiamato anche quando un WebView ha bisogno dell'autorizzazione per modificare l'UI dell'app host, come creare o chiudere finestre o inviare finestre di dialogo JavaScript al utente. Per scoprire di più sul debug in questo contesto, consulta Debug web Google Cloud.
  • Gestione degli eventi che influiscono sul rendering dei contenuti, ad esempio gli errori nel modulo contenuti o la navigazione usando WebViewClient Puoi anche utilizzare questa sottoclasse per intercettare il caricamento dell'URL.
  • Attivazione di JavaScript modificando la WebSettings
  • Utilizzo di JavaScript per accedere agli oggetti del framework Android inseriti in un WebView.

Utilizzare JavaScript in WebView

Se la pagina web che vuoi caricare nel tuo WebView utilizza JavaScript, devi attivare JavaScript per il tuo WebView. Dopo aver attivato JavaScript, puoi creare interfacce tra il codice dell'app e il codice JavaScript.

Attiva JavaScript

JavaScript è disattivato in un WebView per impostazione predefinita. Puoi abilitarlo tramite WebSettings collegato a WebView. Recupera WebSettings con getSettings(), quindi attiva JavaScript con setJavaScriptEnabled().

Vedi l'esempio che segue:

KotlinJava
val myWebView: WebView = findViewById(R.id.webview)
myWebView.settings.javaScriptEnabled = true
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

WebSettings consente di accedere 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 personalizzata dell'agente utente con setUserAgentString(), quindi eseguire una query sull'agente utente 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

Durante lo sviluppo di un'applicazione web progettata specificatamente per il WebView Nell'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 in il tuo codice Android per visualizzare un Dialog anziché utilizzare la funzione alert() di JavaScript.

Per associare una nuova interfaccia tra il codice JavaScript e Android, chiama addJavascriptInterface(), passando un'istanza di classe da associare al codice JavaScript e un nome di interfaccia che il codice JavaScript può chiamare per accedere alla classe.

Ad esempio, puoi includere la seguente classe nella tua app per Android:

KotlinJava
/** 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()
    }
}
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:

KotlinJava
val webView: WebView = findViewById(R.id.webview)
webView.addJavascriptInterface(WebAppInterface(this), "Android")
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 WebAppInterface corso. Ad esempio, ecco alcuni file HTML e JavaScript che crea un messaggio toast 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. Pertanto, 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. In genere, si apre il browser web predefinito e viene caricato l'URL di destinazione. Tuttavia, puoi ignorare questo comportamento per il tuo WebView in modo che i link si aprano all'interno del tuo 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 su dove viene caricato un link su cui è stato fatto clic, crea il tuo WebViewClient che sostituisce il metodo shouldOverrideUrlLoading(). L'esempio seguente presuppone che MyWebViewClient sia una classe interna di Activity.

KotlinJava
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
    }
}
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:

KotlinJava
val myWebView: WebView = findViewById(R.id.webview)
myWebView.webViewClient = MyWebViewClient()
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 corrisponde, il metodo restituisce false e non sostituisce il caricamento dell'URL. Consente alla WebView caricano l'URL come di consueto. Se l'host dell'URL non corrisponde, Intent è stato creato per avviare l'app predefinita Activity per la gestione degli URL, che si risolve nel browser web predefinito dell'utente.

Gestire gli URL personalizzati

WebView applica limitazioni quando richiedi risorse e risolvi i link che utilizzano uno schema URL personalizzato. Ad esempio, se implementi callback come shouldOverrideUrlLoading() o shouldInterceptRequest(), WebView li invoca solo per URL validi.

Ad esempio, WebView potrebbe non chiamare il tuo 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 consigliamo di utilizzare un URL ben formato. Puoi utilizzare uno schema personalizzato o un URL HTTPS per un dominio che la tua organizzazione i controlli di sicurezza.

Invece di 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(), ad esempio questo:

KotlinJava
// 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
    }
}
// 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 avviare intent per URL specifici. Durante l'implementazione, assicurati di restituire false per gli URL gli handle WebView. Tuttavia, non sei limitato a lanciare intent. Puoi sostituire le intenzioni di lancio con qualsiasi comportamento personalizzato nei sample di codice precedenti.

Quando WebView sostituisce il caricamento dell'URL, accumula automaticamente un cronologia delle pagine web visitate. Puoi spostarti avanti e indietro nel cronologia con goBack() e goForward().

Ad esempio, di seguito viene mostrato come Activity può utilizzare il pulsante Indietro del dispositivo per tornare indietro:

KotlinJava
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)
}
@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:

KotlinJava
onBackPressedDispatcher.addCallback {
    // Check whether there's history.
    if (myWebView.canGoBack()) {
        myWebView.goBack()
    }
}
onBackPressedDispatcher.addCallback {
    // Check whether there's history.
    if (myWebView.canGoBack()) {
        myWebView.goBack();
    }
}

Il metodo canGoBack() restituisce true se esiste una cronologia di pagine web da visitare per l'utente. Analogamente, puoi utilizzare canGoForward() per verificare se è presente 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 il runtime, lo stato delle attività cambia quando la configurazione Modifiche, ad esempio quando gli utenti ruotano il dispositivo o ignorano l'editor di un metodo di immissione (IME). Queste modifiche causano l'eliminazione dell'attività di un oggetto WebView e un nuova attività da creare, che crea anche un nuovo oggetto WebView che carica dell'oggetto eliminato. Per modificare il comportamento predefinito dell'attività, puoi cambiare il modo in cui gestisce le modifiche orientation nel file manifest. Per scoprire di più sulla gestione delle modifiche alla configurazione durante il runtime, leggi Gestire la configurazione modifiche.

Gestire le finestre

Per impostazione predefinita, le richieste di apertura di nuove finestre vengono ignorate. Ciò avviene indipendentemente dal fatto che vengono aperte da JavaScript o dall'attributo target in un link. Puoi personalizzare WebChromeClient per impostare il comportamento che preferisci per l'apertura di più finestre.

Per mantenere la tua app più sicura, è meglio evitare popup e nuove finestre apertura in corso. Il modo più sicuro per implementare questo comportamento è trasferire "true" a setSupportMultipleWindows() senza sovrascrivere onCreateWindow() da cui dipende setSupportMultipleWindows(). Questa logica impedisce il caricamento di qualsiasi pagina che utilizza target="_blank" nei suoi link.