Einbetten von Aktivitäten

Die Aktivitätseinbettung optimiert Apps auf Geräten mit großen Bildschirmen, indem ein Aufgabenfenster der Anwendung zwischen zwei Aktivitäten oder zwei Instanzen derselben Aktivitäten.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 1: App „Einstellungen“ mit Aktivitäten nebeneinander.

Wenn deine App aus mehreren Aktivitäten besteht, kannst du mithilfe der Einbettung von Aktivitäten die Nutzerfreundlichkeit auf Tablets, faltbaren Geräten und ChromeOS-Geräten verbessern.

Für das Einbetten von Aktivitäten ist keine Code-Refaktorierung erforderlich. Durch Erstellen einer XML-Konfigurationsdatei oder mithilfe von Jetpack WindowManager-API-Aufrufen legen Sie fest, wie die Aktivitäten in Ihrer App nebeneinander oder gestapelt angezeigt werden.

Die Unterstützung kleiner Bildschirme wird automatisch gepflegt. Wenn Ihre App auf einem Gerät mit kleinem Bildschirm haben, sind die Aktivitäten übereinander gestapelt. An werden Aktivitäten nebeneinander angezeigt. Das System bestimmt, die Präsentation basierend auf der von Ihnen erstellten Konfiguration anpassen. Logik erforderlich.

Das Einbetten von Aktivitäten berücksichtigt Änderungen der Geräteausrichtung und funktioniert nahtlos auf faltbaren Geräten. Aktivitäten werden gestapelt oder entstapelt, wenn das Gerät auf- und zugeklappt wird.

Das Einbetten von Aktivitäten wird auf den meisten Geräten mit großen Bildschirmen mit Android 12L (API-Level 32) und höher unterstützt.

Aufgabenfenster teilen

Die Aktivitätseinbettung teilt das App-Aufgabenfenster in zwei Container auf: primären und sekundäre. Die Container enthalten Aktivitäten, die aus der Hauptaktivität oder aus anderen Aktivitäten, die bereits in den Containern vorhanden sind.

Die Aktivitäten werden beim Start im sekundären Container gestapelt. Die ist der sekundäre Container auf dem kleinen sodass die Aktivitäten-Stacking-Funktion und die Zurück-Navigation mit dem die bereits in Ihre App integrierten Aktivitäten geordnet sind.

Die Einbettung von Aktivitäten ermöglicht es Ihnen, Aktivitäten auf verschiedene Weise darzustellen. Deine App kann das Aufgabenfenster teilen, indem sie zwei Aktivitäten nebeneinander startet gleichzeitig:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 2: Zwei Aktivitäten nebeneinander.

Oder eine Aktivität, die das gesamte Aufgabenfenster einnimmt, Start einer neuen Aktivität zusammen mit:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 3: Aktivität A startet Aktivität B seitlich.

Aktivitäten, die sich bereits in einer geteilten Aufgabe befinden und ein Aufgabenfenster teilen, können gestartet werden auf folgende Arten ausführen:

  • Neben einer anderen Aktivität:

    <ph type="x-smartling-placeholder">
    </ph> <ph type="x-smartling-placeholder">
    </ph> Abbildung 4: Aktivität A beginnt Aktivität C neben Aktivität B.
  • Zur Seite und verlegen Sie die Teilung seitwärts, um die vorherige primäre Aktivität zu verbergen:

    <ph type="x-smartling-placeholder">
    </ph> <ph type="x-smartling-placeholder">
    </ph> Abbildung 5: Aktivität B startet Aktivität C zur Seite und verschiebt seitlich geteilt werden.
  • eine Aktivität oben starten; im selben Aktivitäten-Stack:

    <ph type="x-smartling-placeholder">
    </ph> <ph type="x-smartling-placeholder">
    </ph> Abbildung 6: Aktivität B startet Aktivität C ohne zusätzliche Intent-Flags.
  • Starten Sie ein vollständiges Fenster mit einer Aktivität in derselben Aufgabe:

    <ph type="x-smartling-placeholder">
    </ph> <ph type="x-smartling-placeholder">
    </ph> Abbildung 7: Aktivität A oder Aktivität B startet Aktivität C, das Aufgabenfenster aus.

Rückwärtsnavigation

Verschiedene Arten von Anwendungen können unterschiedliche Regeln für die Zurück-Navigation in einem den Status des Aufgabenfensters in Abhängigkeit von den Abhängigkeiten zwischen Aktivitäten oder Wie Nutzer das Ereignis „Zurück“ auslösen. Beispiel:

  • Zusammenführung: Wenn Aktivitäten zusammenhängen und nicht angezeigt werden sollen ohne das andere, kann die Rückwärtsnavigation so konfiguriert werden, dass beides abgeschlossen wird.
  • Alleine angehen: Sind die Aktivitäten völlig unabhängig voneinander, kann die Rückwärtsnavigation auf Aktivität hat keinen Einfluss auf den Status einer anderen Aktivität im Aufgabenfenster.

Bei Verwendung der Schaltfläche wird das Ereignis „Zurück“ an die letzte fokussierte Aktivität gesendet Navigation. Bei der bewegungsbasierten Navigation wird das Zurück-Ereignis an den Aktivität, bei der die Geste ausgeführt wurde.

Mehrfensterlayout

Mit Jetpack WindowManager können Sie ein Mehrfensterlayout für die Einbettung von Aktivitäten auf Geräten mit großen Bildschirmen mit Android 12L (API-Level 32) oder höher und auf einigen Geräten mit älteren Plattformversionen erstellen. Vorhandene Apps, die auf mehreren Aktivitäten statt auf Fragmenten oder ansichtsbasierten Layouts wie SlidingPaneLayout basieren, können für Nutzer mit großen Bildschirmen eine bessere Nutzererfahrung bieten, ohne dass der Quellcode refaktoriert werden muss.

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

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 8: Zwei Aktivitäten, die gleichzeitig in einem Mehrfachbereich gestartet wurden Layout.

