Indirizzare l'utente a un'altra app

Una delle funzionalità più importanti di Android è la possibilità di un'app di indirizzare l'utente a un'altra app in base a un'"azione" che desidera eseguire. Ad esempio, se la tua app abbia l'indirizzo di un'attività che vuoi mostrare su una mappa, non devi creare un'attività nella tua app che mostra una mappa. Puoi invece creare una richiesta per visualizzare l'indirizzo utilizzando un Intent. Il sistema Android avvia quindi un'app in grado di mostrare l'indirizzo su una mappa.

Come spiegato nella prima lezione, Creare La tua prima app, devi utilizzare gli intent per navigare tra le attività all'interno dell'app. Tu generalmente mediante un intent esplicito, che definisce il nome esatto della classe che vuoi avviare. Se però vuoi che un'app separata esegua un'azione, come come "visualizza una mappa" devi utilizzare un intent implicito.

Questa lezione mostra come creare un intent implicito per una determinata azione e come utilizzarlo per avviare un'attività che esegue l'azione in un'altra app. Vedi anche il video incorporato qui per capire perché è importante includere controlli di runtime per gli intent impliciti.

Costruire un intent implicito

Gli intent impliciti non dichiarano il nome della classe del componente per iniziare, ma dichiarano un dell'azione da eseguire. L'azione specifica l'operazione che vuoi eseguire, ad esempio view, edit, send (invia) o get qualcosa.

Associare le azioni intent ai dati

Gli intent includono spesso anche dati associati con l'azione, ad esempio l'indirizzo che vuoi visualizzare o il messaggio email che vuoi inviare. A seconda dell'intento che vuoi creare, i dati potrebbero essere Uri, uno dei numerosi altri tipi di dati, oppure l'intento potrebbe non aver bisogno di dati.

Se i dati sono di tipo Uri, puoi utilizzare un semplice costruttore Intent() per definire l'azione e e i dati di Google Cloud.

Ad esempio, ecco come creare un intent per avviare una telefonata utilizzando i dati di Uri per specificare il numero di telefono:

Kotlin

val callIntent: Intent = Uri.parse("tel:5551234").let { number ->
    Intent(Intent.ACTION_DIAL, number)
}

Java

Uri number = Uri.parse("tel:5551234");
Intent callIntent = new Intent(Intent.ACTION_DIAL, number);

Quando la tua app richiama questo intent chiamando il numero startActivity(), l'app Telefono avvia una chiamata al numero di telefono specificato.

Ecco un paio di altri intent con le relative azioni e i dati di Uri coppie:

Visualizzare una mappa

Kotlin

// Map point based on address
val mapIntent: Intent = Uri.parse(
        "geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California"
).let { location ->
    // Or map point based on latitude/longitude
    // val location: Uri = Uri.parse("geo:37.422219,-122.08364?z=14") // z param is zoom level
    Intent(Intent.ACTION_VIEW, location)
}

Java

// Map point based on address
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
// Or map point based on latitude/longitude
// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

Visualizzare una pagina web

Kotlin

val webIntent: Intent = Uri.parse("https://www.android.com").let { webpage ->
    Intent(Intent.ACTION_VIEW, webpage)
}

Java

Uri webpage = Uri.parse("https://www.android.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);

Aggiungere extra a un intent

Altri tipi di intent impliciti richiedono "extra" che forniscono tipi di dati diversi, come una stringa. Puoi aggiungere uno o più dati aggiuntivi utilizzando i vari metodi di putExtra().

Per impostazione predefinita, il sistema determina il tipo MIME appropriato richiesto da un intent in base al Uri di dati inclusi. Se non includi un valore Uri nei intent, in genere dovresti usare setType() per specificare il tipo di dati associati all'intento. L'impostazione del tipo MIME specifica ulteriormente i tipi di devono ricevere l'intento.

Di seguito sono riportati alcuni intent che aggiungono ulteriori dati per specificare l'azione desiderata:

Inviare un'email con un allegato

Kotlin

Intent(Intent.ACTION_SEND).apply {
    // The intent does not have a URI, so declare the "text/plain" MIME type
    type = "text/plain"
    putExtra(Intent.EXTRA_EMAIL, arrayOf("jan@example.com")) // recipients
    putExtra(Intent.EXTRA_SUBJECT, "Email subject")
    putExtra(Intent.EXTRA_TEXT, "Email message text")
    putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"))
    // You can also attach multiple items by passing an ArrayList of Uris
}

Java

Intent emailIntent = new Intent(Intent.ACTION_SEND);
// The intent does not have a URI, so declare the "text/plain" MIME type
emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jan@example.com"}); // recipients
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
// You can also attach multiple items by passing an ArrayList of Uris

Creare un evento nel calendario

Nota: questo intent per un evento di calendario è supportato solo con l'API livello 14 e livelli successivi.

Kotlin

// Event is on January 23, 2021 -- from 7:30 AM to 10:30 AM.
Intent(Intent.ACTION_INSERT, Events.CONTENT_URI).apply {
    val beginTime: Calendar = Calendar.getInstance().apply {
        set(2021, 0, 23, 7, 30)
    }
    val endTime = Calendar.getInstance().apply {
        set(2021, 0, 23, 10, 30)
    }
    putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.timeInMillis)
    putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.timeInMillis)
    putExtra(Events.TITLE, "Ninja class")
    putExtra(Events.EVENT_LOCATION, "Secret dojo")
}

