Einbetten von Aktivitäten

Durch das Einbetten von Aktivitäten werden Apps auf Geräten mit großem Display optimiert, indem das Aufgabenfenster einer Anwendung zwischen zwei Aktivitäten oder zwei Instanzen derselben Aktivität aufgeteilt wird.

Abbildung 1. Einstellungen-App mit nebeneinander angezeigten Aktivitäten

Wenn Ihre App aus mehreren Aktivitäten besteht, können Sie mithilfe von eingebetteten Aktivitäten die Nutzerfreundlichkeit auf Tablets, faltbaren Geräten und ChromeOS-Geräten verbessern.

Für das Einbetten von Aktivitäten ist kein Code-Refactoring erforderlich. Sie können festlegen, wie die Aktivitäten in Ihrer App angezeigt werden – nebeneinander oder gestapelt –, indem Sie eine XML-Konfigurationsdatei erstellen oder Jetpack WindowManager API-Aufrufe ausführen.

Die Unterstützung für kleine Bildschirme wird automatisch beibehalten. Wenn Ihre App auf einem Gerät mit kleinem Bildschirm ausgeführt wird, werden Aktivitäten übereinander gestapelt. Auf großen Bildschirmen werden Aktivitäten nebeneinander angezeigt. Das System bestimmt die Präsentation anhand der von Ihnen erstellten Konfiguration. Eine Verzweigungslogik ist nicht erforderlich.

Die Einbettung von Aktivitäten berücksichtigt Änderungen der Geräteausrichtung und funktioniert nahtlos auf faltbaren Geräten. Aktivitäten werden beim Zusammen- und Aufklappen des Geräts gestapelt und wieder entfernt.

Die Einbettung von Aktivitäten wird auf den meisten Geräten mit großem Display und Android 12L (API-Ebene 32) und höher unterstützt.

Fenster für die Aufgabenaufteilung

Beim Einbetten von Aktivitäten wird das App-Aufgabenfenster in zwei Container unterteilt: einen primären und einen sekundären. Die Container enthalten Aktivitäten, die über die Hauptaktivität oder über andere Aktivitäten gestartet wurden, die sich bereits in den Containern befinden.

Aktivitäten werden beim Starten im sekundären Container gestapelt. Auf kleinen Bildschirmen wird der sekundäre Container auf dem primären Container gestapelt. So entsprechen das Stapeln von Aktivitäten und die Rücknavigation der Reihenfolge der Aktivitäten, die bereits in Ihrer App implementiert sind.

Mithilfe von eingebetteten Aktivitäten können Sie Aktivitäten auf unterschiedliche Weise präsentieren. Ihre App kann das Aufgabenfenster teilen, indem zwei Aktivitäten gleichzeitig nebeneinander gestartet werden:

Abbildung 2. Zwei Aktivitäten nebeneinander.

Sie können auch eine neue Aktivität neben einer Aktivität starten, die das gesamte Aufgabenfenster belegt, um eine Aufteilung zu erstellen:

Abbildung 3. Aktivität A startet Aktivität B seitlich.

Aktivitäten, die sich bereits in einem Split befinden und ein Aufgabenfenster teilen, können auf folgende Weise andere Aktivitäten starten:

  • Seitlich über einer anderen Aktivität:

    Abbildung 4: Aktivität A startet Aktivität C seitlich über Aktivität B.
  • Sie können die Aufteilung auch seitlich verschieben, sodass die vorherige primäre Aktivität ausgeblendet wird:

    Abbildung 5: Aktivität B startet Aktivität C seitlich und verschiebt die Aufteilung seitlich.
  • Starten Sie eine Aktivität an derselben Stelle, also im selben Aktivitätsstapel:

    Abbildung 6: Aktivität B startet Aktivität C ohne zusätzliche Intent-Flags.
  • Vollständiges Fenster für eine Aktivität in derselben Aufgabe öffnen:

    Abbildung 7: Aktivität A oder Aktivität B startet Aktivität C, die das Aufgabenfenster füllt.

Rückwärtsnavigation

Je nach Abhängigkeiten zwischen Aktivitäten oder wie Nutzer das Zurück-Ereignis auslösen, können verschiedene Arten von Anwendungen unterschiedliche Regeln für die Rücknavigation im Splitscreen-Fensterstatus haben, z. B.:

  • Zusammen: Wenn Aktivitäten zusammenhängen und eine nicht ohne die andere angezeigt werden soll, kann die Rücknavigation so konfiguriert werden, dass beide abgeschlossen werden.
  • Eigenständig: Wenn Aktivitäten vollständig unabhängig sind, wirkt sich die Rücknavigation bei einer Aktivität nicht auf den Status einer anderen Aktivität im Aufgabenfenster aus.

Das Zurück-Ereignis wird an die zuletzt fokussierte Aktivität gesendet, wenn die Navigation über Schaltflächen verwendet wird.

Für die Bedienung über Gesten:

  • Android 14 (API-Level 34) und niedriger: Das Zurück-Ereignis wird an die Aktivität gesendet, bei der die Geste ausgeführt wurde. Wenn Nutzer von der linken Seite des Bildschirms wischen, wird das Zurück-Ereignis an die Aktivität im linken Bereich des geteilten Fensters gesendet. Wenn Nutzer von der rechten Seite des Bildschirms wischen, wird das Zurück-Ereignis an die Aktivität im rechten Bereich gesendet.

  • Android 15 (API-Level 35) oder höher

    • Wenn Sie mehrere Aktivitäten aus derselben App ausführen, wird mit der Geste unabhängig von der Wischrichtung die oberste Aktivität beendet. Das sorgt für eine einheitlichere Bedienung.

    • In Szenarien mit zwei Aktivitäten aus verschiedenen Apps (Overlay) wird das Zurück-Ereignis auf die zuletzt im Fokus befindliche Aktivität gerichtet, was dem Verhalten der Schaltflächennavigation entspricht.

Layout mit mehreren Ansichten

Mit Jetpack WindowManager können Sie eine Aktivität mit einem mehrflügeligen Layout auf Geräten mit großem Bildschirm und Android 12L (API-Ebene 32) oder höher sowie auf einigen Geräten mit früheren Plattformversionen erstellen. Vorhandene Apps, die auf mehreren Aktivitäten statt auf Fragmenten oder ansichtenbasierten Layouts wie SlidingPaneLayout basieren, können eine verbesserte Nutzererfahrung auf großen Bildschirmen bieten, ohne den Quellcode umzustrukturieren.

Ein häufiges Beispiel ist die Aufteilung in Listen- und Detailelemente. Um eine qualitativ hochwertige Präsentation zu gewährleisten, startet das System die Listenaktivität und die Anwendung startet dann sofort die Detailaktivität. Das Übergangssystem wartet, bis beide Aktivitäten gezeichnet wurden, und zeigt sie dann zusammen an. Für den Nutzer werden die beiden Aktivitäten als eine einzige gestartet.

Abbildung 8: Zwei Aktivitäten wurden gleichzeitig in einem Layout mit mehreren Ansichten gestartet.

Aufgeteilte Attribute

Sie können festlegen, wie das Aufgabenfenster zwischen den aufgeteilten Containern verteilt wird und wie die Container relativ zueinander angeordnet werden.

Legen Sie für Regeln, die in einer XML-Konfigurationsdatei definiert sind, die folgenden Attribute fest:

  • splitRatio: Damit werden die Proportionen des Containers festgelegt. Der Wert ist eine Gleitkommazahl im offenen Intervall (0,0, 1,0).
  • splitLayoutDirection: Gibt an, wie die geteilten Container relativ zueinander angeordnet werden. Zu den Werten gehören:
    • ltr: Von links nach rechts
    • rtl: Von rechts nach links
    • locale: Entweder ltr oder rtl wird anhand der Gebietsschemaeinstellung bestimmt.

Beispiele finden Sie im Abschnitt XML-Konfiguration.

Erstellen Sie für Regeln, die mit den WindowManager APIs erstellt wurden, ein SplitAttributes-Objekt mit SplitAttributes.Builder und rufen Sie die folgenden Buildermethoden auf:

Beispiele finden Sie im Abschnitt WindowManager API.

Abbildung 9: Zwei Aktivitätsaufteilungen, die von links nach rechts angeordnet sind, aber unterschiedliche Aufteilungsverhältnisse haben.

Platzhalter

Platzhalteraktivitäten sind leere sekundäre Aktivitäten, die einen Bereich einer Aktivitätsaufteilung belegen. Sie sollen letztendlich durch eine andere Aktivität ersetzt werden, die Inhalte enthält. Beispielsweise könnte eine Platzhalteraktivität die sekundäre Seite einer Aktivität in einem Listendetaillayout belegen, bis ein Element aus der Liste ausgewählt wird. In diesem Fall wird der Platzhalter durch eine Aktivität mit den Detailinformationen für das ausgewählte Listenelement ersetzt.