Aufteilungsattribute

Sie können angeben, wie das Aufgabenfenster zwischen den aufgeteilten Containern und das Layout der Container im Verhältnis zueinander angeordnet werden soll.

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

  • splitRatio: Legt die Containerproportionen fest. Der Wert ist eine Gleitkommazahl im offenen Intervall (0,0 bis 1,0).
  • splitLayoutDirection: Gibt an, wie die aufgeteilten Container relativ zueinander angeordnet sind. Mögliche Werte: <ph type="x-smartling-placeholder">
      </ph>
    • ltr: von links nach rechts
    • rtl: Linksläufig
    • locale: ltr oder rtl wird durch die Spracheinstellung bestimmt

Beispiele finden Sie unten 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 Builder-Methoden auf:

Beispiele finden Sie unten unter WindowManager API.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 9: Zwei Aktivitätsaufteilungen wurden von links nach rechts angeordnet, aber mit unterschiedlichen Aufteilungsverhältnissen.

Platzhalter

Platzhalteraktivitäten sind leere sekundäre Aktivitäten, die eine Aktivitätsaufteilung. Sie sollen letztendlich durch eine andere die Inhalte enthalten. So könnte eine Platzhalteraktivität die Sekundärseite einer Aktivitätsaufteilung in einem Listen-Detail-Layout einnehmen, wird ein Element aus der Liste ausgewählt, woraufhin eine Aktivität mit den für das ausgewählte Listenelement ersetzt den Platzhalter.

Standardmäßig zeigt das System Platzhalter nur dann an, wenn genügend Platz für eine Aktivitätsaufteilung vorhanden ist. Platzhalter werden automatisch fertiggestellt, wenn sich die Anzeigegröße auf eine Breite oder Höhe ändert, die für eine Aufteilung zu klein ist. Wenn der Platz ausreicht, startet das System den Platzhalter mit einem neu initialisierten Status neu.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 10: Faltbares Gerät auf- und zuklappen. Platzhalter abgeschlossen und bei Änderungen der Anzeigegröße neu erstellt.

Das Attribut stickyPlaceholder einer SplitPlaceholderRule- oder setSticky()-Methode von SplitPlaceholder.Builder kann jedoch das Standardverhalten überschreiben. Wenn das Attribut oder die Methode den Wert true angibt, zeigt das System den Platzhalter als oberste Aktivität im Aufgabenfenster an, wenn die Anzeige von einer Zweifensteransicht zur Einzelansicht verkleinert wird (ein Beispiel finden Sie unter Unterteilte Konfiguration).

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 11: Faltbares Gerät auf- und zuklappen. Platzhalter die Aktivität fixiert.

Änderungen der Fenstergröße