Java

// Event is on January 23, 2021 -- from 7:30 AM to 10:30 AM.
Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
Calendar beginTime = Calendar.getInstance();
beginTime.set(2021, 0, 23, 7, 30);
Calendar endTime = Calendar.getInstance();
endTime.set(2021, 0, 23, 10, 30);
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
calendarIntent.putExtra(Events.TITLE, "Ninja class");
calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");

Nota: è importante definire Intent in modo che sia il più specifico possibile. Ad esempio, se vuoi visualizzare un'immagine utilizzando l'intent ACTION_VIEW, devi specificare un tipo MIME image/*. In questo modo le app che possono "visualizzare" altri tipi di dati (come un'app di mappe) attivati dall'intento.

Avviare un'attività con l'intento

Dopo aver creato Intent e aver impostato le informazioni aggiuntive, chiama startActivity() per inviarle al sistema:

Kotlin

startActivity(intent)

Java

startActivity(intent);

Gestisci la situazione in cui nessuna app può ricevere un intent

Anche se molti intent vengono gestiti correttamente da un'altra app installata sul dispositivo, ad esempio un'app di smartphone, email o calendario, l'app dovrebbe essere predisposta nei casi in cui nessuna attività possa gestire l'intenzione dell'app. Ogni volta che richiamare un intent, essere pronti a rilevare ActivityNotFoundException, che si verifica se non ci sono altre attività in grado di gestire l'intento della tua app:

Kotlin

try {
    startActivity(intent)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Java

try {
    startActivity(intent);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

Dopo aver individuato l'eccezione, decidi cosa deve fare la tua app. Questo prossimo dipende dalle caratteristiche specifiche dell'intenzione che hai provato a richiamare. Ad esempio, se conosci un'app specifica in grado di gestire l'intent, fornire all'utente un link per scaricare l'app. Scopri di più su come eseguire il collegamento al prodotto su Google Play.

Finestra di dialogo di disambiguazione

Se il sistema identifica più attività in grado di gestire l'intento, visualizza una finestra di dialogo (anche nota come "finestra di disambiguazione") per all'utente di selezionare l'app da utilizzare, come mostrato nella figura 1. Se è presente un solo elemento dell'attività che gestisce l'intent, il sistema la avvia immediatamente.

Viene visualizzato un riquadro
  nella parte inferiore dello schermo. Questo riquadro elenca le diverse app che possono
  gestire l'intento.

Figura 1. Esempio della selezione che viene visualizzata quando più app sono in grado di gestire un intent.

Esempio completo

Ecco un esempio completo che mostra come creare un intent per visualizzare una mappa, verificare che dell'app esiste per gestire l'intent, quindi avviala:

Kotlin

// Build the intent.
val location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California")
val mapIntent = Intent(Intent.ACTION_VIEW, location)

// Try to invoke the intent.
try {
    startActivity(mapIntent)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Java

// Build the intent.
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

// Try to invoke the intent.
try {
    startActivity(mapIntent);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

Mostra un selettore di app

Figura 2. Una finestra di dialogo di selezione.

Tieni presente che quando inizi un'attività passando Intent a startActivity() e sono presenti più app che rispondono l'intent, l'utente può selezionare l'app da utilizzare per impostazione predefinita (selezionando una casella di controllo in basso della finestra di dialogo; vedi figura 1). È utile quando si esegue un'azione per la quale l'utente in genere vuole utilizzare la stessa app ogni volta, ad esempio quando apre una pagina web (gli utenti probabilmente usano un solo browser web) o per scattare una foto (gli utenti probabilmente preferiscono una sola fotocamera).

Tuttavia, se l'azione da eseguire potrebbe essere gestita da più app e l'utente potrebbe preferiscono un'app diversa ogni volta, ad esempio una condivisione per la quale gli utenti potrebbero avere diverse app con cui potrebbero condividere un elemento; devi mostrare esplicitamente una finestra di dialogo di selezione come mostrato nella Figura 2. La finestra di dialogo del selettore obbliga l'utente a selezionare ogni volta quale app utilizzare per l'azione (l'utente non può selezionare un app predefinita per l'azione).

Per mostrare il selettore, crea un Intent utilizzando createChooser() e passalo a startActivity(). Ad esempio:

Kotlin

val intent = Intent(Intent.ACTION_SEND)

// Create intent to show chooser
val chooser = Intent.createChooser(intent, /* title */ null)

// Try to invoke the intent.
try {
    startActivity(chooser)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Java

Intent intent = new Intent(Intent.ACTION_SEND);

// Create intent to show chooser
Intent chooser = Intent.createChooser(intent, /* title */ null);

// Try to invoke the intent.
try {
    startActivity(chooser);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

Viene visualizzata una finestra di dialogo con un elenco di app che rispondono all'intent passato al metodo createChooser(). Il parametro title può essere specificato se l'azione non è ACTION_SEND o ACTION_SEND_MULTIPLE