Soddisfare casi d'uso comuni con una visibilità dei pacchetti limitata

Questo documento illustra diversi casi d'uso comuni in cui un'app interagisce con altre app. Ogni sezione fornisce indicazioni su come realizzare la funzionalità dell'app con visibilità limitata del pacchetto, da tenere in considerazione se la tua app ha come target Android 11 (livello API 30) o versioni successive.

Quando un'app che ha come target Android 11 o versioni successive utilizza un intent per iniziare un'attività in un'altra app, l'approccio più semplice è richiamare l'intento e gestire ActivityNotFoundException se non sono disponibili app.

Se parte della tua app dipende dal sapere se la chiamata startActivity() possono riuscire, ad esempio mostrando una UI, aggiungendo un elemento alla Elemento <queries> dell'app del file manifest. In genere, si tratta di un elemento <intent>.

Apri URL

Questa sezione descrive vari modi per aprire gli URL in un'app che ha come target Android 11 o versioni successive.

Aprire URL in un browser o in un'altra app

Per aprire un URL, utilizza un intent che contenga la sezione ACTION_VIEW azione per intent, come descritto nella guida al caricamento di file web URL. Dopo aver chiamato startActivity() utilizzando questo intent, si verifica una delle seguenti situazioni:

  • L'URL si apre in un'app di browser web.
  • L'URL si apre in un'app che lo supporta come deep .
  • Viene visualizzata una finestra di dialogo di disambiguazione che consente all'utente di scegliere quale app apre l'URL.
  • Si verifica un errore ActivityNotFoundException perché non c'è un'app installata il dispositivo in grado di aprire l'URL. (Si tratta di una situazione insolita).

    È consigliabile che la tua app rilevi e gestisca ActivityNotFoundException, se presente.

Poiché il metodo startActivity() non richiede la visibilità dei pacchetti per avviare l'attività di un'altra applicazione, non è necessario aggiungere un <queries> al file manifest dell'app o apportare modifiche a un <queries> esistente . Questo vale sia per gli intent impliciti che per quelli espliciti che aprono un URL.

Verificare se è disponibile un browser

In alcuni casi, per la tua app potrebbe essere opportuno verificare che sia presente almeno un browser disponibili sul dispositivo o che uno specifico browser è quello predefinito, prima di tentare di aprire un URL. In questi casi, includi quanto segue: Elemento <intent> come parte dell'elemento <queries> nel tuo manifest:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="https" />
</intent>

Quando chiami queryIntentActivities() e passi un intent web come argomento, l'elenco restituito include, in alcuni casi, le app browser disponibili. L'elenco non include le app di browser se l'utente ha configurato l'URL in modo che si apra in un'app non browser per impostazione predefinita.

Apri gli URL nelle schede personalizzate

Schede personalizzate consentono a un'app di personalizzare l'aspetto e il design del browser. Puoi aprire un URL in una scheda personalizzata senza dover aggiungere o modificare l'elemento <queries> nel file manifest dell'app.

Tuttavia, ti consigliamo di controllare se il dispositivo ha un browser che supporta Custom Tabs o di selezionare un browser specifico da avviare con Custom Tabs utilizzando CustomTabsClient.getPackageName(). In questi casi, includi il seguente elemento <intent> nell'elemento <queries> del manifest:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>

Consentire alle app non browser di gestire gli URL

Anche se la tua app può aprire gli URL utilizzando le schede personalizzate, è consigliabile se possibile, consenti a un'app non basata sul browser di aprire un URL. Per fornire nella tua app, prova a effettuare una chiamata a startActivity() usando un intent che imposta FLAG_ACTIVITY_REQUIRE_NON_BROWSER flag di intent. Se il sistema emette un ActivityNotFoundException, la tua app può e apri l'URL in una scheda personalizzata.

Se un intent include questo flag, una chiamata a startActivity() provoca un ActivityNotFoundException da generare quando una delle seguenti opzioni si verifica quando si verificano determinate condizioni:

  • La chiamata avrebbe avviato direttamente un'app browser.
  • La chiamata avrebbe mostrato all'utente una finestra di dialogo di disambiguazione in cui le uniche opzioni sono le app del browser.

Il seguente snippet di codice mostra come aggiornare la logica per utilizzare il parametro Flag di intent di FLAG_ACTIVITY_REQUIRE_NON_BROWSER:

Kotlin

try {
    val intent = Intent(ACTION_VIEW, Uri.parse(url)).apply {
        // The URL should either launch directly in a non-browser app (if it's
        // the default) or in the disambiguation dialog.
        addCategory(CATEGORY_BROWSABLE)
        flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_REQUIRE_NON_BROWSER
    }
    startActivity(intent)
} catch (e: ActivityNotFoundException) {
    // Only browser apps are available, or a browser is the default.
    // So you can open the URL directly in your app, for example in a
    // Custom Tab.
    openInCustomTabs(url)
}