Verkleinern Sie bei Änderungen der Gerätekonfiguration die Breite des Aufgabenfensters, nicht groß genug für ein Mehrfensterlayout (z. B. wenn ein großer Bildschirm faltbares Gerät klappt von Tablet zu Smartphone oder das App-Fenster im Mehrfenstermodus geändert werden, werden die Aktivitäten, die keine Platzhalter sind, in der sekundären Bereich des Aufgabenfensters über den Aktivitäten im primären .

Platzhalteraktivitäten werden nur angezeigt, wenn die Anzeigebreite für eine geteilt. Auf kleineren Bildschirmen wird der Platzhalter automatisch geschlossen. Wann? wird der Anzeigebereich wieder groß genug, wird der Platzhalter neu erstellt. Weitere Informationen finden Sie oben unter Platzhalter.

Das Stapeln von Aktivitäten ist möglich, weil WindowManager ordnet die Aktivitäten im sekundären Bereich über den Aktivitäten im primären Bereich.

Mehrere Aktivitäten im sekundären Bereich

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

Aktivitätsaufteilung mit Aktivitäten A, B und C, wobei C eingeblendet ist
          oben auf B.

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

Sekundärer Aktivitätsstapel mit Aktivität C über Seite B.
          Der sekundäre Stapel wird über den primären Aktivitäts-Stack gestapelt
          die Aktivität A enthält.

In einem kleineren Aufgabenfenster wird die Anwendung also auf eine einzige Aktivität verkleinert. mit C ganz oben im Stapel:

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

Wenn Sie im kleineren Fenster zurücknavigieren, können Sie durch die gestapelten Aktivitäten wechseln übereinander liegen.

Wenn die Konfiguration des Aufgabenfensters auf eine größere Größe wiederhergestellt wird, mehrere Bereiche aufnehmen, werden die Aktivitäten wieder nebeneinander angezeigt.

Gestapelte Aufteilungen

Aktivität B startet Aktivität C zur Seite und verschiebt den Teil zur Seite:

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

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

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

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

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 Geräten zu verbessern, können Gerätehersteller (OEMs) Anfragen zur Bildschirmausrichtung ignorieren und die App im Hochformat im Querformat oder im Querformat auf Displays im Hochformat anzeigen lassen.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 12. Letterbox-Aktivitäten: fixiertes Hochformat auf Gerät im Querformat (links), festes Querformat auf Gerät im Hochformat (rechts).

Wenn die Einbettung von Aktivitäten aktiviert ist, können OEMs Geräte so anpassen, dass Aktivitäten im Letterbox-Format im Querformat auf großen Bildschirmen (Breite ≥ 600 dp) angezeigt werden. Wenn eine feste Hochformataktivität eine zweite Aktivität startet, kann das Gerät die beiden Aktivitäten nebeneinander in einem Zweifenster anzeigen.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 13: Aktivität A mit festem Hochformat startet Aktivität B seitlich.

Füge deiner App-Manifestdatei immer das Attribut android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED hinzu, um Geräte darüber zu informieren, dass deine App die Einbettung von Aktivitäten unterstützt (siehe Split-Konfiguration unten). OEM-benutzerdefinierte Geräte können dann bestimmen, ob Aktivitäten im Letterbox-Format (Fixed Portrait) verwendet werden sollen.

Konfiguration der Aufteilung

Mit Aufteilungsregeln werden Aktivitätsaufteilungen konfiguriert. Sie definieren Aufteilungsregeln in einer XML-Konfigurationsdatei oder durch Jetpack-WindowManager-API-Aufrufe.

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

Unternimm Folgendes:

  1. Fügen Sie der Datei build.gradle Ihrer App auf Modulebene die neueste WindowManager-Bibliotheksabhängigkeit hinzu. Beispiel:

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

    Die WindowManager-Bibliothek bietet alle Komponenten, die für das Einbetten von Aktivitäten erforderlich sind.

  2. Teilen Sie dem System mit, dass in Ihrer App die Aktivitätseinbettung implementiert ist.

    Fügen Sie das Attribut android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED zu <application> hinzu. der Manifest-Datei der App an und setzen Sie den Wert auf "true". Beispiel:

    <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-Version 1.1.0-alpha06 sind Aufteilungen mit Aktivitätseinbettungen deaktiviert, es sei denn, die Eigenschaft wird dem Manifest hinzugefügt und auf „true“ gesetzt.

    Außerdem können Gerätehersteller benutzerdefinierte Funktionen für Apps aktivieren, die das Einbetten von Aktivitäten unterstützen. Auf Geräten im Querformat kann beispielsweise eine Aktivität, die nur im Hochformat angezeigt wird, im Letterbox-Format dargestellt werden, um die Aktivität für den Übergang zu einem Layout mit zwei Bereichen zu gestalten, wenn eine zweite Aktivität beginnt (siehe Feste Hochformatausrichtung).

XML-Konfiguration

Führen Sie die folgenden Schritte aus, um eine XML-basierte Implementierung der Aktivitätseinbettung zu erstellen:

  1. Erstellen Sie eine XML-Ressourcendatei, die folgende Aufgaben erfüllt:

    • Definiert Aktivitäten, die eine Aufteilung teilen
    • Konfiguriert die Aufteilungsoptionen
    • Erstellt einen Platzhalter für den sekundären Container der Aufteilung, wenn kein Inhalt verfügbar ist
    • Gibt Aktivitäten an, die niemals Teil einer Aufteilung sein sollen

    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 WindowManager-Komponente RuleController parst die XML-Konfigurationsdatei und stellt die Regeln dem System zur Verfügung. Eine Jetpack-Startbibliothek Initializer stellt RuleController beim Start der App die XML-Datei zur Verfügung, damit die Regeln wirksam werden, wenn Aktivitäten beginnen.

    So erstellen Sie einen Initialisierer:

    1. Fügen Sie der Datei build.gradle auf Modulebene die neueste Abhängigkeit der Jetpack Startup-Bibliothek hinzu. Beispiel:

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

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

      Der Initialisierer macht die Aufteilungsregeln für RuleController verfügbar, indem er die ID der XML-Konfigurationsdatei (main_split_config.xml) an die Methode RuleController.parseRules() ü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üge deiner App-Manifestdatei androidx.startup.InitializationProvider als <provider> hinzu. Füge eine Referenz zur Implementierung deines RuleController-Initialisierers SplitInitializer hinzu:

    <!-- 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 onCreate()-Methode der App aufgerufen wird. Die Aufteilungsregeln gelten daher, wenn die Hauptaktivität der App beginnt.

WindowManager-API

Mit ein paar API-Aufrufen können Sie die Einbettung von Aktivitäten programmatisch implementieren. Führen Sie die Aufrufe in der Methode onCreate() einer Unterklasse von Application aus, um sicherzustellen, dass die Regeln vor dem Start von Aktivitäten wirksam sind.

So erstellen Sie programmatisch eine Aktivitätsaufteilung:

  1. Erstellen Sie eine Aufteilungsregel:

    1. Erstellen Sie einen SplitPairFilter mit den Aktivitäten, 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. So fügen Sie den Filter einer Filtergruppe 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();
      

      SplitAttributes.Builder erstellt ein Objekt mit Layoutattributen:

      • setSplitType: Definiert, wie der verfügbare Anzeigebereich den einzelnen Aktivitätscontainern zugeordnet wird. Der Verhältnisaufteilungstyp gibt den Anteil des verfügbaren Anzeigebereichs an, der dem primären Container zugewiesen ist. nimmt der sekundäre Container den Rest des verfügbaren Anzeigebereichs ein.
      • setLayoutDirection: Gibt an, wie die Aktivitätscontainer im Verhältnis zueinander angeordnet werden (Primärcontainer zuerst).
    4. Erstellen Sie ein SplitPairRule:

      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 Filter für aufgeteilte Paare, die festlegen, wann die Regel angewendet werden soll. Dazu werden Aktivitäten ermittelt, die eine Aufteilung verwenden.
      • setDefaultSplitAttributes: Wendet Layoutattribute auf die Regel an.
      • setMinWidthDp: Hiermit wird die minimale Anzeigebreite (in dichteunabhängigen Pixeln, dp) festgelegt, die eine Aufteilung ermöglicht.
      • setMinSmallestWidthDp: Legt den Mindestwert (in dp) fest, den der kleinere der beiden Displayabmessungen haben muss, um unabhängig von der Geräteausrichtung eine Aufteilung zu ermöglichen.
      • setMaxAspectRatioInPortrait: Hiermit wird das maximale Seitenverhältnis (Höhe:Breite) im Hochformat festgelegt, für das Aktivitätsaufteilungen angezeigt werden. Wenn das Seitenverhältnis eines Displays im Hochformat das maximale Seitenverhältnis überschreitet, wird die Teilung unabhängig von der Breite des Bildschirms deaktiviert. Hinweis:Der Standardwert ist 1,4.Das bedeutet, dass Aktivitäten auf den meisten Tablets das gesamte Aufgabenfenster im Hochformat belegen. 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 wurden (siehe Aktivitäten beenden).
      • setFinishSecondaryWithPrimary: Hiermit wird festgelegt, wie sich das Abschließen 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 immer im sekundären Container abschließen soll, wenn alle Aktivitäten im primären Container abgeschlossen wurden (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. Mit „False“ wird angegeben, dass neue Aktivitäten über die Aktivitäten gestapelt werden, die sich bereits im sekundären Container befinden.
    5. Rufen Sie die Singleton-Instanz von WindowManager 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. Erstellen Sie einen Platzhalter für den sekundären Container, wenn keine Inhalte verfügbar sind:

    1. Erstellen Sie einen ActivityFilter, der die Aktivität identifiziert, mit der der Platzhalter eine Aufteilung des Aufgabenfensters teilt:

      Kotlin

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

      Java

      ActivityFilter placeholderActivityFilter = new ActivityFilter(
          new ComponentName(this, ListActivity.class),
          null
      );
      
    2. So fügen Sie den Filter einer Filtergruppe hinzu:

      Kotlin

      val placeholderActivityFilterSet = setOf(placeholderActivityFilter)
      

      Java

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

      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, die festlegen, wann die Regel angewendet werden soll. Dazu werden Aktivitäten ermittelt, mit denen die Platzhalteraktivität verknüpft ist.
      • Intent: Gibt den Start der Platzhalteraktivität an.
      • setDefaultSplitAttributes: Wendet Layoutattribute auf die Regel an.
      • setMinWidthDp: Hiermit wird die minimale Anzeigebreite (in dichteunabhängigen Pixeln, dp) festgelegt, die eine Aufteilung ermöglicht.
      • setMinSmallestWidthDp: Legt den Mindestwert (in dp) fest, den der kleinere der beiden Anzeigeabmessungen haben muss, um unabhängig von der Geräteausrichtung eine Aufteilung zu ermöglichen.
      • setMaxAspectRatioInPortrait: Hiermit wird das maximale Seitenverhältnis (Höhe:Breite) im Hochformat festgelegt, für das Aktivitätsaufteilungen angezeigt werden. Hinweis:Der Standardwert ist 1,4.Das führt auf den meisten Tablets dazu, dass das Aufgabenfenster im Hochformat ausgefüllt wird. Weitere Informationen finden Sie unter SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT und setMaxAspectRatioInLandscape. Der Standardwert für das Querformat ist ALWAYS_ALLOW.
      • setFinishPrimaryWithPlaceholder: Hiermit wird festgelegt, wie sich das Abschließen der Platzhalteraktivität auf die Aktivitäten im primären Container auswirkt. ALWAYS gibt an, dass das System die Aktivitäten immer im primären Container beenden soll, wenn der Platzhalter beendet ist (siehe Aktivitäten beenden).
      • setSticky: Damit wird festgelegt, ob die Platzhalteraktivität auf kleinen Displays über dem Aktivitätsstapel erscheint, sobald der Platzhalter erstmals in einem Split mit ausreichender Mindestbreite angezeigt wurde.
    4. Füge die Regel zum WindowManager RuleController hinzu:

      Kotlin

      ruleController.addRule(splitPlaceholderRule)
      

      Java

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

    1. Erstellen Sie eine ActivityFilter, die eine Aktivität kennzeichnet, die immer den gesamten Aufgabenbereich einnehmen sollte:

      Kotlin

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

      Java

      ActivityFilter expandedActivityFilter = new ActivityFilter(
        new ComponentName(this, ExpandedActivity.class),
        null
      );
      
    2. So fügen Sie den Filter einer Filtergruppe hinzu:

      Kotlin

      val expandedActivityFilterSet = setOf(expandedActivityFilter)
      

      Java

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

      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, die festlegen, wann die Regel angewendet werden soll. Dazu identifizieren Sie Aktivitäten, die Sie aus Aufteilungen ausschließen möchten.
      • setAlwaysExpand: Gibt an, ob die Aktivität das gesamte Aufgabenfenster ausfüllen soll.
    4. Füge die Regel zum 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 anwendungsübergreifende (UID-) Einbettung von Aktivitäten ermöglicht die visuelle Integration von Aktivitäten aus verschiedenen Android-Apps. Das System zeigt eine Aktivität der Host-App und eine eingebettete Aktivität aus einer anderen App auf dem Bildschirm nebeneinander oder oben und unten an, genau wie beim Einbetten von Einzel-App-Aktivitäten.

In die Einstellungen-App könnte beispielsweise die Hintergrundauswahlaktivität aus der HintergründePicker-App eingebettet werden:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 14: App „Einstellungen“ (Menü auf der linken Seite) mit Hintergrundauswahl 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, Zuschneiden und Transparenz. Schädliche Hosts können diese Funktion nutzen, um Nutzer in die Irre zu führen und Clickjacking oder andere UI-Redressing-Angriffe zu verursachen.

Damit der Missbrauch eingebetteter Aktivitäten von App-übergreifenden Aktivitäten verhindert wird, müssen Apps die Einbettung ihrer Aktivitäten erlauben. Apps können Hosts als vertrauenswürdig oder nicht vertrauenswürdig kennzeichnen.

Vertrauenswürdige Hosts

Damit andere Apps die Darstellung von Aktivitäten aus Ihrer App einbetten und uneingeschränkt steuern können, geben Sie das SHA-256-Zertifikat der Host-App 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 ein String-Array, um mehrere Zertifikate anzugeben:

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

der auf eine Ressource wie die folgende verweist:

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

App-Inhaber können einen SHA-Zertifikat-Digest abrufen, indem sie die Gradle-Task signingReport ausführen. Der Zertifikat-Digest ist der SHA-256-Fingerabdruck ohne die Doppelpunkte. Weitere Informationen finden Sie unter Signaturbericht ausführen und Client authentifizieren.

Nicht vertrauenswürdige Hosts

Wenn Sie einer App erlauben möchten, die Aktivitäten Ihrer App einzubetten und ihre Darstellung zu steuern, geben Sie im App-Manifest das Attribut android:allowUntrustedActivityEmbedding in den Elementen <activity> oder <application> an. Beispiel:

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

Der Standardwert des Attributs ist „false“, wodurch das Einbetten von App-Aktivitäten verhindert wird.

Benutzerdefinierte Authentifizierung

Erstellen Sie einen benutzerdefinierten Authentifizierungsmechanismus, der die Hostidentität überprüft, um das Risiko der Einbettung nicht vertrauenswürdiger Aktivitäten zu verringern. Wenn Sie die Hostzertifikate kennen, verwenden Sie zur Authentifizierung die androidx.security.app.authenticator-Bibliothek. Wenn sich der Host nach dem Einbetten deiner Aktivität authentifiziert, kannst du den tatsächlichen Inhalt anzeigen. Falls nicht, kannst du den Nutzer darüber informieren, dass die Aktion nicht erlaubt wurde, und den Inhalt blockieren.

Verwenden Sie die Methode ActivityEmbeddingController#isActivityEmbedded() aus der Jetpack WindowManager-Bibliothek, um zu prüfen, ob ein Host Ihre Aktivität einbettet. Beispiel:

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-Manifestelement <layout> angegebene Mindesthöhe und -breite auf eingebettete Aktivitäten an. Wenn eine App keine Mindesthöhe und -breite vorgibt, werden die Systemstandardwerte angewendet (sw220dp).

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

<Aktivitätsalias>

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 zur Überprüfung der Sicherheit auf dem Systemserver basiert auf den Flags, die im Ziel festgelegt sind, und nicht auf dem Alias.

Hostanwendung

Host-Apps implementieren die Einbettung App-übergreifender Aktivitäten auf die gleiche Weise wie die Einbettung von Einzel-App-Aktivitäten. SplitPairRule- und SplitPairFilter- oder ActivityRule- und ActivityFilter-Objekte geben eingebettete Aktivitäten und Aufteilungen von Aufgabenfenstern an. Aufteilungsregeln werden statisch in XML oder zur Laufzeit mithilfe von Jetpack WindowManager API-Aufrufen definiert.

Wenn eine Host-App versucht, eine Aktivität einzubetten, die App-übergreifende Einbettung nicht aktiviert hat, belegt die Aktivität die gesamten Aufgabengrenzen. Daher müssen Host-Anwendungen wissen, ob Zielaktivitäten eine appübergreifende Einbettung zulassen.

Wenn eine eingebettete Aktivität eine neue Aktivität in derselben Aufgabe startet und für die neue Aktivität die App-übergreifende Einbettung nicht aktiviert wurde, nimmt die Aktivität die gesamten Aufgabengrenzen ein und überlagert nicht die Aktivität im eingebetteten Container.

Eine Host-Anwendung kann ihre eigenen Aktivitäten ohne Einschränkung einbetten, solange die Aktivitäten in derselben Aufgabe gestartet werden.

Beispiele für Aufteilungen

Vom gesamten Fenster teilen

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 15. Aktivität A startet Aktivität B seitlich.

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

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

Standardmäßig aufteilen

Wenn die Landingpage einer App in zwei Teile geteilt werden soll Container auf großen Bildschirmen verwenden, ist die User Experience am besten, wenn beide Aktivitäten gleichzeitig erstellt und präsentiert werden. Es kann jedoch sein, dass Inhalte für den sekundären Container des Splits verfügbar, bis der Nutzer interagiert mit der Aktivität im primären Container (z. B. wenn der Nutzer ein Element aus einem Navigationsmenü). Eine Platzhalteraktivität kann die Lücke bis kann im sekundären Container des Splits angezeigt werden (siehe Platzhalter oben.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 16. Die Aufteilung wurde durch gleichzeitiges Öffnen von zwei Aktivitäten erstellt. 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 durch die primäre Aktivität:

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

Wenn eine App einen Intent empfängt, kann die Zielaktivität als sekundärer Teil einer Aktivitätsaufteilung; z. B. eine Anfrage, ein Detail anzuzeigen, mit Informationen zu einem Element aus einer Liste. Auf kleinen Displays Details werden im vollständigen Aufgabenfenster angezeigt. auf größeren Geräten neben der Liste.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 17. Die Deeplink-Detailaktivität wird alleine auf einem kleinen Bildschirm angezeigt, sondern zusammen mit einer Liste der Aktivitäten auf einem großen Bildschirm.

Die Startanfrage sollte an die Hauptaktivität weitergeleitet und die Zieldetailaktivität in einer Aufteilung gestartet werden. Das System wählt automatisch die richtige Präsentation – gestapelt oder nebeneinander – basierend auf der verfügbaren Anzeigebreite aus.

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

Unter Umständen ist das Deeplink-Ziel die einzige Aktivität, die verfügbar sein sollte im Rückwärtsnavigations-Stack an. Detailaktivität schließen und nur die Hauptaktivität beibehalten:

Großes Display mit Listen- und Detailaktivitäten nebeneinander.
          „Zurück“-Navigation kann die Detailaktivität nicht schließen und die Liste verlassen
          Aktivitäten auf dem Bildschirm.

Kleines Display nur mit Detailaktivität. Rückwärtsnavigation nicht möglich
          Detailaktivität schließen und Listenaktivität anzeigen.

Stattdessen können Sie beide Aktivitäten mithilfe der Methode Attribut finishPrimaryWithSecondary:

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

Siehe Konfigurationsattribute unten.

Mehrere Aktivitäten in geteilten Containern

Durch das Stapeln mehrerer Aktivitäten in einem geteilten Container können Nutzer tief Inhalte. Bei einer Aufteilung von Listen und Details Abschnitt mit Unterdetails öffnen, dabei aber die primäre Aktivität beibehalten:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 18. Die Aktivität wird im sekundären Bereich des Aufgabenfensters.

Kotlin

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

Java

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

Die Unterdetailaktivität wird über der Detailaktivität platziert und blendet sie aus:

Der Nutzer kann dann zur vorherigen Detailebene zurückkehren, über den Stack:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 19. Aktivität wurde vom Anfang des Stapels entfernt.

Aktivitäten übereinander zu stapeln ist das Standardverhalten, Aktivitäten werden über eine Aktivität im selben sekundären Container gestartet. Aktivitäten, die vom primären Container innerhalb eines aktiven Splits gestartet werden, enden ebenfalls im sekundären Container oben im Aktivitäten-Stack.

Aktivitäten in einer neuen Aufgabe

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

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 20. Beginnen Sie Aktivität C in einer neuen Aufgabe aus Aktivität B.

Aktivitäten ersetzen

Aktivitäten können im sekundären Container-Stack ersetzt werden. wenn beispielsweise wird die primäre Aktivität für die Navigation der obersten Ebene und die sekundäre „Aktivität“ ist ein ausgewähltes Ziel. Jede Auswahl der obersten Ebene eine neue Aktivität im sekundären Container starten und die Aktivitäten oder Aktivitäten, die vorher vorhanden waren.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 21. Navigationsaktivität der obersten Ebene im primären Bereich Zielaktivitäten im sekundären Bereich ersetzt.

Wenn die App die Aktivität nicht im sekundären Container beendet, wenn der ändert sich die Navigationsauswahl, kann die Rückwärtsnavigation verwirrend sein, geteilt wird (beim zusammengeklappten Gerät). Wenn Sie zum Beispiel eine im primären Bereich und die Bildschirme A und B im sekundären Bereich Wenn die nutzende Person das Smartphone zuklappen, befindet sich B auf A und A über dem Menü. Wenn der Nutzer von B zurückkehrt, erscheint anstelle des Menüs A.

Bildschirm A muss in solchen Fällen aus dem Back Stack entfernt werden.

Das Standardverhalten beim Starten seitlich in einem neuen Container über einem bei der bestehenden Aufteilung die neuen sekundären Container ganz oben alten im Back Stack ab. Sie können die Aufteilungen so konfigurieren, dass die vorherigen sekundäre Container mit clearTop und starten neue Aktivitäten normal.

<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 und aus der primären Aktivität (Menü) verwenden. werden neue Intents gesendet, die in dieselbe Instanz aufgelöst werden, aber einen oder UI-Update im sekundären Container.

Mehrere Aufteilungen

Apps können eine mehrstufige Tiefennavigation bieten, indem zusätzliche Aktivitäten beiseite.

Startet eine Aktivität in einem sekundären Container eine neue Aktivität seitlich, wird eine neue Aufteilung erstellt.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 22. Aktivität B startet Aktivität C nebenan.

Der Back-Stack enthält alle Aktivitäten, die zuvor geöffnet waren. nach C-Phasen zum A/B-Split gelangen.

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

Um eine neue Aufteilung zu erstellen, starten Sie die neue Aktivität neben der bestehenden sekundärer Container. Deklarieren Sie die Konfigurationen für A/B und B/C und Aktivität C normalerweise von B starten:

<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 Statusänderungen reagieren

Verschiedene Aktivitäten in einer App können UI-Elemente haben, die dieselbe Funktion haben Funktion; z. B. ein Steuerelement, das ein Fenster mit Einstellungen.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 23. Verschiedene Aktivitäten mit funktional identischen UI-Elementen

Wenn zwei Aktivitäten, die ein UI-Element gemeinsam haben, sich in einem Split befinden, ist es und es möglicherweise verwirrend ist, das Element in beiden Aktivitäten anzuzeigen.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 24. Doppelte UI-Elemente in der Aktivitätsaufteilung.

Wenn Sie wissen möchten, wann sich Aktivitäten in einem Split befinden, prüfen Sie den SplitController.splitInfoList-Ablauf oder registrieren Sie einen Listener mit SplitControllerCallbackAdapter auf Änderungen am Aufteilungsstatus. 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);
            });
}

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

