Intent ed Extras in Android: guida completa con esempi pratici

intent ed extras android

Guida pratica agli Intent in Android: avviare Activity, passare dati con Extras, usare Intent espliciti e impliciti con esempi Java reali.

Gli Intent in Android sono il meccanismo chiave per avviare nuove schermate, delegare azioni al sistema e passare dati tra componenti; di conseguenza comprenderli a fondo è essenziale per progettare un’app moderna, modulare e facile da manutenere. Trovi una guida approfondita sulla documentazione ufficiale Android sugli Intent.

Inoltre, grazie a Intent espliciti e impliciti puoi collegare in modo chiaro le tue Activity, integrarti con altre app installate sul dispositivo e strutturare un ciclo di vita delle Activity coerente con l’architettura dell’applicazione.

Cos’è un Intent ed Extras in Android

Un Intent in Android è un messaggio asincrono che descrive un’azione da eseguire e, facoltativamente, i dati da elaborare. In pratica, quando vuoi avviare una Activity, chiedere al sistema di aprire il browser, condividere un testo o scattare una foto, crei un Intent e lo passi a metodi come startActivity() o startActivityForResult(). Per questo motivo padroneggiare gli intent ed extras Android è fondamentale per qualsiasi sviluppatore che voglia costruire app moderne e ben strutturate.

Un Intent è composto da tre elementi principali: l’azione (ad esempio ACTION_VIEW), i dati (di solito un Uri) e gli Extras, cioè una mappa chiave/valore che ti permette di allegare informazioni aggiuntive. Inoltre, a seconda che tu specifichi o meno la classe di destinazione, l’Intent viene considerato esplicito o implicito.

A differenza di altre piattaforme, Android usa gli Intent per collegare componenti poco accoppiati: una Activity può sapere solo cosa vuole fare (ad esempio “mostrare i dettagli di un prodotto”) senza dipendere dalla logica interna di chi riceve la richiesta. Per questo motivo, gli Intent sono fondamentali non solo per la navigazione, ma anche per definire confini chiari tra moduli dell’app.

Intent Esplicito Android: avviare una Activity specifica

Un Intent esplicito indica in modo diretto quale Activity deve essere avviata. È il caso tipico in cui, all’interno della tua app, passi dalla schermata di lista a quella di dettaglio. Quindi, quando vuoi controllare esattamente il flusso di navigazione, scegli un Intent esplicito e specifichi la classe di destinazione.

Esempio pratico con codice Java

Nell’esempio seguente una MainActivity avvia una DetailActivity quando l’utente preme un pulsante. Il codice mostra il caso d’uso base degli Intent in Android nella forma esplicita.

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button buttonOpenDetail = findViewById(R.id.buttonOpenDetail);
        buttonOpenDetail.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, DetailActivity.class);
                startActivity(intent);
            }
        });
    }
}

Come vedi, l’Intent in Android viene costruito passando il Context corrente e la classe della Activity di destinazione; inoltre, il metodo startActivity() chiede al sistema di creare la nuova schermata e inserirla nello stack di navigazione.

Passare Extras Android con putExtra()

Nella pratica quotidiana non basta avviare una Activity: devi spesso trasferire informazioni come l’ID di un elemento, il nome dell’utente o uno stato di configurazione. Per questo motivo gli Intent in Android mettono a disposizione gli Extras, che puoi impostare con il metodo putExtra().

Nel codice seguente, ad esempio, MainActivity passa alla DetailActivity un identificatore, un titolo e un flag booleano:

Intent intent = new Intent(MainActivity.this, DetailActivity.class);
intent.putExtra("EXTRA_PRODUCT_ID", 42);
intent.putExtra("EXTRA_PRODUCT_TITLE", "Smartphone Android");
intent.putExtra("EXTRA_FROM_NOTIFICATION", true);

startActivity(intent);

Usare chiavi costanti e nomi descrittivi rende molto più chiaro il passaggio dati tra Activity e, di conseguenza, semplifica la collaborazione tra sviluppatori. Inoltre, grazie a questo approccio puoi centralizzare la definizione delle chiavi in una classe dedicata o in un oggetto Kotlin.

Ricevere gli Extras Android nella seconda Activity

Nel lato ricevente, l’Activity accede all’Intent in Android che l’ha avviata tramite getIntent() e utilizza i metodi getIntExtra(), getStringExtra() e simili per leggere gli Extras. È importante, tuttavia, fornire valori di default per evitare crash quando alcune chiavi non sono presenti.

public class DetailActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);

        TextView textTitle = findViewById(R.id.textTitle);

        Intent intent = getIntent();
        int productId = intent.getIntExtra("EXTRA_PRODUCT_ID", -1);
        String title = intent.getStringExtra("EXTRA_PRODUCT_TITLE");
        boolean fromNotification = intent.getBooleanExtra("EXTRA_FROM_NOTIFICATION", false);

        if (productId != -1 && title != null) {
            textTitle.setText(title + " (ID: " + productId + ")");
        }

        if (fromNotification) {
            // Ad esempio, traccia un evento di analytics personalizzato
        }
    }
}

