6.4 Mehrere Apps gleichzeitig nutzen 

Grundsätzlich kennt Android mehrere Wege, Apps parallel auszuführen und anzuzeigen. Welche von ihnen zur Verfügung stehen, hängt von der Geräteklasse und teilweise vom Hersteller ab. Die meisten Smartphones und Tablets unterstützen einen Mehrfenstermodus. Ihn gibt es in unterschiedlichen Ausprägungen. Zum einen können zwei Anwendungen gleichzeitig über- und nebeneinander oder als Bild im Bild dargestellt werden. Darüber hinaus existiert noch ein Freeform genannter Modus. Er ermöglicht beliebig positionierbare, in ihrer Größe veränderliche Fenster. Was Sie bei der Entwicklung beachten müssen, damit Ihre App in diesen Modi optimal funktioniert, zeige ich Ihnen in diesem Abschnitt.
6.4.1 Zwei-App-Darstellung 

Um die Zwei-App-Darstellung (Splitscreen) zu aktivieren, ruft der Anwender die horizontal scrollbare Liste der kürzlich verwendeten Apps auf. Anschließend tippt er auf das App-Symbol oberhalb der Vorschau und bleibt mit dem Finger auf dem Bildschirm, bis ein Auswahlmenü erscheint. Mit Split screen wird der Bildschirm geteilt und man kann die zweite Anwendung auswählen. Ist der Zwei-App-Modus aktiv, teilt ein verschiebbarer schwarzer Balken den Bildschirm. Er rastet im oberen bzw. linken Drittel, in der Mitte und im unteren bzw. rechten Drittel ein. Wird er hingegen an den Bildschirmrand geschoben, beendet dies die Zwei-App-Darstellung.
Abbildung 6.6 Zwei-App-Modus aktivieren
Apps, die in der Datei build.gradle den API-Level 23 oder niedriger angeben, melden dem System automatisch, dass sie bei geteiltem Bildschirm möglicherweise nicht funktionieren. Bei Programmen ab targetSdkVersion = 24 geht Android hingegen davon aus, dass sie Mehrfenster-Unterstützung bieten. Ist dies nicht der Fall, müssen Apps mit android:resizeableActivity="false" mitteilen, dass sie das nicht tun. Das Attribut kann innerhalb des <application />-Tags verwendet werden (dann wirkt die Einstellung App-weit) und innerhalb von <activity /> (dann bezieht es sich auf eine bestimmte Activity). Apps für den Vollbildmodus funktionieren übrigens nicht im Splitscreen-Modus. Gleiches gilt für Anwendungen, die das automatische Drehen der Anzeige nicht unterstützen.
Die Mehrfenstermodi haben grundsätzlich keine Auswirkungen auf den Lebenszyklus von Activities. Sofern Ihre App Animationen oder Clips anzeigt, müssen Sie aber überlegen, wann diese gestartet und gestoppt werden. Bis einschließlich Android 9 war nur die Activity, mit der der Anwender zuletzt interagiert hat, aktiv (im Status resumed). Alle anderen Activities pausierten, auch wenn sie dabei ganz oder teilweise sichtbar waren. Bei der Zwei-App-Darstellung ergab sich das Problem, dass zu viele Apps Animationen in onResume() begonnen und onPause() beendet haben. Google hat deshalb mit Android Q das sogenannte Multi Resume eingeführt: Mehrere Activities können sich im Status resumed befinden. Damit Ihre App auch unter älteren Plattform-Versionen Mehrfenstermodi unterstützt, sollten Sie trotzdem onStart() und onStop() für das Starten und Stoppen von bewegten Inhalten nutzen. Sie können das anhand meines Beispiels MultiWindowDemo nachvollziehen. Listing 6.31 zeigt die Hauptklasse MainActivity.
package com.thomaskuenneth.androidbuch.multiwindowdemo
import android.content.Intent
import android.content.res.Configuration
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
private val TAG = MainActivity::class.simpleName
class MainActivity : AppCompatActivity() {
private val sb = StringBuilder()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
val intent = Intent(this, ChildActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT or
Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
}
override fun onStop() {
super.onStop()
animation.isEnabled = false
Log.d(TAG, "onStop()")
}
override fun onStart() {
super.onStart()
updateTextView()
animation.isEnabled = true
Log.d(TAG, "onStart()")
}
override fun onPictureInPictureModeChanged(
isInPictureInPictureMode: Boolean,
newConfig: Configuration?
) {
Log.d(
TAG, "onPictureInPictureModeChanged(): " +
isInPictureInPictureMode
)
}
override fun onMultiWindowModeChanged(
isInMultiWindowMode: Boolean,
newConfig: Configuration?
) {
Log.d(
TAG, "onMultiWindowModeChanged(): " +
isInMultiWindowMode
)
}
private fun updateTextView() {
sb.setLength(0)
sb.append("isInMultiWindowMode(): ")
.append(isInMultiWindowMode)
.append("\n")
sb.append("isInPictureInPictureMode(): ")
.append(isInPictureInPictureMode)
.append("\n")
textview.text = sb.toString()
}
}
Listing 6.31 Die Klasse »MainActivity«
In onCreate() wird die einfach gehaltene Benutzeroberfläche geladen und angezeigt. Sie besteht aus einem Textfeld, einer Animation sowie einer Schaltfläche. Klickt der Anwender auf Starten, so wird eine zweite Activity gestartet, die die aufrufende Aktivität üblicherweise vollständig verdeckt. Befand sich das Gerät aber im Zweifenstermodus, sieht der Bildschirm aus wie in Abbildung 6.7 dargestellt: Beide Activities sind dann gleichzeitig zu sehen.
Abbildung 6.7 Die App »MultiWindowDemo«
Beim Start einer neuen Activity mit startActivity() können Sie dem System mit intent.flags = Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT einen Hinweis geben, dass diese nach Möglichkeit neben bzw. unterhalb der aktuellen (aktiven) Activity angezeigt werden soll. Befindet sich das System im Splitscreen-Modus, versucht Android, die neue Activity entsprechend zu positionieren. Dann teilen sich die beiden Activities den Bildschirm. Allerdings ist nicht garantiert, dass dies erfolgreich ist, zum Beispiel weil die zu startende Activity den Fullscreen-Modus nutzt. Ist beim Start der Activity der Mehrfenstermodus nicht aktiv, hat FLAG_ACTIVITY_LAUNCH_ADJACENT keinen Effekt. Die Konstante kann nur in Verbindung mit FLAG_ACTIVITY_NEW_TASK verwendet werden.
Ob der Mehrfenstermodus aktiv ist, kann mit isInMultiWindowMode abgefragt werden. Möchte eine App bei Änderungen des Fenstermodus benachrichtigt werden, kann sie onPictureInPictureModeChanged() und onMultiWindowModeChanged() überschreiben. Die minimale Breite und Höhe im Freeform-Modus (dazu gleich mehr) und im Zweifenstermodus wird in der Manifestdatei mit dem Tag <layout /> und seinen Attributen android:minHeight und android:minWidth festgelegt. Verkleinert der Anwender im Splitscreen-Modus eine Activity über den hier gesetzten Wert hinaus, beschneidet das System die Größe der Activity entsprechend. Nur für den Freeform-Modus gelten die Attribute android:defaultWidth und android:defaultHeight (sie legen die Standardfenstergröße fest) und android:gravity (gibt die initiale Positionierung an).
6.4.2 Beliebig positionierbare Fenster 

Android bietet mit Freeform die beliebige Positionierbarkeit von Activities einschließlich des Veränderns ihrer Größe. Allerdings lässt sich dieses Verhalten nicht einfach freischalten, sondern muss vom Gerätehersteller konfiguriert werden. Ziele könnten dank der bereits vorhandenen und in Android 7 verfeinerten Maus- und Zeigerunterstützung Notebooks und Desktop-Systeme sein. Zum Zeitpunkt der Drucklegung gab es solche Hardware aber nur in Gestalt von Chrome OS-Geräten.[ 8 ](https://developer.android.com/topic/arc/optimizing) Der Emulator ließ sich nicht entsprechend konfigurieren. Eine ausführlichere Darstellung muss deshalb einer etwaigen späteren Auflage vorbehalten bleiben.