Callbacks können in jedem Lebenszyklusstatus erfolgen, auch wenn eine Aktivität angehalten. Listener sollten normalerweise in onStart() registriert und nicht registriert in onStop()

Modales Vollbildfenster

Einige Aktivitäten blockieren die Interaktion der Nutzer mit der App, bis eine die angegebene Aktion ausgeführt wird; z. B. eine Aktivität auf dem Anmeldebildschirm, Bestätigungsbildschirm oder eine Fehlermeldung angezeigt. Modale Aktivitäten sollten verhindert werden in einer Aufteilung erscheinen.

Sie können erzwingen, dass eine Aktivität immer das Aufgabenfenster ausfüllt, indem Sie die Schaltfläche zum Maximieren verwenden Konfiguration:

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

Aktivitäten beenden

Nutzer können die Aktivitäten auf beiden Seiten des geteilten Bereichs beenden, indem sie vom Rand des Displays:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Abbildung 25. Wischgeste zum Beenden von Aktivität B.
<ph type="x-smartling-placeholder">
</ph>
Abbildung 26. Wischgeste zum Beenden von Aktivität A.

Wenn das Gerät so eingerichtet ist, dass die Schaltfläche „Zurück“ anstelle der Bedienung über Gesten verwendet wird, wird die Eingabe an die fokussierte Aktivität gesendet, d. h. die Aktivität, die berührt oder zuletzt eingeführt.