Standardmäßig zeigt das System Platzhalter nur an, wenn genügend Platz für eine Aktivitätsaufteilung vorhanden ist. Platzhalter werden automatisch beendet, wenn die Anzeigegröße eine Breite oder Höhe erreicht, die zu klein ist, um einen Split anzuzeigen. Wenn der Platz ausreicht, startet das System den Platzhalter mit einem zurückgesetzten Status neu.

Abbildung 10: Faltbares Gerät wird zusammengeklappt und aufgeklappt. Die Platzhalteraktivität wird beendet und bei einer Änderung der Displaygröße neu erstellt.

Das stickyPlaceholder-Attribut einer SplitPlaceholderRule- oder setSticky()-Methode von SplitPlaceholder.Builder kann das Standardverhalten jedoch überschreiben. Wenn für das Attribut oder die Methode der Wert true angegeben ist, zeigt das System den Platzhalter als oberste Aktivität im Aufgabenfenster an, wenn das Display von einem zweispaltigen zu einem einspaltigen Display minimiert wird (siehe Split-Konfiguration).

Abbildung 11. Faltbares Gerät wird zusammengeklappt und aufgeklappt. Die Platzhalteraktivität ist fixiert.

Fenstergrößenänderungen

Wenn sich die Gerätekonfiguration ändert und die Breite des Aufgabenfensters so reduziert wird, dass es nicht groß genug für ein Layout mit mehreren Ansichten ist (z. B. wenn ein faltbares Gerät mit großem Bildschirm von der Größe eines Tablets auf die Größe eines Smartphones zusammengefaltet wird oder das App-Fenster im Mehrfenstermodus neu skaliert wird), werden die Aktivitäten, die keine Platzhalter sind, im sekundären Bereich des Aufgabenfensters über den Aktivitäten im primären Bereich gestapelt.

Platzhalteraktivitäten werden nur angezeigt, wenn die Displaybreite für eine Aufteilung ausreicht. Auf kleineren Bildschirmen wird der Platzhalter automatisch geschlossen. Sobald der Anzeigebereich wieder groß genug ist, wird der Platzhalter neu erstellt. Weitere Informationen finden Sie im Abschnitt Platzhalter.

Das Stapeln von Aktivitäten ist möglich, weil WindowManager die Aktivitäten im sekundären Bereich in Z-Reihenfolge über den Aktivitäten im primären Bereich anordnet.

Mehrere Aktivitäten im sekundären Bereich

Aktivität B startet Aktivität C ohne zusätzliche Intent-Flags:

Aktivitätsaufteilung mit den Aktivitäten A, B und C, wobei C über B gestapelt ist.

Dies führt zu der folgenden Z-Reihenfolge der Aktivitäten in derselben Aufgabe:

Sekundärer Aktivitätsstapel mit Aktivität C, die auf Aktivität B gestapelt ist.
          Der sekundäre Stapel wird auf dem primären Aktivitätsstapel mit Aktivität A gestapelt.

In einem kleineren Aufgabenfenster wird die Anwendung also auf eine einzelne Aktivität mit C oben im Stack reduziert:

Kleines Fenster, in dem nur Aktivität C angezeigt wird

Wenn Sie im kleineren Fenster zurückgehen, wechseln Sie zwischen den übereinander liegenden Aktivitäten.

Wenn die Konfiguration des Aufgabenfensters wieder auf eine Größe zurückgesetzt wird, die mehrere Bereiche aufnehmen kann, werden die Aktivitäten wieder nebeneinander angezeigt.

Gestapelte Aufteilungen

Aktivität B startet Aktivität C seitlich und verschiebt die Aufteilung seitlich:

Aufgabenfenster mit den Aktivitäten A und B, dann mit den Aktivitäten B und C

Das Ergebnis ist die folgende Z-Reihenfolge der Aktivitäten in derselben Aufgabe:

Aktivitäten A, B und C in einem einzigen Stack Die Aktivitäten werden von oben nach unten in der folgenden Reihenfolge gestapelt: C, B, A.

In einem kleineren Aufgabenfenster wird die Anwendung auf eine einzelne Aktivität mit C oben reduziert:

Kleines Fenster, in dem nur Aktivität C angezeigt wird

Festes Hochformat

Mit der Manifesteinstellung android:screenOrientation können Apps Aktivitäten auf das Hoch- oder Querformat beschränken. Um die Nutzerfreundlichkeit auf Geräten mit großen Bildschirmen wie Tablets und faltbaren Smartphones zu verbessern, können Gerätehersteller (OEMs) Anfragen zur Bildschirmausrichtung ignorieren und die App im Hochformat auf Querformat-Displays oder im Querformat auf Hochformat-Displays im Letterbox-Format anzeigen.

Abbildung 12. Aktivitäten im Letterbox-Format: festes Hochformat auf einem Gerät im Querformat (links), festes Querformat auf einem Gerät im Hochformat (rechts)

Wenn die Aktivitäts-Embedding-Funktion aktiviert ist, können OEMs Geräte so anpassen, dass Aktivitäten im Querformat mit Letterbox-Ansicht im Hochformat auf großen Bildschirmen (Breite ≥ 600 dp) angezeigt werden. Wenn eine Aktivität im Hochformat eine zweite Aktivität startet, kann das Gerät die beiden Aktivitäten nebeneinander in einem zweispaltigen Display anzeigen.

Abbildung 13. Bei der Aktivität A im Fix-Hochformat wird die Aktivität B seitlich gestartet.

Fügen Sie der Manifestdatei Ihrer App immer das Attribut android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED hinzu, um Geräte darüber zu informieren, dass Ihre App das Einbetten von Aktivitäten unterstützt (siehe Abschnitt Konfiguration teilen). Auf OEM-angepassten Geräten kann dann festgelegt werden, ob Aktivitäten im festen Hochformat in Letterbox-Format dargestellt werden sollen.

Split-Konfiguration

Mit Split-Regeln können Sie Aktivitätsaufteilungen konfigurieren. Sie definieren Splitscreen-Regeln in einer XML-Konfigurationsdatei oder durch API-Aufrufe der Jetpack-WindowManager API.

In beiden Fällen muss Ihre App auf die WindowManager-Bibliothek zugreifen und das System darüber informieren, dass die App die Einbettung von Aktivitäten implementiert hat.

Unternimm Folgendes:

  1. Fügen Sie der Datei build.gradle auf Modulebene Ihrer App die neueste Abhängigkeit der WindowManager-Bibliothek hinzu, z. B.:

    implementation 'androidx.window:window:1.1.0-beta02'

    Die WindowManager-Bibliothek enthält alle für das Einbetten von Aktivitäten erforderlichen Komponenten.

  2. Informieren Sie das System darüber, dass Ihre App die Einbettung von Aktivitäten implementiert hat.

    Fügen Sie das Attribut android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED dem Element <application> der App-Manifestdatei hinzu und legen Sie den Wert auf „true“ fest, z. B.:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
        <application>
            <property
                android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED"
                android:value="true" />
        </application>
    </manifest>
    

    Ab WindowManager-Release 1.1.0-alpha06 sind Aktivitätseinbettungen deaktiviert, es sei denn, die Property wird dem Manifest hinzugefügt und auf „wahr“ gesetzt.

    Außerdem verwenden Gerätehersteller die Einstellung, um benutzerdefinierte Funktionen für Apps zu aktivieren, die das Einbetten von Aktivitäten unterstützen. So können Geräte beispielsweise eine nur im Hochformat verfügbare Aktivität auf einem Querformat-Display im Letterbox-Format anzeigen, um die Aktivität für den Übergang zu einem Zwei-Spalten-Layout zu orientieren, wenn eine zweite Aktivität gestartet wird (siehe Fixierte Hochformatausrichtung).

XML-Konfiguration