Questo flusso di passaggio dati tra Activity si integra alla perfezione con il pattern MVVM e ViewModel, che puoi usare per mantenere lo stato in memoria e ridurre al minimo la quantità di informazioni serializzate negli Extras.

Intent Implicito Android: azioni di sistema

Un Intent implicito non specifica direttamente la Activity di destinazione; invece, descrive l’azione da eseguire e il tipo di dato da gestire. Sarà il sistema operativo a trovare la migliore app in grado di soddisfare la richiesta, oppure a mostrare all’utente un chooser. Gli Intent in Android di questo tipo permettono, quindi, di integrare facilmente funzionalità offerte da altre applicazioni. Consulta la documentazione Android sui comuni Intent di sistema per scoprire tutte le azioni predefinite.

Aprire un URL nel browser

Uno degli scenari più comuni è l’apertura di un link nel browser predefinito. In questo caso l’azione da usare è ACTION_VIEW e l’Uri contiene l’indirizzo da visitare. Inoltre è buona norma verificare che esista almeno un handler prima di chiamare startActivity().

String url = "https://developer.android.com";
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));

if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
} else {
    // Gestisci il caso in cui nessun browser sia disponibile
}

Grazie a questo meccanismo l’utente può scegliere, ad esempio, tra Chrome, Firefox o altri browser installati, mantenendo l’esperienza coerente con le proprie preferenze.

Inviare un’email

Per comporre una nuova email puoi usare un Intent implicito con azione ACTION_SENDTO e schema mailto:. In questo modo l’app di posta scelta dall’utente verrà aperta con campi precompilati, semplificando l’operazione di supporto o feedback.

Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"support@example.com"});
intent.putExtra(Intent.EXTRA_SUBJECT, "Richiesta di supporto");
intent.putExtra(Intent.EXTRA_TEXT, "Ciao, ho bisogno di aiuto con la tua app...");

if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
}

Tuttavia, non tutti i client email supportano allo stesso modo gli Extras avanzati; per questo motivo conviene mantenere il messaggio semplice e testare il comportamento sulle app più diffuse.

Effettuare una chiamata

Per avviare la composizione di una telefonata è consigliabile usare l’azione ACTION_DIAL, che apre il dialer con il numero già impostato. A differenza di ACTION_CALL, non richiede permessi per effettuare direttamente la chiamata e, di conseguenza, rispetta meglio le aspettative dell’utente.

String phoneNumber = "+391234567890";
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + phoneNumber));

if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
}

Questo pattern è molto comune nelle app aziendali e, inoltre, può essere combinato con un Navigation Component che gestisce la transizione tra schermate prima di proporre l’azione di chiamata.

Trasferire oggetti con Intent ed Extras Android

Finora abbiamo visto il passaggio dati tra Activity usando tipi primitivi e stringhe. Tuttavia, nella vita reale devi spesso trasferire oggetti più ricchi, come modelli di dominio o configurazioni di filtro. Gli intent ed extras Android supportano il trasferimento di oggetti che implementano Serializable o Parcelable, permettendoti di mantenere un’architettura pulita e una comunicazione efficace tra i componenti della tua app.

Usare Serializable

Serializable è l’opzione più semplice: basta far implementare l’interfaccia alla classe e l’oggetto potrà essere passato come Extra. Ad esempio, immagina un modello User con nome ed età:

public class User implements Serializable {

    private final String name;
    private final int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

Il passaggio dati tra Activity con questo oggetto diventa quindi molto naturale:

User user = new User("Mario Rossi", 30);
Intent intent = new Intent(MainActivity.this, ProfileActivity.class);
intent.putExtra("EXTRA_USER", user);
startActivity(intent);

Nella Activity di destinazione recuperi l’oggetto tramite getSerializableExtra() e lo casti al tipo corretto:

User user = (User) getIntent().getSerializableExtra("EXTRA_USER");
if (user != null) {
    // Usa user.getName() e user.getAge()
}

Serializable è molto comodo per prototipi o per app con poco traffico tra Activity; tuttavia, quando il passaggio di oggetti è frequente o coinvolge liste numerose, l’overhead può diventare rilevante.

Usare Parcelable

Parcelable è un’interfaccia pensata specificamente per Android, più efficiente di Serializable ma anche più verbosa. In Java richiede di implementare metodi come writeToParcel() e di definire un campo CREATOR, mentre in Kotlin puoi semplificare molto con l’annotazione @Parcelize. Di conseguenza è la scelta ideale quando devi ottimizzare le prestazioni.

Un approccio bilanciato prevede di usare Parcelable per le entità che viaggiano spesso negli Intent in Android, mantenendo invece Serializable per casi sporadici o di debug. Inoltre, grazie all’uso di ViewModel condivisi, puoi ridurre ulteriormente la quantità di dati serializzati e lasciare ai ViewModel la responsabilità di recuperare i dettagli da repository o database.

Esplicito o implicito: quale scegliere?

Per questo motivo è utile confrontare rapidamente Intent esplicito e Intent implicito, così da scegliere consapevolmente lo strumento giusto ogni volta che devi gestire il passaggio dati tra Activity o delegare un’azione al sistema.

Tipo Quando usarlo Esempio pratico
Intent esplicito Quando conosci la Activity di destinazione all'interno della tua app. Aprire la schermata di dettaglio di un articolo dalla lista principale.
Intent esplicito con Extras Quando devi passare parametri strutturati alla nuova schermata. Inviare ID prodotto, nome utente o oggetti Serializable/Parcelable.
Intent implicito Quando vuoi delegare un'azione a qualsiasi app in grado di gestirla. Aprire un link nel browser o condividere un testo sui social.
Intent implicito per media Quando l'utente deve scegliere un'app per foto, video o selezione file. Avviare la fotocamera o il file picker di sistema.
Intent con risultato Quando ti serve un valore di ritorno dalla Activity avviata. Selezionare un contatto, scegliere un file o restituire un input dell'utente.

startActivityForResult() e ActivityResultLauncher con Intent Android

Alcuni flussi richiedono non solo di avviare una Activity, ma anche di ricevere un risultato. Pensiamo, ad esempio, alla scelta di un’immagine dalla galleria o alla selezione di un documento. Storicamente, per questi scenari si usava startActivityForResult() insieme al metodo onActivityResult(), basati sempre su Intent in Android.

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_CODE_PICK_IMAGE = 1001;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button buttonPickImage = findViewById(R.id.buttonPickImage);
        buttonPickImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_PICK);
                intent.setType("image/*");
                startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == REQUEST_CODE_PICK_IMAGE && resultCode == RESULT_OK && data != null) {
            Uri imageUri = data.getData();
            // Usa imageUri per mostrare l'immagine
        }
    }
}