Wie sich das Beenden aller Aktivitäten in einem Container auf den gegenüberliegenden Container auswirkt, hängt von der Aufteilungskonfiguration ab.

Konfigurationsattribute

Sie können Regelattribute für Aufteilungspaare angeben, um zu konfigurieren, wie sich das Beenden aller Aktivitäten auf einer Seite der Aufteilung auf die Aktivitäten auf der anderen Seite der Aufteilung auswirkt. Die Attribute sind:

  • window:finishPrimaryWithSecondary: Wie wirkt sich das Beenden aller Aktivitäten im sekundären Container auf die Aktivitäten im primären Container aus?
  • window:finishSecondaryWithPrimary: Wie wirkt sich das Beenden aller Aktivitäten im primären Container auf die Aktivitäten im sekundären Container aus?

Mögliche Werte der Attribute:

  • always: Die Aktivitäten werden immer im zugehörigen Container beendet.
  • never: Die Aktivitäten im zugehörigen Container werden nie beendet.
  • adjacent: Die Aktivitäten im zugehörigen Container werden beendet, wenn die beiden Container nebeneinander angezeigt werden, aber nicht, wenn die beiden Container gestapelt sind.

Beispiel:

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

Standardkonfiguration

Wenn alle Aktivitäten in einem Container eines Splits abgeschlossen sind, belegt der verbleibende Container das gesamte Fenster:

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