So erstellst du eine XML-basierte Implementierung der Aktivitäts-Embedding-Funktion:

  1. Erstellen Sie eine XML-Ressourcendatei, die Folgendes tut:

    • Definiert Aktivitäten, die eine gemeinsame Aufteilung haben
    • Konfiguriert die Optionen für die Aufteilung
    • Erstellt einen Platzhalter für den sekundären Container der Aufteilung, wenn keine Inhalte verfügbar sind.
    • Gibt Aktivitäten an, die niemals Teil einer Aufteilung sein sollten

    Beispiel:

    <!-- main_split_config.xml -->
    
    <resources
        xmlns:window="http://schemas.android.com/apk/res-auto">
    
        <!-- Define a split for the named activities. -->
        <SplitPairRule
            window:splitRatio="0.33"
            window:splitLayoutDirection="locale"
            window:splitMinWidthDp="840"
            window:splitMaxAspectRatioInPortrait="alwaysAllow"
            window:finishPrimaryWithSecondary="never"
            window:finishSecondaryWithPrimary="always"
            window:clearTop="false">
            <SplitPairFilter
                window:primaryActivityName=".ListActivity"
                window:secondaryActivityName=".DetailActivity"/>
        </SplitPairRule>
    
        <!-- Specify a placeholder for the secondary container when content is
             not available. -->
        <SplitPlaceholderRule
            window:placeholderActivityName=".PlaceholderActivity"
            window:splitRatio="0.33"
            window:splitLayoutDirection="locale"
            window:splitMinWidthDp="840"
            window:splitMaxAspectRatioInPortrait="alwaysAllow"
            window:stickyPlaceholder="false">
            <ActivityFilter
                window:activityName=".ListActivity"/>
        </SplitPlaceholderRule>
    
        <!-- Define activities that should never be part of a split. Note: Takes
             precedence over other split rules for the activity named in the
             rule. -->
        <ActivityRule
            window:alwaysExpand="true">
            <ActivityFilter
                window:activityName=".ExpandedActivity"/>
        </ActivityRule>
    
    </resources>
    
  2. Erstellen Sie einen Initialisierer.

    Die Komponente „WindowManager“ RuleController analysiert die XML-Konfigurationsdatei und stellt die Regeln dem System zur Verfügung. Eine Jetpack-Start-Bibliothek Initializer stellt die XML-Datei beim Starten der App für RuleController zur Verfügung, damit die Regeln beim Starten von Aktivitäten in Kraft treten.

    So erstellen Sie einen Initiierer:

    1. Fügen Sie der Datei build.gradle auf Modulebene die neueste Abhängigkeit der Jetpack-Starter-Bibliothek hinzu, z. B.:

      implementation 'androidx.startup:startup-runtime:1.1.1'

    2. Erstellen Sie eine Klasse, die die Initializer-Schnittstelle implementiert.

      Der Initialisierer stellt die Split-Regeln für RuleController zur Verfügung, indem er die ID der XML-Konfigurationsdatei (main_split_config.xml) an die RuleController.parseRules()-Methode übergibt.

      Kotlin

      class SplitInitializer : Initializer<RuleController> {
      
          override fun create(context: Context): RuleController {
              return RuleController.getInstance(context).apply {
                  setRules(RuleController.parseRules(context, R.xml.main_split_config))
              }
          }
      
          override fun dependencies(): List<Class<out Initializer<*>>> {
              return emptyList()
          }
      }

      Java

      public class SplitInitializer implements Initializer<RuleController> {
      
           @NonNull
           @Override
           public RuleController create(@NonNull Context context) {
               RuleController ruleController = RuleController.getInstance(context);
               ruleController.setRules(
                   RuleController.parseRules(context, R.xml.main_split_config)
               );
               return ruleController;
           }
      
           @NonNull
           @Override
           public List<Class<? extends Initializer<?>>> dependencies() {
               return Collections.emptyList();
           }
      }
  3. Erstellen Sie einen Contentanbieter für die Regeldefinitionen.

    Fügen Sie androidx.startup.InitializationProvider als <provider> Ihrer App-Manifestdatei hinzu. Fügen Sie einen Verweis auf die Implementierung des RuleController-Initialisierers SplitInitializer ein:

    <!-- AndroidManifest.xml -->
    
    <provider android:name="androidx.startup.InitializationProvider"
        android:authorities="${applicationId}.androidx-startup"
        android:exported="false"
        tools:node="merge">
        <!-- Make SplitInitializer discoverable by InitializationProvider. -->
        <meta-data android:name="${applicationId}.SplitInitializer"
            android:value="androidx.startup" />
    </provider>
    

    InitializationProvider erkennt und initialisiert SplitInitializer, bevor die Methode onCreate() der App aufgerufen wird. Daher werden die Split-Regeln angewendet, wenn die Hauptaktivität der App gestartet wird.

WindowManager API

Sie können das Einbetten von Aktivitäten mit wenigen API-Aufrufen programmgesteuert implementieren. Führen Sie die Aufrufe in der onCreate()-Methode einer Unterklasse von Application aus, damit die Regeln in Kraft sind, bevor Aktivitäten gestartet werden.

