ReviewFlow 0.2.0 ist veröffentlicht und unterstützt jetzt Kotlin Multiplatform. Meine bisherige Android-Bibliothek für In-App Reviews erhält damit einen gemeinsamen Kern für Android und iOS. Regeln für den passenden Zeitpunkt, Wartezeiten zwischen Anfragen und die Begrenzung pro App-Version lassen sich in Kotlin gemeinsam nutzen. Die eigentliche Bewertungsanfrage läuft weiterhin über Google Play beziehungsweise StoreKit.

Das Release 0.2.0 auf GitHub erweitert damit den Ansatz aus meinem ersten Artikel zu Android Review Flow bei creative workline: Bewertungsanfragen gehören in eine klar geregelte, testbare Komponente. Für Teams mit Android- und iOS-App muss diese Logik nun nicht mehr zweimal implementiert werden.

Read this article in English on creativeworkline.at.

Was ist ReviewFlow?

ReviewFlow ist eine Open-Source-Bibliothek, die In-App-Bewertungsanfragen koordiniert. Sie prüft, ob die App eine Anfrage starten darf, speichert Nutzungszähler und Wartezeiten und verhindert parallele Anfragen innerhalb einer Instanz. Zustände und Ereignisse sind über Kotlin Flows beobachtbar.

Ein typischer Anlass ist ein erfolgreich abgeschlossener Export oder eine gespeicherte Aufgabe. Die App meldet diesen Nutzungsmoment; ReviewFlow prüft die konfigurierten Regeln. Der normale Ablauf der App geht auch dann weiter, wenn kein Bewertungsdialog erscheint.

Was mit Version 0.2.0 gemeinsam wird

Der neue plattformneutrale Einstiegspunkt heißt ReviewFlow. Er bündelt die Regeln und die Zustandssteuerung im KMP-Kern. Die Anbindung an das Betriebssystem und die lokale Speicherung übernehmen die jeweiligen Plattformadapter.

BereichGemeinsam oder plattformspezifisch?
App-Starts, Erfolgsmomente, Cooldown und VersionsregelGemeinsame Kotlin-Logik
Koordination paralleler Anfragen, Zustände und EreignisseGemeinsame Kotlin-Logik
Bewertungsanfrage auf AndroidGoogle Play In-App Review API
Bewertungsanfrage auf iOSStoreKit über eine kleine Swift-Brücke
PersistenzDataStore auf Android, UserDefaults auf iOS
Optionale Compose-HelferWeiterhin Android-spezifisch

Die Dokumentation zu Version 0.2.0 beschreibt diese Aufteilung und die Integrationswege. Gemeinsame Logik bedeutet hier auch keine Synchronisierung zwischen Geräten: Zähler und Cooldowns bleiben lokal in der jeweiligen App-Installation.

Für Produktteams liegt der Nutzen in einer zentralen Regelbasis. Wenn eine Anfrage künftig erst nach mehreren abgeschlossenen Vorgängen sinnvoll ist, lässt sich diese Entscheidung im gemeinsamen Code pflegen und testen. Die Oberflächen können weiterhin mit Jetpack Compose auf Android und SwiftUI auf iOS umgesetzt sein.

Einstieg im KMP-Projekt

In einem bestehenden KMP-Modul wird der Core in commonMain eingebunden. Voraussetzung ist, dass Maven Central in der Repository-Konfiguration des Projekts verfügbar ist:

kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation("com.zleptnig:reviewflow-core:0.2.0")
        }
    }
}

Die Plattforminitialisierung erzeugt anschließend eine ReviewFlow-Instanz und übergibt sie an den gemeinsamen Anwendungscode. Der folgende Ausschnitt zeigt nur die Aufrufstellen; die Einrichtung der Plattformadapter und des Coroutine-Scopes gehört zur jeweiligen App:

import com.zleptnig.reviewflow.core.ReviewFlow

class ReviewTriggers(private val reviewFlow: ReviewFlow) {
    // Einmal pro kaltem App-Start aufrufen.
    suspend fun onColdStart() {
        reviewFlow.onAppStart()
    }

    // Erst nach einem erfolgreich abgeschlossenen Export aufrufen.
    suspend fun onExportCompleted() {
        reviewFlow.onSuccessMoment()
        reviewFlow.tryRequest()
    }
}

Das Beispiel trennt App-Start und Erfolgsmoment bewusst: Ein Export darf nicht zusätzlich als App-Start gezählt werden. Ebenso sollte ein Wechsel aus dem Hintergrund nicht automatisch den Startzähler erhöhen.

Die Standardregeln sind mindestens drei App-Starts, mindestens ein Erfolgsmoment, 30 Tage Cooldown und höchstens ein abgeschlossener Plattformrequest pro App-Version. Diese Werte sind konfigurierbar. Sie beschreiben die Regeln der Bibliothek, nicht die Quoten von Google oder Apple.

iOS: gemeinsame Regeln, native StoreKit-Anfrage

Auf iOS wird die Instanz über IosReviewFlow erstellt. Die App implementiert dafür IosReviewRequest in Swift und exportiert den Core über ihr eigenes KMP-Framework. Die dokumentierte Brücke verwendet AppStore.requestReview(in:) mit einer aktiven UIWindowScene und setzt iOS 16 oder neuer voraus.