Aufteilung mit den Aktivitäten A und B. A ist abgeschlossen, während B
          das gesamte Fenster einnimmt.

Aufteilung mit den Aktivitäten A und B. B abgeschlossen ist, während A bis
          das gesamte Fenster einnimmt.

Aktivitäten gemeinsam beenden

Die Aktivitäten im primären Container werden automatisch beendet, 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 beendet ist, was auch
          beendet A und lässt das Aufgabenfenster leer.

Aufteilung mit den Aktivitäten A und B. A ist beendet, B bleibt in diesem Fall.
          im Aufgabenfenster aus.

Schließen Sie die Aktivitäten im sekundären Container automatisch ab, 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 beendet ist, was auch
          beendet B und lässt das Aufgabenfenster leer.

Aufteilung mit den Aktivitäten A und B. B abgeschlossen ist, und A in Ruhe lässt.
          im Aufgabenfenster aus.

Schließen Sie die Aktivitäten zusammen ab, 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 beendet ist, was auch
          beendet B und lässt das Aufgabenfenster leer.

Aufteilung mit den Aktivitäten A und B. B beendet ist, was auch
          beendet A und lässt das Aufgabenfenster leer.

Mehrere Aktivitäten in Containern abschließen

Wenn mehrere Aktivitäten in einem geteilten Container gestapelt sind, wird eine Aktivität beendet unten im Stapel beenden Aktivitäten nicht automatisch oben.

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

Sekundärer Aktivitätsstapel mit Aktivität C über Seite B
          wird über den praktischen Aktivitäten-Stack gestapelt, der die Aktivität enthält.

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

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

Beim Abschließen der obersten Aktivität wird die Aufteilung beibehalten.

Mit Aktivität A im primären Container und Aktivitäten B und C im primären Container aufteilen
          Sekundär, C über B gestapelt. C endet, während A und B
          Aktivitätsaufteilung.

Das Abschließen der unteren (Stamm-)Aktivität des sekundären Containers die Aktivitäten darüber entfernen; und behält so auch die Aufteilung bei.

Mit Aktivität A im primären Container und Aktivitäten B und C im primären Container aufteilen
          Sekundär, C über B gestapelt. B beendet, wobei A und C
          Aktivitätsaufteilung.

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

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

Mit Aktivität A im primären Container und Aktivitäten B und C im primären Container aufteilen
          sekundärer Container, C über B gestapelt. A Ende, auch
          B und C beenden.

Und wenn die Aufteilung so konfiguriert ist, dass die primäre und die sekundäre Instanz zusammen abgeschlossen werden:

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

Mit Aktivität A im primären Container und Aktivitäten B und C im primären Container aufteilen
          Sekundär, C über B gestapelt. C endet, während A und B
          Aktivitätsaufteilung.

Mit Aktivität A im primären Container und Aktivitäten B und C im primären Container aufteilen
          Sekundär, C über B gestapelt. B beendet, wobei A und C
          Aktivitätsaufteilung.

Mit Aktivität A im primären Container und Aktivitäten B und C im primären Container aufteilen
          Sekundär, C über B gestapelt. Ende A, Ende B und Ende
          C)

Aufteilungsattribute während der Laufzeit ändern

Die Eigenschaften einer derzeit aktiven und sichtbaren Aufteilung können nicht geändert werden. Das Ändern der Aufteilungsregeln wirkt sich auf zusätzliche Aktivitäten und neue Container, aber nicht vorhandene und aktive Aufteilungen.

Um die Eigenschaften aktiver Aufteilungen zu ändern, schließen Sie die Nebenaktivität ab oder und dann mit einer neuen Konfiguration wieder auf der Seite starten.