So erstellen Sie programmatisch eine Aktivitätsaufteilung:

  1. So erstellen Sie eine Split-Regel:

    1. Erstellen Sie eine SplitPairFilter, mit der die Aktivitäten angegeben werden, die die Aufteilung teilen:

      Kotlin

      val splitPairFilter = SplitPairFilter(
         ComponentName(this, ListActivity::class.java),
         ComponentName(this, DetailActivity::class.java),
         null
      )

      Java

      SplitPairFilter splitPairFilter = new SplitPairFilter(
         new ComponentName(this, ListActivity.class),
         new ComponentName(this, DetailActivity.class),
         null
      );
    2. Fügen Sie den Filter einem Filtersatz hinzu:

      Kotlin

      val filterSet = setOf(splitPairFilter)

      Java

      Set<SplitPairFilter> filterSet = new HashSet<>();
      filterSet.add(splitPairFilter);
    3. Erstellen Sie Layoutattribute für die Aufteilung:

      Kotlin

      val splitAttributes: SplitAttributes = SplitAttributes.Builder()
          .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
          .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
          .build()

      Java

      final SplitAttributes splitAttributes = new SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build();

      Mit SplitAttributes.Builder wird ein Objekt mit Layoutattributen erstellt:

      • setSplitType(): Hiermit wird festgelegt, wie der verfügbare Anzeigebereich den einzelnen Aktivitätscontainern zugewiesen wird. Mit dem Verhältnisstyp wird der Anteil des verfügbaren Anzeigebereichs angegeben, der dem primären Container zugewiesen ist. Der sekundäre Container nimmt den verbleibenden Teil des verfügbaren Anzeigebereichs ein.
      • setLayoutDirection(): Gibt an, wie die Aktivitätscontainer relativ zueinander angeordnet werden, zuerst der primäre Container.
    4. SplitPairRule erstellen:

      Kotlin

      val splitPairRule = SplitPairRule.Builder(filterSet)
          .setDefaultSplitAttributes(splitAttributes)
          .setMinWidthDp(840)
          .setMinSmallestWidthDp(600)
          .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
          .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
          .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
          .setClearTop(false)
          .build()

      Java

      SplitPairRule splitPairRule = new SplitPairRule.Builder(filterSet)
          .setDefaultSplitAttributes(splitAttributes)
          .setMinWidthDp(840)
          .setMinSmallestWidthDp(600)
          .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
          .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
          .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
          .setClearTop(false)
          .build();

      SplitPairRule.Builder erstellt und konfiguriert die Regel:

      • filterSet: Enthält Split-Paar-Filter, mit denen bestimmt wird, wann die Regel angewendet wird. Dazu werden Aktivitäten mit derselben Aufteilung identifiziert.
      • setDefaultSplitAttributes(): Hiermit werden Layoutattribute auf die Regel angewendet.
      • setMinWidthDp(): Hiermit wird die Mindestbreite des Displays (in dichteunabhängigen Pixeln, dp) festgelegt, die eine Aufteilung ermöglicht.
      • setMinSmallestWidthDp(): Legt den Mindestwert (in dp) fest, den die kleinere der beiden Displayabmessungen haben muss, um eine Aufteilung unabhängig von der Geräteausrichtung zu ermöglichen.
      • setMaxAspectRatioInPortrait(): Legt das maximale Seitenverhältnis (Höhe:Breite) in Hochformat fest, für das Aktivitätsaufschlüsselungen angezeigt werden. Wenn das Seitenverhältnis eines Hochformat-Displays das maximale Seitenverhältnis überschreitet, werden Splitscreens unabhängig von der Breite des Displays deaktiviert. Hinweis:Der Standardwert ist 1,4.Das bedeutet, dass Aktivitäten auf den meisten Tablets im Hochformat das gesamte Aufgabenfenster einnehmen. Weitere Informationen finden Sie unter SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT und setMaxAspectRatioInLandscape(). Der Standardwert für das Querformat ist ALWAYS_ALLOW.
      • setFinishPrimaryWithSecondary(): Hiermit wird festgelegt, wie sich das Abschließen aller Aktivitäten im sekundären Container auf die Aktivitäten im primären Container auswirkt. NEVER gibt an, dass das System die primären Aktivitäten nicht beenden soll, wenn alle Aktivitäten im sekundären Container abgeschlossen sind (siehe Aktivitäten beenden).
      • setFinishSecondaryWithPrimary(): Hiermit wird festgelegt, wie sich das Beenden aller Aktivitäten im primären Container auf die Aktivitäten im sekundären Container auswirkt. ALWAYS gibt an, dass das System die Aktivitäten im sekundären Container immer beenden soll, wenn alle Aktivitäten im primären Container abgeschlossen sind (siehe Aktivitäten beenden).
      • setClearTop(): Gibt an, ob alle Aktivitäten im sekundären Container beendet sind, wenn eine neue Aktivität im Container gestartet wird. Ein false-Wert gibt an, dass neue Aktivitäten über Aktivitäten gestapelt werden, die sich bereits im sekundären Container befinden.
    5. Rufen Sie die Singleton-Instanz des WindowManagers RuleController ab und fügen Sie die Regel hinzu:

      Kotlin

        val ruleController = RuleController.getInstance(this)
        ruleController.addRule(splitPairRule)
        

      Java

        RuleController ruleController = RuleController.getInstance(this);
        ruleController.addRule(splitPairRule);
        
  2. Erstelle einen Platzhalter für den sekundären Container, wenn Inhalte nicht verfügbar sind:

    1. Erstellen Sie eine ActivityFilter, die die Aktivität angibt, mit der der Platzhalter ein Aufgabenfenster teilt:

      Kotlin

      val placeholderActivityFilter = ActivityFilter(
          ComponentName(this, ListActivity::class.java),
          null
      )

      Java

      ActivityFilter placeholderActivityFilter = new ActivityFilter(
          new ComponentName(this, ListActivity.class),
          null
      );
    2. Fügen Sie den Filter einem Filtersatz hinzu:

      Kotlin

      val placeholderActivityFilterSet = setOf(placeholderActivityFilter)

      Java

      Set<ActivityFilter> placeholderActivityFilterSet = new HashSet<>();
      placeholderActivityFilterSet.add(placeholderActivityFilter);
    3. SplitPlaceholderRule erstellen:

      Kotlin

      val splitPlaceholderRule = SplitPlaceholderRule.Builder(
            placeholderActivityFilterSet,
            Intent(context, PlaceholderActivity::class.java)
          ).setDefaultSplitAttributes(splitAttributes)
           .setMinWidthDp(840)
           .setMinSmallestWidthDp(600)
           .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
           .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
           .setSticky(false)
           .build()

      Java

      SplitPlaceholderRule splitPlaceholderRule = new SplitPlaceholderRule.Builder(
            placeholderActivityFilterSet,
            new Intent(context, PlaceholderActivity.class)
          ).setDefaultSplitAttributes(splitAttributes)
           .setMinWidthDp(840)
           .setMinSmallestWidthDp(600)
           .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
           .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
           .setSticky(false)
           .build();

      SplitPlaceholderRule.Builder erstellt und konfiguriert die Regel:

      • placeholderActivityFilterSet: Enthält Aktivitätsfilter, mit denen festgelegt wird, wann die Regel angewendet werden soll. Dazu werden Aktivitäten angegeben, mit denen die Platzhalteraktivität verknüpft ist.
      • Intent: Gibt das Starten der Platzhalteraktivität an.
      • setDefaultSplitAttributes(): Mit diesem Attribut werden Layoutattribute auf die Regel angewendet.
      • setMinWidthDp(): Mit dieser Einstellung wird die Mindestbreite des Displays (in dichteunabhängigen Pixeln, dp) festgelegt, ab der eine Aufteilung möglich ist.
      • setMinSmallestWidthDp(): Mit diesem Attribut wird der Mindestwert (in dp) festgelegt, den die kleinere der beiden Displayabmessungen haben muss, damit eine Aufteilung unabhängig von der Geräteausrichtung möglich ist.
      • setMaxAspectRatioInPortrait(): Mit diesem Attribut wird das maximale Seitenverhältnis (Höhe:Breite) in Hochformat festgelegt, für das Aktivitätsaufschlüsselungen angezeigt werden. Hinweis:Der Standardwert ist 1, 4.Bei diesem Wert füllen Aktivitäten auf den meisten Tablets das Aufgabenfenster in Hochformat aus. Weitere Informationen finden Sie unter SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT und setMaxAspectRatioInLandscape(). Der Standardwert für „Querformat“ ist ALWAYS_ALLOW.
      • setFinishPrimaryWithPlaceholder(): Mit dieser Einstellung legen Sie fest, wie sich das Beenden der Platzhalteraktivität auf die Aktivitäten im primären Container auswirkt. „IMMER“ gibt an, dass das System die Aktivitäten im primären Container immer beenden soll, wenn der Platzhalter abgeschlossen ist (siehe Aktivitäten beenden).
      • setSticky(): Bestimmt, ob die Platzhalteraktivität auf kleinen Displays über dem Aktivitätenstapel angezeigt wird, nachdem der Platzhalter zum ersten Mal in einem Split mit ausreichender Mindestbreite erschienen ist.
    4. Fügen Sie die Regel dem WindowManager RuleController hinzu:

      Kotlin

      ruleController.addRule(splitPlaceholderRule)

      Java

      ruleController.addRule(splitPlaceholderRule);
  3. Geben Sie Aktivitäten an, die niemals Teil einer Aufteilung sein sollten:

    1. Erstellen Sie eine ActivityFilter, die eine Aktivität identifiziert, die immer den gesamten Bereich für die Aufgabenanzeige einnehmen soll:

      Kotlin

      val expandedActivityFilter = ActivityFilter(
        ComponentName(this, ExpandedActivity::class.java),
        null
      )

      Java

      ActivityFilter expandedActivityFilter = new ActivityFilter(
        new ComponentName(this, ExpandedActivity.class),
        null
      );
    2. Fügen Sie den Filter einem Filtersatz hinzu:

      Kotlin

      val expandedActivityFilterSet = setOf(expandedActivityFilter)

      Java

      Set<ActivityFilter> expandedActivityFilterSet = new HashSet<>();
      expandedActivityFilterSet.add(expandedActivityFilter);
    3. ActivityRule erstellen:

      Kotlin

      val activityRule = ActivityRule.Builder(expandedActivityFilterSet)
          .setAlwaysExpand(true)
          .build()

      Java

      ActivityRule activityRule = new ActivityRule.Builder(
          expandedActivityFilterSet
      ).setAlwaysExpand(true)
       .build();

      ActivityRule.Builder erstellt und konfiguriert die Regel:

      • expandedActivityFilterSet: Enthält Aktivitätsfilter, mit denen Sie festlegen, wann die Regel angewendet werden soll. Dazu werden Aktivitäten angegeben, die von der Aufteilung ausgeschlossen werden sollen.
      • setAlwaysExpand(): Gibt an, ob die Aktivität das gesamte Aufgabenfenster ausfüllen soll.
    4. Fügen Sie die Regel dem WindowManager RuleController hinzu:

      Kotlin

      ruleController.addRule(activityRule)

      Java

      ruleController.addRule(activityRule);

Anwendungsübergreifende Einbettung

Unter Android 13 (API-Level 33) und höher können Apps Aktivitäten aus anderen Apps einbetten. Die App-übergreifende oder UID-übergreifende Einbettung von Aktivitäten ermöglicht die visuelle Integration von Aktivitäten aus mehreren Android-Apps. Das System zeigt eine Aktivität der Host-App und eine eingebettete Aktivität aus einer anderen App nebeneinander oder oben und unten auf dem Bildschirm an, genau wie bei der Einbettung von Aktivitäten in einer einzelnen App.

So könnte die Einstellungen-App beispielsweise die Aktivität der Hintergrundauswahl aus der App „WallpaperPicker“ einbetten:

Abbildung 14. Die Einstellungen-App (Menü links) mit der Auswahl für Hintergründe als eingebettete Aktivität (rechts).

Vertrauensmodell

Hostprozesse, die Aktivitäten aus anderen Apps einbetten, können die Darstellung der eingebetteten Aktivitäten neu definieren, einschließlich Größe, Position, Zuschnitt und Transparenz. Böswillige Hosts können diese Funktion nutzen, um Nutzer zu täuschen und Clickjacking oder andere Angriffe auf die Benutzeroberfläche durchzuführen.

Um Missbrauch von App-übergreifenden Aktivitäten zu verhindern, müssen Apps unter Android die Einbettung ihrer Aktivitäten aktivieren. Apps können Hosts als vertrauenswürdig oder nicht vertrauenswürdig kennzeichnen.

Vertrauenswürdige Hosts

Wenn Sie anderen Anwendungen erlauben möchten, Aktivitäten aus Ihrer App einzubetten und vollständig zu steuern, geben Sie das SHA-256-Zertifikat der Hostanwendung im Attribut android:knownActivityEmbeddingCerts der Elemente <activity> oder <application> der Manifestdatei Ihrer App an.

Legen Sie den Wert von android:knownActivityEmbeddingCerts entweder als String fest:

<activity
    android:name=".MyEmbeddableActivity"
    android:knownActivityEmbeddingCerts="@string/known_host_certificate_digest"
    ... />

oder, um mehrere Zertifikate anzugeben, ein String-Array:

<activity
    android:name=".MyEmbeddableActivity"
    android:knownActivityEmbeddingCerts="@array/known_host_certificate_digests"
    ... />

Das Manifest verweist auf eine Ressource wie diese:

<resources>
    <string-array name="known_host_certificate_digests">
      <item>cert1</item>
      <item>cert2</item>
      ...
    </string-array>
</resources>

App-Inhaber können einen SHA-Zertifikats-Digest abrufen, indem sie die Gradle-Aufgabe signingReport ausführen. Der Zertifikats-Digest ist der SHA-256-Fingerabdruck ohne die Trennpunkte. Weitere Informationen finden Sie unter Bericht zur Signatur ausführen und Client authentifizieren.

Nicht vertrauenswürdige Hosts

Wenn Sie zulassen möchten, dass andere Apps die Aktivitäten Ihrer App einbetten und deren Darstellung steuern können, geben Sie das Attribut android:allowUntrustedActivityEmbedding in den Elementen <activity> oder <application> im App-Manifest an. Beispiel:

<activity
    android:name=".MyEmbeddableActivity"
    android:allowUntrustedActivityEmbedding="true"
    ... />

Der Standardwert des Attributs ist „false“, was das Einbetten von App-übergreifenden Aktivitäten verhindert.

Benutzerdefinierte Authentifizierung

Um die Risiken von nicht vertrauenswürdigen eingebetteten Aktivitäten zu minimieren, erstellen Sie einen benutzerdefinierten Authentifizierungsmechanismus, der die Identität des Hosts überprüft. Wenn Sie die Hostzertifikate kennen, verwenden Sie die androidx.security.app.authenticator-Bibliothek, um sich zu authentifizieren. Wenn sich der Host nach dem Einbetten Ihrer Aktivität authentifiziert, können Sie die tatsächlichen Inhalte anzeigen. Andernfalls kannst du den Nutzer darüber informieren, dass die Aktion nicht zulässig war, und die Inhalte blockieren.

Mit der Methode ActivityEmbeddingController#isActivityEmbedded() aus der Jetpack WindowManager-Bibliothek kannst du prüfen, ob ein Host deine Aktivität einbettet, z. B. so:

Kotlin

fun isActivityEmbedded(activity: Activity): Boolean {
    return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity)
}

Java

boolean isActivityEmbedded(Activity activity) {
    return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity);
}

Mindestgröße

Das Android-System wendet die im App-Manifest-Element <layout> angegebene minimale Höhe und Breite auf eingebettete Aktivitäten an. Wenn für eine Anwendung keine Mindesthöhe und ‑breite angegeben ist, gelten die Standardwerte des Systems (sw220dp).

Wenn der Host versucht, die Größe des eingebetteten Containers auf eine Größe kleiner als das Minimum zu ändern, wird der eingebettete Container so erweitert, dass er die gesamten Aufgabengrenzen einnimmt.

<activity-alias>

Damit das Einbetten vertrauenswürdiger oder nicht vertrauenswürdiger Aktivitäten mit dem Element <activity-alias> funktioniert, muss android:knownActivityEmbeddingCerts oder android:allowUntrustedActivityEmbedding auf die Zielaktivität und nicht auf den Alias angewendet werden. Die Richtlinie, die die Sicherheit auf dem Systemserver prüft, basiert auf den Flags, die für das Ziel festgelegt sind, nicht auf dem Alias.

Hostanwendung

Hostanwendungen implementieren das Einbetten von App-übergreifenden Aktivitäten auf die gleiche Weise wie das Einbetten von Aktivitäten in einer einzelnen App. Mit den Objekten SplitPairRule und SplitPairFilter oder ActivityRule und ActivityFilter werden eingebettete Aktivitäten und Aufgabenfensteraufteilungen angegeben. Split-Regeln werden statisch in XML oder zur Laufzeit mithilfe von Jetpack WindowManager API-Aufrufen definiert.

Wenn eine Hostanwendung versucht, eine Aktivität einzubetten, für die die App-übergreifende Einbettung nicht aktiviert ist, nimmt die Aktivität die gesamte Aufgabengrenze ein. Daher müssen Hostanwendungen wissen, ob das Einbetten in anderen Apps für die Zielaktivitäten zulässig ist.

Wenn durch eine eingebettete Aktivität eine neue Aktivität in derselben Aufgabe gestartet wird und die neue Aktivität nicht für die App-übergreifende Einbettung aktiviert wurde, nimmt die Aktivität die gesamte Aufgabe ein, anstatt die Aktivität im eingebetteten Container zu überlagern.

Eine Hostanwendung kann ihre eigenen Aktivitäten uneingeschränkt einbetten, solange die Aktivitäten in derselben Aufgabe gestartet werden.

Beispiele für Split

Splitscreen-Modus vom Vollbild aus starten

Abbildung 15. Aktivität A startet Aktivität B seitlich.

Kein Refactoring erforderlich. Sie können die Konfiguration für die Aufteilung statisch oder zur Laufzeit definieren und dann Context#startActivity() ohne zusätzliche Parameter aufrufen.

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Standardmäßig teilen

Wenn die Landingpage einer Anwendung auf großen Bildschirmen in zwei Container aufgeteilt werden soll, ist die Nutzerfreundlichkeit am besten, wenn beide Aktivitäten gleichzeitig erstellt und präsentiert werden. Inhalte sind für den sekundären Container der Aufteilung jedoch möglicherweise erst verfügbar, wenn der Nutzer mit der Aktivität im primären Container interagiert, z. B. ein Element aus einem Navigationsmenü auswählt. Eine Platzhalteraktivität kann die Lücke füllen, bis Inhalte im sekundären Container der Aufteilung angezeigt werden können (siehe Abschnitt Platzhalter).

Abbildung 16. Split, der durch gleichzeitiges Öffnen von zwei Aktivitäten erstellt wurde. Eine Aktivität ist ein Platzhalter.

Wenn Sie eine Aufteilung mit einem Platzhalter erstellen möchten, erstellen Sie einen Platzhalter und verknüpfen Sie ihn mit der primären Aktivität:

<SplitPlaceholderRule
    window:placeholderActivityName=".PlaceholderActivity">
    <ActivityFilter
        window:activityName=".MainActivity"/>
</SplitPlaceholderRule>

Wenn eine App eine Intent-Anfrage erhält, kann die Zielaktivität als sekundärer Teil einer Aktivitätsaufteilung angezeigt werden. Beispiel: Eine Anfrage zum Anzeigen eines Detailbildschirms mit Informationen zu einem Element aus einer Liste. Auf kleinen Displays werden die Details im vollständigen Aufgabenfenster angezeigt, auf größeren Geräten neben der Liste.

Abbildung 17: Detailaktivitäten für Deeplinks, die auf einem kleinen Bildschirm allein und auf einem großen Bildschirm zusammen mit einer Listenaktivität angezeigt werden.

Die Startanfrage sollte an die Hauptaktivität weitergeleitet werden und die Zieldetailaktivität sollte in einem Split gestartet werden. Das System wählt automatisch die richtige Darstellung aus – gestapelt oder nebeneinander – basierend auf der verfügbaren Bildschirmbreite.

Kotlin

override fun onCreate(savedInstanceState Bundle?) {
    . . .
    RuleController.getInstance(this)
        .addRule(SplitPairRule.Builder(filterSet).build())
    startActivity(Intent(this, DetailActivity::class.java))
}

Java

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    . . .
    RuleController.getInstance(this)
        .addRule(new SplitPairRule.Builder(filterSet).build());
    startActivity(new Intent(this, DetailActivity.class));
}

Das Deeplink-Ziel ist möglicherweise die einzige Aktivität, die dem Nutzer im Navigationsstapel angezeigt werden sollte. Sie sollten die Detailaktivität also nicht schließen und nur die Hauptaktivität anzeigen lassen:

Großes Display mit Listen- und Detailaktivitäten nebeneinander.
          Bei der Rückwärtsnavigation können Details zu Aktivitäten nicht geschlossen und die Listenaktivitäten nicht auf dem Bildschirm beibehalten werden.

Kleines Display mit nur Details zur Aktivität. Bei der Zurücknavigation können Details zu Aktivitäten nicht geschlossen und Listenaktivitäten nicht angezeigt werden.

Stattdessen können Sie beide Aktivitäten gleichzeitig abschließen, indem Sie das Attribut finishPrimaryWithSecondary verwenden:

<SplitPairRule
    window:finishPrimaryWithSecondary="always">
    <SplitPairFilter
        window:primaryActivityName=".ListActivity"
        window:secondaryActivityName=".DetailActivity"/>
</SplitPairRule>

Weitere Informationen finden Sie im Abschnitt Konfigurationsattribute.

Mehrere Aktivitäten in aufgeteilten Containern

Wenn mehrere Aktivitäten in einem Split-Container gestapelt werden, können Nutzer auf umfangreiche Inhalte zugreifen. Bei einer Aufteilung in Liste und Details muss der Nutzer beispielsweise möglicherweise einen untergeordneten Detailbereich aufrufen, die Hauptaktivität aber beibehalten:

Abbildung 18: Aktivität, die im sekundären Bereich des Aufgabenfensters geöffnet wurde

Kotlin

class DetailActivity {
    . . .
    fun onOpenSubDetail() {
      startActivity(Intent(this, SubDetailActivity::class.java))
    }
}

Java

public class DetailActivity {
    . . .
    void onOpenSubDetail() {
        startActivity(new Intent(this, SubDetailActivity.class));
    }
}

Die untergeordnete Detailaktivität wird über der Detailaktivität platziert und verdeckt sie:

Der Nutzer kann dann durch den Stapel zurück zur vorherigen Detailebene wechseln:

Abbildung 19: Aktivität wurde von oben aus dem Stapel entfernt.

Das Stapeln von Aktivitäten übereinander ist das Standardverhalten, wenn Aktivitäten über eine Aktivität im selben sekundären Container gestartet werden. Aktivitäten, die über den primären Container innerhalb einer aktiven Aufteilung gestartet werden, landen ebenfalls im sekundären Container oben im Aktivitätsstapel.

Aktivitäten in einer neuen Aufgabe

Wenn Aktivitäten in einem geteilten Aufgabenfenster Aktivitäten in einer neuen Aufgabe starten, ist die neue Aufgabe unabhängig von der Aufgabe, die die Aufteilung enthält, und wird im Vollfenster angezeigt. Auf dem Bildschirm „Letzte“ werden zwei Aufgaben angezeigt: die Aufgabe in der Aufteilung und die neue Aufgabe.

Abbildung 20: Starten Sie Aktivität C in einer neuen Aufgabe über Aktivität B.

Aktivitätsersatz

Aktivitäten können im sekundären Container-Stack ersetzt werden, z. B. wenn die primäre Aktivität für die Navigation auf oberster Ebene verwendet wird und die sekundäre Aktivität ein ausgewähltes Ziel ist. Jede Auswahl aus der Navigation auf oberster Ebene sollte eine neue Aktivität im sekundären Container starten und die vorherigen Aktivitäten entfernen.

Abbildung 21. Navigationsaktivitäten der obersten Ebene im primären Bereich ersetzen Zielaktivitäten im sekundären Bereich.

Wenn die App die Aktivität im sekundären Container nicht beendet, wenn sich die Navigationsauswahl ändert, kann die Rücknavigation verwirrend sein, wenn die Ansicht minimiert ist (wenn das Gerät zusammengeklappt ist). Wenn Sie beispielsweise ein Menü im Hauptbereich und die Bildschirme A und B im sekundären Bereich haben, wird beim Zusammenklappen des Smartphones Bildschirm B über Bildschirm A und Bildschirm A über dem Menü angezeigt. Wenn der Nutzer von B zurückgeht, wird anstelle des Menüs A angezeigt.

In solchen Fällen muss Bildschirm A aus dem Backstack entfernt werden.

Standardmäßig werden beim Starten in einem neuen Container neben einer vorhandenen Spaltung die neuen sekundären Container oben platziert und die alten im Hintergrundstapel beibehalten. Sie können die Aufteilungen so konfigurieren, dass die vorherigen sekundären Container mit clearTop gelöscht und neue Aktivitäten normal gestartet werden.

<SplitPairRule
    window:clearTop="true">
    <SplitPairFilter
        window:primaryActivityName=".Menu"
        window:secondaryActivityName=".ScreenA"/>
    <SplitPairFilter
        window:primaryActivityName=".Menu"
        window:secondaryActivityName=".ScreenB"/>
</SplitPairRule>

Kotlin

class MenuActivity {
    . . .
    fun onMenuItemSelected(selectedMenuItem: Int) {
        startActivity(Intent(this, classForItem(selectedMenuItem)))
    }
}

Java

public class MenuActivity {
    . . .
    void onMenuItemSelected(int selectedMenuItem) {
        startActivity(new Intent(this, classForItem(selectedMenuItem)));
    }
}

Alternativ können Sie dieselbe sekundäre Aktivität verwenden und von der primären (Menü-)Aktivität neue Intents senden, die auf dieselbe Instanz verweisen, aber einen Status- oder UI-Update im sekundären Container auslösen.

Mehrere Aufteilungen

Apps können eine mehrstufige Navigation bieten, indem zusätzliche Aktivitäten seitlich gestartet werden.

Wenn eine Aktivität in einem sekundären Container eine neue Aktivität seitlich startet, wird eine neue Aufteilung über der vorhandenen Aufteilung erstellt.

Abbildung 22. Aktivität B startet Aktivität C seitlich.

Der Backstack enthält alle zuvor geöffneten Aktivitäten, sodass Nutzer nach Abschluss von C zur A/B-Testverzweigung wechseln können.

Aktivitäten A, B und C in einem Stapel Die Aktivitäten werden von oben nach unten in der folgenden Reihenfolge gestapelt: C, B, A.

Wenn Sie eine neue Aufteilung erstellen möchten, starten Sie die neue Aktivität seitlich neben dem vorhandenen sekundären Container. Deklarieren Sie die Konfigurationen sowohl für die A/B- als auch für die B/C-Aufteilung und starten Sie Aktivität C wie gewohnt über B:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
    <SplitPairFilter
        window:primaryActivityName=".B"
        window:secondaryActivityName=".C"/>
</SplitPairRule>

Kotlin

class B {
    . . .
    fun onOpenC() {
        startActivity(Intent(this, C::class.java))
    }
}

Java

public class B {
    . . .
    void onOpenC() {
        startActivity(new Intent(this, C.class));
    }
}

Auf Änderungen des Split-Status reagieren

Unterschiedliche Aktivitäten in einer App können UI-Elemente haben, die dieselbe Funktion ausführen, z. B. ein Steuerelement, mit dem ein Fenster mit Kontoeinstellungen geöffnet wird.

Abbildung 23. Unterschiedliche Aktivitäten mit funktional identischen UI-Elementen

Wenn zwei Aktivitäten, die ein gemeinsames UI-Element haben, in einem Split enthalten sind, ist es redundant und möglicherweise verwirrend, das Element in beiden Aktivitäten anzuzeigen.

Abbildung 24. Duplizierte UI-Elemente in der Aktivitätsaufteilung

Wenn Sie wissen möchten, wann sich Aktivitäten in einem Split befinden, prüfen Sie den Fluss SplitController.splitInfoList oder registrieren Sie einen Listener mit SplitControllerCallbackAdapter für Änderungen am Split-Status. Passen Sie dann die Benutzeroberfläche entsprechend an:

Kotlin

val layout = layoutInflater.inflate(R.layout.activity_main, null)
val view = layout.findViewById<View>(R.id.infoButton)
lifecycleScope.launch {
    lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
        splitController.splitInfoList(this@SplitDeviceActivity) // The activity instance.
            .collect { list ->
                view.visibility = if (list.isEmpty()) View.VISIBLE else View.GONE
            }
    }
}

Java

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    . . .
    new SplitControllerCallbackAdapter(SplitController.getInstance(this))
        .addSplitListener(
            this,
            Runnable::run,
            splitInfoList -> {
                View layout = getLayoutInflater().inflate(R.layout.activity_main, null);
                layout.findViewById(R.id.infoButton).setVisibility(
                    splitInfoList.isEmpty() ? View.VISIBLE : View.GONE);
            });
}

Coroutinen können in jedem Lebenszyklusstatus gestartet werden, werden aber in der Regel im Status STARTED gestartet, um Ressourcen zu sparen. Weitere Informationen finden Sie unter Kotlin-Coroutinen mit lebenszyklusbewussten Komponenten verwenden.

Callbacks können in jedem Lebenszyklusstatus erfolgen, auch wenn eine Aktivität angehalten wird. Hörer sollten in der Regel in onStart() registriert und in onStop() nicht registriert sein.

Modales Fenster im Vollbildmodus

Bei einigen Aktivitäten können Nutzer erst dann mit der Anwendung interagieren, wenn eine bestimmte Aktion ausgeführt wurde, z. B. eine Aktivität auf dem Anmeldebildschirm, ein Bildschirm zur Bestätigung der Richtlinien oder eine Fehlermeldung. Modale Aktivitäten sollten nicht in einem Split angezeigt werden.

Mit der Konfigurationsoption „Maximieren“ kann eine Aktivität so konfiguriert werden, dass sie immer das Aufgabenfenster füllt:

<ActivityRule
    window:alwaysExpand="true">
    <ActivityFilter
        window:activityName=".FullWidthActivity"/>
</ActivityRule>

Aktivitäten abschließen

Nutzer können Aktivitäten auf beiden Seiten der Aufteilung beenden, indem sie vom Rand des Displays wischen:

Abbildung 25: Wischgeste, die Aktivität B beendet
Abbildung 26. Wisch-Touch-Geste zum Beenden von Aktivität A

Wenn das Gerät so eingerichtet ist, dass die Rückwärtstaste anstelle der Gestennavigation verwendet wird, wird die Eingabe an die aktive Aktivität gesendet, also die Aktivität, die zuletzt berührt oder gestartet wurde.

Welche Auswirkungen das Beenden aller Aktivitäten in einem Container auf den gegenüberliegenden Container hat, hängt von der Split-Konfiguration ab.

Konfigurationsattribute

Sie können Regeln für Split-Paare angeben, um zu konfigurieren, wie sich das Abschließen aller Aktivitäten auf der einen Seite der Aufteilung auf die Aktivitäten auf der anderen Seite auswirkt. Die Attribute sind:

  • window:finishPrimaryWithSecondary – Wie sich das Abschließen aller Aktivitäten im sekundären Container auf die Aktivitäten im primären Container auswirkt
  • window:finishSecondaryWithPrimary – Auswirkungen des Abschlusses aller Aktivitäten im primären Container auf die Aktivitäten im sekundären Container

Mögliche Werte für die Attribute:

  • always – Aktivitäten im zugehörigen Container immer abschließen
  • never – Die Aktivitäten im zugehörigen Container werden nie abgeschlossen.
  • adjacent: Die Aktivitäten im zugehörigen Container werden abgeschlossen, wenn die beiden Container nebeneinander angezeigt werden, aber nicht, wenn sie übereinander gestapelt sind.

Beispiel:

<SplitPairRule
    &lt;!-- Do not finish primary container activities when all secondary container activities finish. --&gt;
    window:finishPrimaryWithSecondary="never"
    &lt;!-- Finish secondary container activities when all primary container activities finish. --&gt;
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Standardkonfiguration

Wenn alle Aktivitäten in einem Container eines Splits beendet sind, nimmt der verbleibende Container das gesamte Fenster ein:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Aufteilung mit den Aktivitäten A und B A ist fertig und B nimmt das gesamte Fenster ein.

Aufteilung mit den Aktivitäten A und B B ist fertig und A nimmt das gesamte Fenster ein.

Aktivitäten gemeinsam abschließen

Aktivitäten im primären Container automatisch beenden, wenn alle Aktivitäten im sekundären Container abgeschlossen sind:

<SplitPairRule
    window:finishPrimaryWithSecondary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Aufteilung mit den Aktivitäten A und B B ist abgeschlossen, wodurch auch A abgeschlossen wird und das Aufgabenfenster leer bleibt.

Aufteilung mit den Aktivitäten A und B A ist fertig und B bleibt allein im Aufgabenfenster.

Aktivitäten im sekundären Container automatisch beenden, wenn alle Aktivitäten im primären Container abgeschlossen sind:

<SplitPairRule
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Aufteilung mit den Aktivitäten A und B A ist abgeschlossen, wodurch auch B beendet wird und das Aufgabenfenster leer bleibt.

Aufteilung mit den Aktivitäten A und B B ist fertig und A bleibt allein im Aufgabenfenster.

Aktivitäten gemeinsam beenden, wenn alle Aktivitäten im primären oder sekundären Container abgeschlossen sind:

<SplitPairRule
    window:finishPrimaryWithSecondary="always"
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Aufteilung mit den Aktivitäten A und B A ist abgeschlossen, wodurch auch B beendet wird und das Aufgabenfenster leer bleibt.

Aufteilung mit den Aktivitäten A und B B ist abgeschlossen, wodurch auch A abgeschlossen wird und das Aufgabenfenster leer bleibt.

Mehrere Aktivitäten in Containern abschließen

Wenn mehrere Aktivitäten in einem geteilten Container gestapelt sind, werden durch das Beenden einer Aktivität unten im Stapel nicht automatisch die Aktivitäten oben beendet.

Wenn sich beispielsweise zwei Aktivitäten im sekundären Container befinden, C über B:

Der sekundäre Aktivitätsstapel mit Aktivität C, der auf B gestapelt ist, ist auf dem primären Aktivitätsstapel mit Aktivität A gestapelt.

Die Konfiguration der Aufteilung wird durch die Konfiguration der Aktivitäten A und B definiert:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Wenn Sie die oberste Aktivität beenden, bleibt die Aufteilung erhalten.

Aufteilung mit Aktivität A im primären Container und Aktivitäten B und C im sekundären Container, wobei C über B gestapelt ist. C ist fertig und A und B bleiben in der Aktivitätsaufteilung.

Wenn Sie die untere (Stamm-)Aktivität des sekundären Containers beenden, werden die darüber liegenden Aktivitäten nicht entfernt. Die Aufteilung bleibt also erhalten.

Aufteilung mit Aktivität A im primären Container und Aktivitäten B und C im sekundären Container, wobei C über B gestapelt ist. B ist fertig, sodass A und C in der Aktivitätsaufteilung verbleiben.

Alle zusätzlichen Regeln für das gemeinsame Abschließen von Aktivitäten, z. B. das Abschließen der sekundären Aktivität mit der primären, werden ebenfalls ausgeführt:

<SplitPairRule
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Aufgeteilt mit Aktivität A im primären Container und Aktivitäten B und C im sekundären Container, wobei C auf B gestapelt ist. A ist fertig und damit auch B und C.

Wenn die Aufteilung so konfiguriert ist, dass primäre und sekundäre Anzeigen gleichzeitig ausgeliefert werden:

<SplitPairRule
    window:finishPrimaryWithSecondary="always"
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Aufteilung mit Aktivität A im primären Container und Aktivitäten B und C im sekundären Container, wobei C über B gestapelt ist. C ist fertig und A und B bleiben in der Aktivitätsaufteilung.

Aufteilung mit Aktivität A im primären Container und Aktivitäten B und C im sekundären Container, wobei C über B gestapelt ist. B ist fertig, sodass A und C in der Aktivitätsaufteilung verbleiben.

Aufteilung mit Aktivität A im primären Container und Aktivitäten B und C im sekundären Container, wobei C über B gestapelt ist. A ist fertig und damit auch B und C.

Aufteilungseigenschaften zur Laufzeit ändern

Die Eigenschaften einer aktiven und sichtbaren Aufteilung können nicht geändert werden. Änderungen an den Split-Regeln wirken sich auf zusätzliche Aktivitätsstarts und neue Container aus, aber nicht auf vorhandene und aktive Splits.

Wenn Sie die Eigenschaften aktiver Splits ändern möchten, beenden Sie die Seitenaktivität oder -aktivitäten in der Spalte und starten Sie die Seite mit einer neuen Konfiguration neu.

Eigenschaften mit dynamischer Aufteilung

Android 15 (API-Level 35) und höher, unterstützt von Jetpack WindowManager 1.4 und höher, bieten dynamische Funktionen, mit denen sich die Aufteilung von eingebetteten Aktivitäten konfigurieren lässt. Dazu gehören:

  • Bereichserweiterung:Mit einem interaktiven, verschiebbaren Trennstrich können Nutzer die Bereiche in einer geteilten Präsentation anpassen.
  • Aktivitätsstapel anpinnen:Nutzer können Inhalte in einem Container anpinnen und die Navigation im Container von der Navigation im anderen Container isolieren.
  • Dialogfeld im Vollbildmodus dimmen:Wenn ein Dialogfeld angezeigt wird, können Apps angeben, ob das gesamte Aufgabenfenster oder nur der Container, in dem das Dialogfeld geöffnet wurde, gedimmt werden soll.

Bereich maximieren

Mit der Ansichtserweiterung können Nutzer die Bildschirmfläche anpassen, die den beiden Aktivitäten in einem Layout mit zwei Ansichten zugewiesen ist.

So passen Sie das Aussehen des Fensterteilers an und legen den Bereich fest, in dem er verschoben werden kann:

  1. Instanz von DividerAttributes erstellen

  2. Passen Sie die Trennlinienattribute an:

    • color:Die Farbe des verschiebbaren Bereichs Trennzeichens.

    • widthDp:Die Breite des verschiebbaren Bereichs Trennzeichens. Legen Sie WIDTH_SYSTEM_DEFAULT fest, damit das System die Breite des Trennstrichs bestimmt.

    • Ziehenbereich:Der Mindestprozentsatz des Bildschirms, den jeder Bereich einnehmen kann. Kann zwischen 0,33 und 0,66 liegen. Legen Sie DRAG_RANGE_SYSTEM_DEFAULT fest, damit das System den Bereich für das Ziehen festlegt.

Kotlin

val splitAttributesBuilder: SplitAttributes.Builder = SplitAttributes.Builder()
    .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
    .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)

if (WindowSdkExtensions.getInstance().extensionVersion >= 6) {
    splitAttributesBuilder.setDividerAttributes(
      DividerAttributes.DraggableDividerAttributes.Builder()
        .setColor(getColor(context, R.color.divider_color))
        .setWidthDp(4)
        .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT)
        .build()
    )
}
val splitAttributes: SplitAttributes = splitAttributesBuilder.build()

Java

SplitAttributes.Builder splitAttributesBuilder = new SplitAttributes.Builder()
    .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
    .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT);

if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 6) {
    splitAttributesBuilder.setDividerAttributes(
      new DividerAttributes.DraggableDividerAttributes.Builder()
        .setColor(ContextCompat.getColor(context, R.color.divider_color))
        .setWidthDp(4)
        .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT)
        .build()
    );
}
SplitAttributes splitAttributes = splitAttributesBuilder.build();

Aktivitätsstapel anpinnen

Mit der Aktivitätsstapel-Anpinning-Funktion können Nutzer eines der geteilten Fenster anpinnen, damit die Aktivität unverändert bleibt, während sie im anderen Fenster navigieren. Das Anpinnen von Aktivitätsstapel ermöglicht ein besseres Multitasking.

So aktivieren Sie das Anpinnen des Aktivitätsstacks in Ihrer App:

  1. Fügen Sie der Layoutdatei der Aktivität, die Sie anpinnen möchten, eine Schaltfläche hinzu, z. B. die Detailaktivität eines Listendetaillayouts:

    <androidx.constraintlayout.widget.ConstraintLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/detailActivity"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@color/white"
     tools:context=".DetailActivity">
    
    <TextView
       android:id="@+id/textViewItemDetail"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textSize="36sp"
       android:textColor="@color/obsidian"
       app:layout_constraintBottom_toTopOf="@id/pinButton"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toTopOf="parent" />
    
    <androidx.appcompat.widget.AppCompatButton
       android:id="@+id/pinButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/pin_this_activity"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@id/textViewItemDetail"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  2. Legen Sie in der onCreate()-Methode der Aktivität einen Onclick-Listener für die Schaltfläche fest:

    Kotlin

    pinButton = findViewById(R.id.pinButton)
    pinButton.setOnClickListener {
        val splitAttributes: SplitAttributes = SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.66f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build()
    
        val pinSplitRule = SplitPinRule.Builder()
            .setSticky(true)
            .setDefaultSplitAttributes(splitAttributes)
            .build()
    
        SplitController.getInstance(applicationContext).pinTopActivityStack(taskId, pinSplitRule)
    }

    Java

    Button pinButton = findViewById(R.id.pinButton);
    pinButton.setOnClickListener( (view) => {
        SplitAttributes splitAttributes = new SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.66f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build();
    
        SplitPinRule pinSplitRule = new SplitPinRule.Builder()
            .setSticky(true)
            .setDefaultSplitAttributes(splitAttributes)
            .build();
    
        SplitController.getInstance(getApplicationContext()).pinTopActivityStack(getTaskId(), pinSplitRule);
    });

Dialogfeld im Vollbildmodus abdunkeln

Bei Aktivitäten werden die Displays in der Regel gedimmt, um die Aufmerksamkeit auf einen Dialog zu lenken. Bei der Einbettung von Aktivitäten sollten beide Bereiche des zweigeteilten Displays gedimmt werden, nicht nur der Bereich mit der Aktivität, die das Dialogfeld geöffnet hat, um eine einheitliche Benutzeroberfläche zu ermöglichen.

Bei WindowManager 1.4 und höher wird das gesamte App-Fenster standardmäßig gedimmt, wenn ein Dialogfeld geöffnet wird (siehe EmbeddingConfiguration.DimAreaBehavior.ON_TASK).

Wenn Sie nur den Container der Aktivität dimmen möchten, durch die das Dialogfeld geöffnet wurde, verwenden Sie EmbeddingConfiguration.DimAreaBehavior.ON_ACTIVITY_STACK.

Aktivität aus einem geteilten Fenster in ein Vollbildfenster extrahieren

Erstellen Sie eine neue Konfiguration, in der die Seitenaktivität im Vollfenster angezeigt wird, und starten Sie die Aktivität dann noch einmal mit einem Intent, der auf dieselbe Instanz verweist.

Unterstützung für Splits während der Laufzeit prüfen

Die Einbettung von Aktivitäten wird unter Android 12L (API-Level 32) und höher unterstützt, ist aber auch auf einigen Geräten mit älteren Plattformversionen verfügbar. Wenn Sie die Verfügbarkeit der Funktion zur Laufzeit prüfen möchten, verwenden Sie das Attribut SplitController.splitSupportStatus oder die Methode SplitController.getSplitSupportStatus():

Kotlin

if (SplitController.getInstance(this).splitSupportStatus ==
     SplitController.SplitSupportStatus.SPLIT_AVAILABLE) {
     // Device supports split activity features.
}

Java

if (SplitController.getInstance(this).getSplitSupportStatus() ==
     SplitController.SplitSupportStatus.SPLIT_AVAILABLE) {
     // Device supports split activity features.
}

Wenn Aufteilungen nicht unterstützt werden, werden Aktivitäten über dem Aktivitätsstapel gestartet (gemäß dem Modell für das Einbetten von Inhalten ohne Aktivität).

System-Override verhindern

Die Hersteller von Android-Geräten (Erstausrüster, OEMs) können die Einbettung von Aktivitäten als Funktion des Gerätesystems implementieren. Das System legt Splitscreen-Regeln für Apps mit mehreren Aktivitäten fest und überschreibt das Fensterverhalten der Apps. Durch das System-Override werden Apps mit mehreren Aktivitäten in einen systemdefinierten Aktivitäts-Embedding-Modus gezwungen.

Die Einbettung von Systemaktivitäten kann die App-Darstellung durch mehrspaltige Layouts wie Liste-Detail verbessern, ohne dass Änderungen an der App vorgenommen werden müssen. Die Einbettung von Systemaktivitäten kann jedoch auch zu falschen App-Layouts, Fehlern oder Konflikten mit der von der App implementierten Einbettung von Aktivitäten führen.

Ihre App kann das Einbetten von Systemaktivitäten verhindern oder zulassen, indem Sie eine Property in der Manifestdatei der App festlegen, z. B.:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application>
        <property
            android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE"
            android:value="true|false" />
    </application>
</manifest>

Der Property-Name wird im Jetpack WindowManager-Objekt WindowProperties definiert. Legen Sie den Wert auf false fest, wenn Ihre App die Einbettung von Aktivitäten implementiert oder Sie anderweitig verhindern möchten, dass das System seine Regeln für die Einbettung von Aktivitäten auf Ihre App anwendet. Legen Sie den Wert auf true fest, damit das System systemdefinierte Einbettungen von Aktivitäten auf Ihre App anwenden kann.

Einschränkungen und Vorbehalte

  • Nur die Host-App der Aufgabe, die als Inhaber der Stammaktivität in der Aufgabe angegeben ist, kann andere Aktivitäten in die Aufgabe organisieren und einbetten. Wenn Aktivitäten, die das Einbetten und Aufteilen unterstützen, in einer Aufgabe ausgeführt werden, die zu einer anderen Anwendung gehört, funktionieren das Einbetten und Aufteilen für diese Aktivitäten nicht.
  • Aktivitäten können nur innerhalb einer einzelnen Aufgabe organisiert werden. Wenn Sie eine Aktivität in einer neuen Aufgabe starten, wird sie immer in einem neuen maximierten Fenster außerhalb vorhandener Aufteilungen geöffnet.
  • Nur Aktivitäten im selben Prozess können organisiert und in eine Aufteilung aufgenommen werden. Der SplitInfo-Callback meldet nur Aktivitäten, die zum selben Prozess gehören, da keine Informationen zu Aktivitäten in anderen Prozessen verfügbar sind.
  • Jedes Paar oder jede einzelne Aktivitätsregel gilt nur für Aktivitätsstarts, die nach der Registrierung der Regel erfolgen. Es gibt derzeit keine Möglichkeit, vorhandene Aufteilungen oder ihre visuellen Eigenschaften zu aktualisieren.
  • Die Filterkonfiguration für das Split-Pair-Tracking muss mit den Intents übereinstimmen, die beim Starten von Aktivitäten verwendet werden. Die Übereinstimmung erfolgt an dem Punkt, an dem eine neue Aktivität vom Anwendungsvorgang gestartet wird. Daher sind bei Verwendung impliziter Intents möglicherweise keine Komponentennamen bekannt, die später im Systemprozess aufgelöst werden. Wenn der Name einer Komponente zum Zeitpunkt der Einführung nicht bekannt ist, kann stattdessen ein Platzhalter („*/*“) verwendet und die Filterung basierend auf der Intent-Aktion durchgeführt werden.
  • Es ist derzeit nicht möglich, Aktivitäten nach der Erstellung zwischen Containern oder zwischen Aufteilungen zu verschieben. Aufsplittungen werden von der WindowManager-Bibliothek nur erstellt, wenn neue Aktivitäten mit übereinstimmenden Regeln gestartet werden. Sie werden wieder gelöscht, wenn die letzte Aktivität in einem aufgeteilten Container beendet ist.
  • Aktivitäten können bei einer Änderung der Konfiguration neu gestartet werden. Wenn also eine Aufteilung erstellt oder entfernt wird und sich die Aktivitätsgrenzen ändern, kann die vorherige Instanz vollständig zerstört und eine neue erstellt werden. Daher sollten App-Entwickler vorsichtig sein, wenn sie beispielsweise neue Aktivitäten über Lebenszyklus-Callbacks starten.
  • Geräte müssen die Benutzeroberfläche für Fenstererweiterungen enthalten, um das Einbetten von Aktivitäten zu unterstützen. Die Benutzeroberfläche ist auf fast allen Geräten mit großem Bildschirm und Android 12L (API-Level 32) oder höher verfügbar. Einige Geräte mit großem Display, auf denen nicht mehrere Aktivitäten ausgeführt werden können, haben jedoch keine Benutzeroberfläche für Fenstererweiterungen. Wenn ein Gerät mit großem Bildschirm den Multifenstermodus nicht unterstützt, wird möglicherweise auch das Einbetten von Aktivitäten nicht unterstützt.

Weitere Informationen