Java

try {
    Intent intent = new Intent(ACTION_VIEW, Uri.parse(url));
    // The URL should either launch directly in a non-browser app (if it's the
    // default) or in the disambiguation dialog.
    intent.addCategory(CATEGORY_BROWSABLE);
    intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_REQUIRE_NON_BROWSER);
    startActivity(intent);
} catch (ActivityNotFoundException e) {
    // Only browser apps are available, or a browser is the default.
    // So you can open the URL directly in your app, for example in a
    // Custom Tab.
    openInCustomTabs(url);
}

Evitare una finestra di dialogo di disambiguazione

Se vuoi evitare di mostrare la finestra di dialogo di disambiguazione che gli utenti potrebbero vedere quando apre un URL, ma preferisce gestirlo personalmente in queste situazioni, puoi utilizzare un intent che imposti FLAG_ACTIVITY_REQUIRE_DEFAULT flag di intent.

Se un'intenzione include questo flag, una chiamata a startActivity() provoca un ActivityNotFoundException quando la chiamata avrebbe mostrato all'utente una finestra di dialogo di disambiguazione.

Se un intent include sia questo flag sia FLAG_ACTIVITY_REQUIRE_NON_BROWSER flag di intent, una chiamata a startActivity() provoca un ActivityNotFoundException da generare quando si verifica una delle seguenti condizioni:

  • La chiamata avrebbe avviato direttamente l'app del browser.
  • La chiamata avrebbe mostrato all'utente una finestra di dialogo di disambiguazione.

Il seguente snippet di codice mostra come utilizzare FLAG_ACTIVITY_REQUIRE_NON_BROWSER e FLAG_ACTIVITY_REQUIRE_DEFAULT insieme:

Kotlin

val url = URL_TO_LOAD
try {
    // For this intent to be invoked, the system must directly launch a
    // non-browser app.
    val intent = Intent(ACTION_VIEW, Uri.parse(url)).apply {
        addCategory(CATEGORY_BROWSABLE)
        flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_REQUIRE_NON_BROWSER or
                FLAG_ACTIVITY_REQUIRE_DEFAULT
    }
    startActivity(intent)
} catch (e: ActivityNotFoundException) {
    // This code executes in one of the following cases:
    // 1. Only browser apps can handle the intent.
    // 2. The user has set a browser app as the default app.
    // 3. The user hasn't set any app as the default for handling this URL.
    openInCustomTabs(url)
}

Java

String url = URL_TO_LOAD;
try {
    // For this intent to be invoked, the system must directly launch a
    // non-browser app.
    Intent intent = new Intent(ACTION_VIEW, Uri.parse(url));
    intent.addCategory(CATEGORY_BROWSABLE);
    intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_REQUIRE_NON_BROWSER |
            FLAG_ACTIVITY_REQUIRE_DEFAULT);
    startActivity(intent);
} catch (ActivityNotFoundException e) {
    // This code executes in one of the following cases:
    // 1. Only browser apps can handle the intent.
    // 2. The user has set a browser app as the default app.
    // 3. The user hasn't set any app as the default for handling this URL.
    openInCustomTabs(url);
}

Apri un file

Se l'app gestisce file o allegati, ad esempio per controllare se un dispositivo può aprire un determinato file, di solito è più facile provare ad avviare un'attività che possa e gestire il file. Per farlo, utilizza un intent che includa l'intent ACTION_VIEW e l'URI che rappresenta il file specifico. Se non è disponibile nessuna app il dispositivo, la tua app può rilevare ActivityNotFoundException. Nel tuo di gestione delle eccezioni, puoi mostrare un errore o provare a gestire il file per te.

Se la tua app deve sapere in anticipo se un'altra app può aprire un determinato file, includi l'elemento <intent> nel seguente snippet di codice come parte della <queries> elemento nel file manifest. Includi il tipo di file, se già conosci al momento della compilazione.

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.VIEW" />
  <!-- If you don't know the MIME type in advance, set "mimeType" to "*/*". -->
  <data android:mimeType="application/pdf" />
</intent>

Dopodiché potrai verificare se un'app è disponibile chiamando il numero resolveActivity() con il tuo intento.

Concedi accesso URI

Nota: dichiarando le autorizzazioni di accesso URI come descritto in questa sezione è obbligatorio per le app destinate ad Android 11 (livello API 30) o versioni successive e consigliato per tutte le app, indipendentemente dalla versione dell'SDK target e dal fatto che esportano i propri fornitori di contenuti.

Affinché le app destinate ad Android 11 o versioni successive possano accedere all'URI dei contenuti, l'intent dell'app deve dichiarare le autorizzazioni di accesso all'URI impostando uno o entrambi i seguenti flag intent: FLAG_GRANT_READ_URI_PERMISSION e FLAG_GRANT_WRITE_URI_PERMISSION.

Su Android 11 e versioni successive, le autorizzazioni di accesso URI forniscono le seguenti funzionalità all'app che riceve l'intent:

  • Leggono o scrivono in base ai dati rappresentati dall'URI dei contenuti, a seconda le autorizzazioni URI specificate.
  • Ottieni visibilità nell'app contenente il fornitore di contenuti che corrisponde alle URI. L'app che contiene il fornitore di contenuti potrebbe essere diversa dall'app che invia l'intent.

Il seguente snippet di codice mostra come aggiungere un flag di intent delle autorizzazioni URI in modo che un'altra app destinata ad Android 11 o versioni successive possa visualizzare i dati nell'URI dei contenuti:

Kotlin

val shareIntent = Intent(Intent.ACTION_VIEW).apply {
    flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
    data = CONTENT_URI_TO_SHARE_WITH_OTHER_APP
}

Java

Intent shareIntent = new Intent(Intent.ACTION_VIEW);
shareIntent.setFlags(FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.setData(CONTENT_URI_TO_SHARE_WITH_OTHER_APP);

Connettiti ai servizi

Se la tua app deve interagire con un servizio non visibile automaticamente, puoi dichiarare l'azione per intent appropriata all'interno di un elemento <queries>. Le seguenti sezioni fornire esempi sull'uso dei servizi a cui si accede comunemente.

Connettiti a un motore di sintesi vocale

Se la tua app interagisce con un motore di sintesi vocale, includi quanto segue. Elemento <intent> come parte dell'elemento <queries> nel tuo manifest:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.TTS_SERVICE" />
</intent>

Connettersi a un servizio di riconoscimento vocale

Se la tua app interagisce con un servizio di riconoscimento vocale, includi quanto segue Elemento <intent> come parte dell'elemento <queries> nel tuo manifest:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.speech.RecognitionService" />
</intent>

Connettersi a servizi di browser multimediali

Se la tua app è un browser multimediale client app, includi il seguente elemento <intent> come parte dell'elemento <queries> in manifest:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.media.browse.MediaBrowserService" />
</intent>

Fornire funzionalità personalizzate

Se la tua app deve eseguire azioni personalizzabili o mostrare contenuti di dati in base alle sue interazioni con altre app, puoi rappresentare comportamento personalizzato utilizzando il filtro di intent firme come dell'elemento <queries> nel tuo file manifest. Le sezioni seguenti forniscono indicazioni dettagliate per diversi scenari comuni.

Query per le app SMS

Se la tua app ha bisogno di informazioni sul gruppo di app per SMS installate su un dispositivo, ad esempio per controllare quale app è il gestore di SMS predefinito del dispositivo, includi il seguente elemento <intent> come parte dell'elemento <queries> in il tuo manifest:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.SENDTO"/>
  <data android:scheme="smsto" android:host="*" />
</intent>

Creare una scheda di condivisione personalizzata

Se possibile, utilizza un modello fornito dal sistema Sharesheet. In alternativa, includi il seguente elemento <intent> come parte dell'elemento <queries> in il tuo manifest:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.SEND" />
  <!-- Replace with the MIME type that your app works with, if needed. -->
  <data android:mimeType="image/jpeg" />
</intent>

Il processo di creazione di Sharesheet nella logica della tua app, ad esempio la chiamata a queryIntentActivities(), altrimenti rimane invariato rispetto a versioni precedenti di Android 11.

Mostra azioni di selezione del testo personalizzate

Quando gli utenti selezionano del testo nella tua app, una barra degli strumenti per la selezione del testo mostra l'insieme di operazioni possibili da eseguire sul testo selezionato. Se questa barra degli strumenti mostra azioni personalizzate di altre app, includi il seguente elemento <intent> nell'elemento <queries> nel manifest:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.PROCESS_TEXT" />
  <data android:mimeType="text/plain" />
</intent>

Mostra righe di dati personalizzate per un contatto

Le app possono aggiungere righe di dati personalizzati al fornitore di contatti. Affinché un'app Contatti possa mostrare questi dati personalizzati, deve essere in grado di:

  1. Leggi il file contacts.xml dalle altre app.
  2. Carica un'icona corrispondente al tipo MIME personalizzato.

Se la tua app è un'app per i contatti, includi i seguenti elementi <intent> come parte dell'elemento <queries> nel tuo manifest:

<!-- Place inside the <queries> element. -->
<!-- Lets the app read the contacts.xml file from other apps. -->
<intent>
  <action android:name="android.accounts.AccountAuthenticator" />
</intent>
<!-- Lets the app load an icon corresponding to the custom MIME type. -->
<intent>
  <action android:name="android.intent.action.VIEW" />
  <data android:scheme="content" android:host="com.android.contacts"
        android:mimeType="vnd.android.cursor.item/*" />
</intent>