Aktivität aus einem Split-to-Full-Fenster extrahieren

Erstellen Sie eine neue Konfiguration, die das vollständige Fenster der Nebenaktivität anzeigt, und Starten Sie dann die Aktivität mit einem Intent neu, der in dieselbe Instanz aufgelöst wird.

Unterstützung von Split während der Laufzeit prüfen

Das Einbetten von Aktivitäten wird ab Android 12L (API-Level 32) unterstützt, ist aber auch auf einigen Geräten mit früheren Plattformversionen verfügbar. Mit dem Attribut SplitController.splitSupportStatus oder der Methode SplitController.getSplitSupportStatus() können Sie während der Laufzeit prüfen, ob die Funktion verfügbar ist:

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 zusätzlich zum Aktivitäten-Stack gestartet (nach dem Einbettungsmodell ohne Aktivität).

Systemüberschreibung verhindern

Die Hersteller von Android-Geräten (Erstausrüster oder OEMs) können die Aktivitätseinbettung als Funktion des Gerätesystems implementieren. Die gibt das System Aufteilungsregeln für Apps mit mehreren Aktivitäten an, wodurch das Windowing überschrieben wird. Verhalten der Apps. Durch die Systemüberschreibung werden Apps mit mehreren Aktivitäten in einer systemdefinierten Aktivitätseinbettungsmodus.

Die Einbettung von Systemaktivitäten kann die App-Präsentation durch den Mehrfenstermodus verbessern Layouts wie list-detail ohne Änderungen an der App zu ändern. Die Aktivitätseinbettung des Systems führen auch zu falschen App-Layouts, Fehlern oder Konflikten mit der Aktivitätseinbettung. App implementiert werden.

Deine App kann die Einbettung von Systemaktivitäten verhindern oder zulassen, indem du eine property in der Manifestdatei der App angeben. Beispiel:

<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 Eigenschaftsname wird im WindowManager von Jetpack definiert. WindowProperties-Objekt. Setze den Wert auf false, wenn in deiner App Aktivitätseinbettungen implementiert sind oder wenn du anderweitig verhindern möchten, dass das System seine Aktivitätseinbettungsregeln anwendet. zu Ihrer App hinzufügen. Legen Sie den Wert auf true fest, damit das System diese anwenden kann systemdefinierten Aktivitäten in deine App einzubetten.

Einschränkungen und Vorbehalte

  • Nur die Host-App der Aufgabe, die als Eigentümer des Stamms identifiziert wurde Aktivität in der Aufgabe, können andere Aktivitäten organisieren und in die Aufgabe einbetten. Wenn Aktivitäten, die Einbettungen und Aufteilungen unterstützen, in einer Aufgabe ausgeführt werden, in eine andere Anwendung übertragen, dann funktionieren Einbettungen und Aufteilungen nicht. für diese Aktivitäten.
  • Aktivitäten können nur innerhalb einer Aufgabe organisiert werden. Aktivität starten in einer neuen Aufgabe immer in einem neuen maximierten Fenster bereits vorhandenen Aufteilungen.
  • Nur Aktivitäten im selben Prozess können organisiert und aufgeteilt werden. Die Der SplitInfo-Callback meldet nur Aktivitäten, die zum selben Prozess gehören. da es keine Möglichkeit gibt, etwas über Aktivitäten in verschiedenen Prozessen zu wissen.
  • Jede Paar- oder einzelne Aktivitätsregel gilt nur für Aktivitätsstarts, die nachdem die Regel registriert wurde. Derzeit gibt es keine Möglichkeit, vorhandene Aufteilungen oder ihre visuellen Eigenschaften zu aktualisieren.
  • Die Filterkonfiguration für aufgeteilte Paare muss mit den Intents übereinstimmen, die verwendet werden, wenn vollständig zu starten. Der Abgleich erfolgt an dem Punkt, an dem ein neuer die Aktivität während des Bewerbungsprozesses gestartet wird, Komponentennamen, die später im Systemprozess aufgelöst werden, impliziten Intents. Wenn der Name einer Komponente zum Zeitpunkt der Markteinführung nicht bekannt ist, wird ein Stattdessen kann ein Platzhalter („*/*“) verwendet werden. Die Filterung kann basierend auf auf Absichtsaktionen.
  • Es gibt derzeit keine Möglichkeit, Aktivitäten zwischen Containern oder in und aus zu verschieben von Aufteilungen nach ihrer Erstellung. Aufteilungen werden nur vom die WindowManager-Bibliothek verwenden, wenn neue Aktivitäten mit übereinstimmenden Regeln gestartet werden, Splits werden gelöscht, wenn die letzte Aktivität in einem Split-Container abgeschlossen.
  • Aktivitäten können neu gestartet werden, wenn sich die Konfiguration ändert. erstellt oder entfernt wird und sich die Aktivitätsgrenzen ändern, kann die Aktivität durch vollständiges Löschen der vorherigen Instanz und Erstellen der neuen. Daher sollten App-Entwickler vorsichtig sein mit Dingen wie dem Starten neuer Aktivitäten aus Lebenszyklus-Callbacks.
  • Geräte müssen die Oberfläche für Fenstererweiterungen enthalten, damit Aktivitäten eingebettet werden können. Fast alle Geräte mit großem Bildschirm mit Android 12L (API-Level 32) oder höher haben die Benutzeroberfläche. Auf einigen Geräten mit großen Bildschirmen, die nicht mehrere Aktivitäten ausführen können, wird die Oberfläche für Fenstererweiterungen jedoch nicht angezeigt. Wenn ein Gerät mit großem Bildschirm den Mehrfenstermodus nicht unterstützt, wird das Einbetten von Aktivitäten möglicherweise nicht unterstützt.

Weitere Informationen