Skip to content

Compose code for App Distribution #1630

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions appdistribution/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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.
Expand All @@ -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'
Expand Down
6 changes: 6 additions & 0 deletions appdistribution/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
android:theme="@style/AppTheme">
</activity>

<activity
android:name=".kotlin.ComposeMainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme">
</activity>

<activity android:name=".EntryChoiceActivity"
android:exported="true">
<intent-filter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Choice> {
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),
),

)
}
}
Original file line number Diff line number Diff line change
@@ -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 <T : ViewModel> create(
modelClass: Class<T>,
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.
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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)
)
Original file line number Diff line number Diff line change
@@ -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
)
}
Original file line number Diff line number Diff line change
@@ -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
)
)
4 changes: 4 additions & 0 deletions appdistribution/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

buildscript {

ext {
compose_version = '1.2.1'
}

repositories {
mavenLocal()
google()
Expand Down
1 change: 1 addition & 0 deletions appdistribution/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading