Häufige Anwendungsfälle bei eingeschränkter Paketsichtbarkeit erfüllen

In diesem Dokument werden mehrere häufige Anwendungsfälle vorgestellt, in denen eine Anwendung mit anderen Anwendungen interagiert. Jeder Abschnitt enthält Anleitungen dazu, wie du die Funktionen der App mit eingeschränkter Paketsichtbarkeit erreichen kannst. Dies musst du berücksichtigen, wenn deine App auf Android 11 (API-Level 30) oder höher ausgerichtet ist.

Wenn eine App, die auf Android 11 oder höher ausgerichtet ist, einen Intent verwendet, um eine Aktivität in einer anderen App zu starten, ist es am einfachsten, den Intent aufzurufen und die Ausnahme ActivityNotFoundException zu verarbeiten, wenn keine App verfügbar ist.

Wenn ein Teil deiner App davon abhängt, ob der Aufruf von startActivity() erfolgreich sein kann, z. B. beim Anzeigen einer UI, füge dem <queries>-Element des App-Manifests ein Element hinzu. In der Regel ist dies ein <intent>-Element.

URLs öffnen

In diesem Abschnitt werden verschiedene Möglichkeiten zum Öffnen von URLs in einer App beschrieben, die auf Android 11 oder höher ausgerichtet ist.

URLs in einem Browser oder einer anderen App öffnen

Verwenden Sie zum Öffnen einer URL einen Intent, der die Intent-Aktion ACTION_VIEW enthält, wie in der Anleitung zum Laden einer Web-URL beschrieben. Nachdem Sie startActivity() mit diesem Intent aufgerufen haben, geschieht Folgendes:

  • Die URL wird in einer Webbrowser-App geöffnet.
  • Die URL wird in einer App geöffnet, die sie als Deeplink unterstützt.
  • Ein Dialogfeld wird angezeigt, in dem der Nutzer auswählen kann, welche Anwendung die URL öffnet.
  • Ein ActivityNotFoundException tritt auf, weil auf dem Gerät keine App installiert ist, die die URL öffnen kann. (Dies ist ungewöhnlich.)

    Es wird empfohlen, die ActivityNotFoundException in Ihrer App abzufangen und zu verarbeiten, wenn dies auftritt.

Da für die Methode startActivity() keine Paketsichtbarkeit erforderlich ist, um die Aktivität einer anderen Anwendung zu starten, müssen Sie dem Manifest Ihrer App kein <queries>-Element hinzufügen und keine Änderungen an einem vorhandenen <queries>-Element vornehmen. Dies gilt sowohl für implizite als auch für explizite Intents, die eine URL öffnen.

Verfügbarkeit eines Browsers prüfen

In einigen Fällen möchte Ihre Anwendung vor dem Öffnen einer URL prüfen, ob mindestens ein Browser auf dem Gerät verfügbar ist oder ob ein bestimmter Browser der Standardbrowser ist. Füge in diesen Fällen das folgende <intent>-Element als Teil des <queries>-Elements in dein Manifest ein:

<!-- 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>

Wenn Sie queryIntentActivities() aufrufen und einen Web-Intent als Argument übergeben, enthält die zurückgegebene Liste in einigen Fällen die verfügbaren Browseranwendungen. Die Liste enthält keine Browseranwendungen, wenn der Nutzer die URL so konfiguriert hat, dass sie standardmäßig in einer nicht browsergestützten Anwendung geöffnet wird.

URLs in benutzerdefinierten Tabs öffnen

Mit benutzerdefinierten Tabs lässt sich das Erscheinungsbild einer App an das Erscheinungsbild des Browsers anpassen. Sie können eine URL auf einem benutzerdefinierten Tab öffnen, ohne das Element <queries> im App-Manifest hinzufügen oder ändern zu müssen.

Sie können jedoch überprüfen, ob das Gerät einen Browser hat, der benutzerdefinierte Tabs unterstützt, oder mit CustomTabsClient.getPackageName() einen bestimmten Browser auswählen, der mit benutzerdefinierten Tabs gestartet werden soll. Füge in diesen Fällen das folgende <intent>-Element als Teil des <queries>-Elements in dein Manifest ein:

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

URLs von nicht browsergestützten Apps verarbeiten lassen

Auch wenn Ihre Anwendung URLs über benutzerdefinierte Tabs öffnen kann, sollten Sie nach Möglichkeit URLs von einer nicht browsergestützten App öffnen lassen. Um diese Funktion in Ihrer App bereitzustellen, rufen Sie startActivity() mit einem Intent auf, der das Intent-Flag FLAG_ACTIVITY_REQUIRE_NON_BROWSER festlegt. Wenn das System einen ActivityNotFoundException ausgibt, kann Ihre App die URL dann in einem benutzerdefinierten Tab öffnen.

Wenn ein Intent dieses Flag enthält, führt ein Aufruf von startActivity() dazu, dass unter einer der folgenden Bedingungen ein ActivityNotFoundException ausgelöst wird:

  • Der Anruf hätte direkt eine Browser-App gestartet.
  • Der Aufruf hätte dem Nutzer ein Dialogfeld zur Auswahl angezeigt, in dem die einzigen Optionen für Browser-Apps sind.

Das folgende Code-Snippet zeigt, wie Sie Ihre Logik für die Verwendung des Intent-Flags FLAG_ACTIVITY_REQUIRE_NON_BROWSER aktualisieren:

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);
}

Nachfragen vermeiden

Wenn Sie nicht möchten, dass das Dialogfeld angezeigt wird, das Nutzer beim Öffnen einer URL sehen, und die URL in diesen Situationen lieber selbst verarbeiten möchten, können Sie einen Intent verwenden, der das Intent-Flag FLAG_ACTIVITY_REQUIRE_DEFAULT festlegt.

Wenn ein Intent dieses Flag enthält, führt ein Aufruf von startActivity() dazu, dass ein ActivityNotFoundException ausgelöst wird, wenn der Aufruf für den Nutzer ein Auswahldialogfeld eingeblendet hätte.

Wenn ein Intent sowohl dieses Flag als auch das Intent-Flag FLAG_ACTIVITY_REQUIRE_NON_BROWSER enthält, führt ein Aufruf von startActivity() dazu, dass ein ActivityNotFoundException ausgelöst wird, wenn eine der folgenden Bedingungen eintritt:

  • Der Anruf hätte die Browser-App direkt gestartet.
  • Beim Anruf hätte dem Nutzer ein Dialogfeld zur Auswahl angezeigt.

Das folgende Code-Snippet zeigt, wie die Flags FLAG_ACTIVITY_REQUIRE_NON_BROWSER und FLAG_ACTIVITY_REQUIRE_DEFAULT zusammen verwendet werden:

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);
}

Datei öffnen

Wenn Ihre App Dateien oder Anhänge verarbeitet und beispielsweise prüft, ob ein Gerät eine bestimmte Datei öffnen kann, ist es in der Regel am einfachsten, eine Aktivität zu starten, die die Datei verarbeiten kann. Verwenden Sie dazu einen Intent, der die Intent-Aktion ACTION_VIEW und den URI für die jeweilige Datei enthält. Wenn auf dem Gerät keine App verfügbar ist, kann sie das ActivityNotFoundException abfangen. In der Logik zur Verarbeitung von Ausnahmen können Sie entweder einen Fehler anzeigen oder versuchen, die Datei selbst zu verarbeiten.

Wenn deine App vorab wissen muss, ob eine bestimmte Datei von einer anderen App geöffnet werden kann, füge das <intent>-Element in das folgende Code-Snippet als Teil des <queries>-Elements in deinem Manifest ein. Geben Sie den Dateityp an, wenn Sie bereits wissen, was es zum Zeitpunkt der Kompilierung ist.

<!-- 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>

Anschließend können Sie prüfen, ob eine App verfügbar ist. Dazu rufen Sie resolveActivity() mit Ihrem Intent auf.

URI-Zugriff gewähren

Hinweis:Die Deklarierung von URI-Zugriffsberechtigungen wie in diesem Abschnitt beschrieben ist für Apps erforderlich, die auf Android 11 (API-Level 30) oder höher ausgerichtet sind. Sie wird für alle Apps empfohlen, unabhängig von der SDK-Zielversion und davon, ob sie ihre Contentanbieter exportieren.

Für Apps, die auf Android 11 oder höher ausgerichtet sind und auf den Inhalts-URI zugreifen möchten, müssen im Intent Ihrer App URI-Zugriffsberechtigungen deklariert werden. Dazu müssen Sie eines oder beide der folgenden Intent-Flags festlegen: FLAG_GRANT_READ_URI_PERMISSION und FLAG_GRANT_WRITE_URI_PERMISSION.

Unter Android 11 und höher stellen die URI-Zugriffsberechtigungen der App, die den Intent empfängt, die folgenden Funktionen bereit:

  • Aus den Daten lesen oder in diese schreiben, die der Inhalts-URI darstellt, je nach den gegebenen URI-Berechtigungen.
  • Sehen Sie sich die App an, die den Contentanbieter enthält, der der URI-Befugnis entspricht. Die App, die den Contentanbieter enthält, kann sich von der App unterscheiden, die den Intent sendet.

Im folgenden Code-Snippet wird gezeigt, wie ein URI-Berechtigungs-Intent-Flag hinzugefügt wird, damit eine andere App, die auf Android 11 oder höher ausgerichtet ist, die Daten im Inhalts-URI ansehen kann:

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);

Verbindung zu Diensten herstellen

Wenn Ihre App mit einem Dienst interagieren muss, der nicht automatisch sichtbar ist, können Sie die entsprechende Intent-Aktion mit einem <queries>-Element deklarieren. Die folgenden Abschnitte enthalten Beispiele für häufig aufgerufene Dienste.

Mit einer Text-in-Sprache-Engine verbinden

Wenn deine App mit einer Sprachausgabe-Engine interagiert, füge das folgende <intent>-Element als Teil des <queries>-Elements in dein Manifest ein:

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

Verbindung zu einem Spracherkennungsdienst herstellen

Wenn deine App mit einem Spracherkennungsdienst interagiert, füge das folgende <intent>-Element als Teil des <queries>-Elements in dein Manifest ein:

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

Verbindung zu Medienbrowserdiensten herstellen

Wenn deine App eine Client-Medienbrowser-App ist, füge deinem Manifest das folgende <intent>-Element als Teil des <queries>-Elements hinzu:

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

Benutzerdefinierte Funktionen bereitstellen

Wenn Ihre App anpassbare Aktionen ausführen oder auf Grundlage der Interaktionen mit anderen Apps anpassbare Informationen anzeigen muss, können Sie dieses benutzerdefinierte Verhalten mithilfe von Intent-Filtersignaturen als Teil des <queries>-Elements in Ihrem Manifest darstellen. Die folgenden Abschnitte enthalten detaillierte Anleitungen für mehrere gängige Szenarien.

Abfrage für SMS-Apps

Wenn Ihre App Informationen zu den auf einem Gerät installierten SMS-Apps benötigt, z. B. um zu prüfen, welche App der Standard-SMS-Handler des Geräts ist, fügen Sie das folgende <intent>-Element als Teil des <queries>-Elements in Ihr Manifest ein:

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

Benutzerdefiniertes Sharesheet erstellen

Verwenden Sie nach Möglichkeit ein vom System bereitgestelltes Sharesheet. Alternativ kannst du das folgende <intent>-Element als Teil des <queries>-Elements in dein Manifest einfügen:

<!-- 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>

Ansonsten bleibt die Erstellung des Sharesheet in der Logik deiner App, z. B. der Aufruf von queryIntentActivities(), im Vergleich zu Android-Versionen vor Android 11 unverändert.

Benutzerdefinierte Aktionen für die Textauswahl anzeigen

Wenn Nutzer Text in Ihrer App auswählen, wird in einer Symbolleiste für die Textauswahl die Reihe der möglichen Vorgänge angezeigt, die für den ausgewählten Text ausgeführt werden können. Wenn in dieser Symbolleiste benutzerdefinierte Aktionen aus anderen Apps angezeigt werden, füge das folgende <intent>-Element als Teil des <queries>-Elements in deinem Manifest ein:

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

Benutzerdefinierte Datenzeilen für einen Kontakt anzeigen

Anwendungen können dem Contacts Provider benutzerdefinierte Datenzeilen hinzufügen. Damit diese benutzerdefinierten Daten in einer Kontakt-App angezeigt werden können, muss sie Folgendes tun können:

  1. Die Datei contacts.xml aus den anderen Apps lesen.
  2. Lädt ein Symbol entsprechend dem benutzerdefinierten MIME-Typ.

Wenn deine App eine Kontakt-App ist, füge die folgenden <intent>-Elemente als Teil des <queries>-Elements in dein Manifest ein:

<!-- 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>