Die Swift-Brücke im Repository zeigt die vollständige Anbindung. Sie prüft zuerst, ob eine Szene im Vordergrund verfügbar ist. Fehlt dieser Kontext, meldet sie die Anfrage als nicht verfügbar zurück. Dadurch werden weder Cooldown noch Versionsfreigabe verbraucht. Der Kotlin-Adapter führt den Aufruf auf dem Main Dispatcher aus.

Für den praktischen Einstieg enthält das Projekt außerdem eine native SwiftUI-Demo. Sie zeigt Zustände und Ereignisse, persistierte Zähler sowie einen StoreKit-Modus und simulierte Ergebnisse. Damit lassen sich Integrationsfälle nachvollziehen, ohne jede Prüfung von einem sichtbaren Store-Dialog abhängig zu machen.

Bestehende Android-Apps können ihre API behalten

Die Umstellung des Bibliothekskerns auf KMP erzwingt keine KMP-Migration der konsumierenden Android-App. Für eine bestehende Core-Integration wird die Version aktualisiert:

implementation("com.zleptnig:reviewflow-core:0.2.0")

ReviewOrchestrator.create(context), onAppStart(), onSuccessMoment() und tryShow(activity) bleiben verfügbar. Auch der bisherige DataStore-Name und seine Schlüssel werden beibehalten, damit vorhandene Zähler, Cooldowns und Versionsinformationen das Update überstehen.

Für Android mit Jetpack Compose gibt es weiterhin das optionale Modul:

implementation("com.zleptnig:reviewflow-compose:0.2.0")

Dieses bringt den Core bereits mit und enthält unter anderem rememberReviewOrchestrator() und ReviewEffect. reviewflow-compose bleibt Android-spezifisch; die KMP-Erweiterung betrifft reviewflow-core. Die Bibliothek benötigt auf Android mindestens API 23, das Compose-Modul außerdem compileSdk 36.

Ein abgeschlossener Request ist keine abgegebene Bewertung

Die wichtigste Grenze bleibt auf beiden Plattformen bestehen: ReviewFlow kontrolliert den Zeitpunkt des eigenen Aufrufs. Ob ein Dialog angezeigt wird, entscheidet die Plattform.

In der neuen API heißt das entsprechende Ereignis deshalb ReviewFlowEvent.RequestCompleted. Ein Rückgabewert von true bei tryRequest() bestätigt den abgeschlossenen Plattformaufruf. Er belegt weder einen sichtbaren Dialog noch eine abgegebene Bewertung. Der ältere Android-Ereignisname ReviewEvent.Shown bleibt aus Kompatibilitätsgründen erhalten und hat ebenfalls keine solche Aussagekraft.

Für die UX heißt das: Eine Bewertungsanfrage darf keinen wichtigen Arbeitsschritt blockieren. Google empfiehlt außerdem, den In-App-Dialog nicht an einen expliziten Bewertungsbutton zu hängen, weil nach dem Tippen möglicherweise nichts erscheint. Details stehen in den Google-Play-Richtlinien für In-App Reviews; Apple erläutert den Plattformablauf unter Requesting App Store reviews.

Testbare Regeln statt Tests auf einen sichtbaren Dialog

Die gemeinsame API nimmt austauschbare Komponenten entgegen: ReviewPresenter, ReviewStateStore, AppVersionProvider und Clock. Damit kann ein Test beispielsweise die Zeit kontrolliert vorsetzen oder eine nicht verfügbare Präsentation simulieren.

Sinnvolle Prüfungen betreffen die eigene Logik: Wird eine Anfrage vor dem dritten Start abgewiesen? Greift die Versionsregel nach einem abgeschlossenen Request? Wird eine gleichzeitige zweite Anfrage sofort verworfen? Bleibt ein späterer Versuch möglich, wenn gerade kein gültiger Darstellungskontext vorhanden ist?

Diese Trennung ist auch über Bewertungsanfragen hinaus interessant. Kotlin Multiplatform lässt sich für klar abgegrenzte Funktionen einsetzen, während Plattformintegration und UI nativ bleiben. ReviewFlow 0.2.0 zeigt dieses Muster an einer kleinen, konkreten Aufgabe. Die Bibliothek steht unter Apache-2.0-Lizenz und enthält selbst keine Analytics- oder Tracking-SDKs.

Häufige Fragen

Muss eine bestehende Android-App für ReviewFlow 0.2.0 auf KMP umgestellt werden?

Nein. Die Android-API aus 0.1.x bleibt verfügbar. Bestehende Integrationen können die Dependency auf 0.2.0 aktualisieren und ReviewOrchestrator weiterverwenden.

Ist reviewflow-compose jetzt eine Compose-Multiplatform-Bibliothek?

Nein. reviewflow-core ist der gemeinsame KMP-Kern für Android und iOS. reviewflow-compose bleibt eine optionale Android-Erweiterung für Jetpack Compose.

Garantiert ReviewFlow, dass ein Bewertungsdialog erscheint?

Nein. Google Play und StoreKit entscheiden über die Anzeige. Ein erfolgreicher Request bestätigt den Abschluss des Plattformaufrufs, nicht die Anzeige oder Abgabe einer Bewertung.

Den Quellcode, Integrationsbeispiele und das Release finden Sie im ReviewFlow-Repository auf GitHub. Wenn Sie gemeinsame Kotlin-Logik in einer bestehenden App einsetzen möchten, unterstütze ich Sie bei App-Architektur und schrittweiser KMP-Integration.