diff --git a/appdistribution/app/build.gradle b/appdistribution/app/build.gradle
index cb4c85c26..2f2ee4090 100644
--- a/appdistribution/app/build.gradle
+++ b/appdistribution/app/build.gradle
@@ -6,11 +6,11 @@ plugins {
android {
namespace 'com.google.firebase.appdistributionquickstart'
- compileSdk 33
+ compileSdk 34
defaultConfig {
applicationId "com.google.firebase.appdistributionquickstart"
minSdk 21 // minSdk would be 19 without compose
- targetSdk 33
+ targetSdk 34
versionCode 1
versionName "1.0"
@@ -66,7 +66,7 @@ dependencies {
implementation platform('com.google.firebase:firebase-bom:31.0.2')
// ADD the SDK to the "prerelease" variant only (example)
- implementation 'com.google.firebase:firebase-appdistribution-ktx:16.0.0-beta01'
+ implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta12'
// For an optimal experience using App Distribution, add the Firebase SDK
// for Google Analytics. This is recommended, but not required.
@@ -77,6 +77,7 @@ dependencies {
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.activity:activity-compose:1.5.1'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.4.1'
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
diff --git a/appdistribution/app/src/main/AndroidManifest.xml b/appdistribution/app/src/main/AndroidManifest.xml
index a29b19adf..f261af635 100644
--- a/appdistribution/app/src/main/AndroidManifest.xml
+++ b/appdistribution/app/src/main/AndroidManifest.xml
@@ -21,6 +21,12 @@
android:theme="@style/AppTheme">
+
+
+
diff --git a/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/EntryChoiceActivity.kt b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/EntryChoiceActivity.kt
index b8e0666f8..6fe85d44a 100644
--- a/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/EntryChoiceActivity.kt
+++ b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/EntryChoiceActivity.kt
@@ -4,20 +4,29 @@ import android.content.Intent
import com.firebase.example.internal.BaseEntryChoiceActivity
import com.firebase.example.internal.Choice
import com.google.firebase.appdistributionquickstart.java.MainActivity
+import com.google.firebase.appdistributionquickstart.kotlin.ComposeMainActivity
import com.google.firebase.appdistributionquickstart.kotlin.KotlinMainActivity
class EntryChoiceActivity : BaseEntryChoiceActivity() {
override fun getChoices(): List {
return listOf(
- Choice(
- "Java",
- "Run the Firebase App Distribution quickstart written in Java.",
- Intent(this, MainActivity::class.java)),
- Choice(
- "Kotlin",
- "Run the Firebase App Distribution quickstart written in Kotlin.",
- Intent(this, KotlinMainActivity::class.java))
- )
+ Choice(
+ "Java",
+ "Run the Firebase App Distribution quickstart written in Java.",
+ Intent(this, MainActivity::class.java)
+ ),
+ Choice(
+ "Kotlin",
+ "Run the Firebase App Distribution quickstart written in Kotlin.",
+ Intent(this, KotlinMainActivity::class.java)
+ ),
+ Choice(
+ "Compose",
+ "Run the Firebase App Distribution quickstart written in Compose.",
+ Intent(this, ComposeMainActivity::class.java),
+ ),
+
+ )
}
}
diff --git a/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/kotlin/AppDistributionViewModel.kt b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/kotlin/AppDistributionViewModel.kt
new file mode 100644
index 000000000..3aa373dd0
--- /dev/null
+++ b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/kotlin/AppDistributionViewModel.kt
@@ -0,0 +1,45 @@
+package com.google.firebase.appdistributionquickstart.kotlin
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.viewmodel.CreationExtras
+import com.google.firebase.Firebase
+import com.google.firebase.appdistribution.FirebaseAppDistribution
+import com.google.firebase.appdistribution.FirebaseAppDistributionException
+import com.google.firebase.appdistribution.appDistribution
+
+class AppDistributionViewModel(
+ val appDistribution: FirebaseAppDistribution
+) : ViewModel() {
+
+ companion object {
+ const val TAG = "AppDistribution-Quickstart"
+
+ // Used to inject this ViewModel's dependencies
+ // See also: https://developer.android.com/topic/libraries/architecture/viewmodel/viewmodel-factories
+ val Factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory {
+ @Suppress("UNCHECKED_CAST")
+ override fun create(
+ modelClass: Class,
+ extras: CreationExtras
+ ): T {
+ // Get instance.
+ val appDistribution = Firebase.appDistribution
+ return AppDistributionViewModel(appDistribution) as T
+ }
+ }
+ }
+
+ fun updateIfNewRelease() {
+ appDistribution.updateIfNewReleaseAvailable()
+ .addOnProgressListener { updateProgress ->
+ // (Optional) Implement custom progress updates in addition to
+ // automatic NotificationManager updates.
+ }
+ .addOnFailureListener { e ->
+ if (e is FirebaseAppDistributionException) {
+ // Handle exception.
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/kotlin/ComposeMainActivity.kt b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/kotlin/ComposeMainActivity.kt
new file mode 100644
index 000000000..5977d5a17
--- /dev/null
+++ b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/kotlin/ComposeMainActivity.kt
@@ -0,0 +1,114 @@
+package com.google.firebase.appdistributionquickstart.kotlin
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Scaffold
+import androidx.compose.material.Surface
+import androidx.compose.material.Text
+import androidx.compose.material.TopAppBar
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalLifecycleOwner
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.viewmodel.compose.viewModel
+import com.google.firebase.appdistributionquickstart.R
+import com.google.firebase.appdistributionquickstart.ui.theme.AppDistributionTheme
+
+
+class ComposeMainActivity : ComponentActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContent {
+ AppDistributionTheme {
+ Surface(
+ modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background
+ ) {
+ MainAppView()
+ }
+ }
+ }
+ }
+}
+
+@Composable
+fun MainAppView(
+ appDistributionViewModel: AppDistributionViewModel = viewModel(factory = AppDistributionViewModel.Factory)
+) {
+
+ ComposableLifecycle { source, event ->
+ if (event == Lifecycle.Event.ON_RESUME) {
+ appDistributionViewModel.updateIfNewRelease()
+ }
+ }
+
+
+ Scaffold(topBar = {
+ TopAppBar(
+ backgroundColor = colorResource(R.color.colorPrimary)
+ ) {
+ Text(
+ text = stringResource(R.string.app_name),
+ style = MaterialTheme.typography.h6,
+ textAlign = TextAlign.Center,
+ modifier = Modifier.padding(8.dp),
+ color = Color.White
+ )
+ }
+ }, content = { it ->
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier
+ .fillMaxSize()
+ .padding(it)
+ ) {
+ Spacer(modifier = Modifier.height(30.dp))
+ Image(
+ painterResource(R.drawable.firebase_lockup_400),
+ contentDescription = "Firebase logo",
+ contentScale = ContentScale.Crop,
+ )
+ Text(
+ text = stringResource(R.string.textview_text), modifier = Modifier.padding(8.dp)
+ )
+ }
+ })
+}
+
+@Composable
+fun ComposableLifecycle(
+ lifeCycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
+ onEvent: (LifecycleOwner, Lifecycle.Event) -> Unit
+) {
+ DisposableEffect(lifeCycleOwner) {
+ val observer = LifecycleEventObserver { source, event ->
+ onEvent(source, event)
+ }
+ lifeCycleOwner.lifecycle.addObserver(observer)
+ onDispose {
+ lifeCycleOwner.lifecycle.removeObserver(observer)
+ }
+ }
+}
\ No newline at end of file
diff --git a/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/ui/theme/Color.kt b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/ui/theme/Color.kt
new file mode 100644
index 000000000..3e95f9409
--- /dev/null
+++ b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/ui/theme/Color.kt
@@ -0,0 +1,11 @@
+package com.google.firebase.appdistributionquickstart.ui.theme
+
+import androidx.compose.ui.graphics.Color
+
+val Purple80 = Color(0xFFD0BCFF)
+val PurpleGrey80 = Color(0xFFCCC2DC)
+val Pink80 = Color(0xFFEFB8C8)
+
+val FirebaseBlue = Color(0xFF0288D1) // copied from colors.xml
+val FirebaseBannerBlue = Color(0xFF039BE5) // copied from colors.xml
+val FirebaseOrange = Color(0xFFFFA000) // copied from colors.xml
\ No newline at end of file
diff --git a/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/ui/theme/Shape.kt b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/ui/theme/Shape.kt
new file mode 100644
index 000000000..cb3013c77
--- /dev/null
+++ b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/ui/theme/Shape.kt
@@ -0,0 +1,11 @@
+package com.google.firebase.appdistributionquickstart.ui.theme
+
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.Shapes
+import androidx.compose.ui.unit.dp
+
+val Shapes = Shapes(
+ small = RoundedCornerShape(16.dp),
+ medium = RoundedCornerShape(2.dp),
+ large = RoundedCornerShape(0.dp)
+)
\ No newline at end of file
diff --git a/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/ui/theme/Theme.kt b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/ui/theme/Theme.kt
new file mode 100644
index 000000000..23c43e59d
--- /dev/null
+++ b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/ui/theme/Theme.kt
@@ -0,0 +1,39 @@
+package com.google.firebase.appdistributionquickstart.ui.theme
+
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.darkColors
+import androidx.compose.material.lightColors
+
+import androidx.compose.runtime.Composable
+
+private val DarkColorPalette = darkColors(
+ primary = Purple80,
+ primaryVariant = PurpleGrey80,
+ secondary = Pink80
+)
+
+private val LightColorPalette = lightColors(
+ primary = FirebaseBlue,
+ primaryVariant = FirebaseBannerBlue,
+ secondary = FirebaseOrange
+)
+
+@Composable
+fun AppDistributionTheme(
+ darkTheme: Boolean = isSystemInDarkTheme(),
+ content: @Composable () -> Unit
+) {
+ val colors = if (darkTheme) {
+ DarkColorPalette
+ } else {
+ LightColorPalette
+ }
+
+ MaterialTheme(
+ colors = colors,
+ typography = Typography,
+ shapes = Shapes,
+ content = content
+ )
+}
\ No newline at end of file
diff --git a/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/ui/theme/Type.kt b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/ui/theme/Type.kt
new file mode 100644
index 000000000..d64c4bb93
--- /dev/null
+++ b/appdistribution/app/src/main/java/com/google/firebase/appdistributionquickstart/ui/theme/Type.kt
@@ -0,0 +1,18 @@
+package com.google.firebase.appdistributionquickstart.ui.theme
+
+import androidx.compose.material.Typography
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.sp
+
+// Set of Material typography styles to start with
+val Typography = Typography(
+ body1 = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ letterSpacing = 0.5.sp
+ )
+)
\ No newline at end of file
diff --git a/appdistribution/build.gradle b/appdistribution/build.gradle
index 64c31555c..0421ce3df 100644
--- a/appdistribution/build.gradle
+++ b/appdistribution/build.gradle
@@ -2,6 +2,10 @@
buildscript {
+ ext {
+ compose_version = '1.2.1'
+ }
+
repositories {
mavenLocal()
google()
diff --git a/appdistribution/gradle.properties b/appdistribution/gradle.properties
index aac7c9b46..c79c84715 100644
--- a/appdistribution/gradle.properties
+++ b/appdistribution/gradle.properties
@@ -15,3 +15,4 @@ org.gradle.jvmargs=-Xmx1536m
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
+android.useAndroidX=true
\ No newline at end of file