Questo approccio funziona ancora, ma nelle versioni moderne del framework è stato deprecato. Di conseguenza, la soluzione raccomandata è l’uso di ActivityResultLauncher e ActivityResultContracts, che semplificano la gestione del ciclo di vita e si integrano meglio con Activity e Ciclo di Vita.

public class MainActivity extends AppCompatActivity {

    private ActivityResultLauncher<Intent> pickImageLauncher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        pickImageLauncher = registerForActivityResult(
                new ActivityResultContracts.StartActivityForResult(),
                result -> {
                    if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) {
                        Uri imageUri = result.getData().getData();
                        // Usa imageUri per aggiornare la UI
                    }
                }
        );

        Button buttonPickImage = findViewById(R.id.buttonPickImage);
        buttonPickImage.setOnClickListener(v -> {
            Intent intent = new Intent(Intent.ACTION_PICK);
            intent.setType("image/*");
            pickImageLauncher.launch(intent);
        });
    }
}

In questo modo il codice rimane vicino al punto di lancio; inoltre, l’API è più sicura rispetto al ciclo di vita e riduce il rischio di memory leak, soprattutto quando usata insieme a ViewModel e Navigation Component.

Consigli per un codice pulito e manutenibile

Per sfruttare al massimo gli Intent in Android è fondamentale seguire alcune buone pratiche. Innanzitutto, verifica sempre la presenza di un handler con resolveActivity() prima di chiamare startActivity(), in particolare quando lavori con Intent impliciti che dipendono da app esterne.

Inoltre, usa costanti centralizzate per le chiavi degli Extras, così da ridurre errori di battitura e rendere esplicito quali dati vengono scambiati tra Activity. Questo approccio si integra bene con un’architettura pulita basata su MVVM e ViewModel, dove i ViewModel espongono solo gli ID necessari, mentre i repository si occupano di caricare i dettagli.

Evita di inserire negli Extras oggetti o liste eccessivamente grandi: invece di serializzare blocchi di dati corposi, salva le informazioni in un database locale, ad esempio usando SharedPreferences, o in un livello di cache e passa solo le chiavi necessarie. Per questo motivo il passaggio dati tra Activity dovrebbe limitarsi a ciò che è strettamente indispensabile per ricostruire lo stato.

Infine, presta grande attenzione alle informazioni sensibili: token, credenziali e dati personali non dovrebbero mai circolare in chiaro, soprattutto quando coinvolgono componenti esterni. In questi casi è preferibile usare canali dedicati o utilizzare meccanismi di autenticazione server side.

Conclusione e risorse utili

Abbiamo visto come usare gli Intent in Android per avviare Activity, passare dati con Extras, delegare azioni al sistema e ricevere risultati con le API moderne basate su ActivityResultLauncher. Di conseguenza, padroneggiare questi strumenti significa costruire flussi di navigazione chiari e prevedibili, in linea con il ciclo di vita delle schermate.

Per chiudere, ti consiglio di approfondire il ruolo delle Activity leggendo l’articolo su Activity e Ciclo di Vita, di esplorare il Navigation Component per una navigazione dichiarativa e, infine, di integrare tutto con MVVM e ViewModel così da ottenere un’architettura solida, testabile e pronta a crescere nel tempo. Trovi tutti gli articoli raccolti nella pagina Guide Android, il punto di partenza per il tuo percorso di sviluppo mobile.

Commenti

Rispondi

Scopri di più da App Tutorial

Abbonati ora per continuare a leggere e avere accesso all'archivio completo.

Continua a leggere