Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: 🤖 Apply Spotless formatting
file_pattern: '**/*.kt **/*.kts **/*.java **/*.xml'
file_pattern: '**/*.kt **/*.kts **/*.xml'

- name: Build debug APK
run: ./gradlew assembleDebug --no-configuration-cache
Expand Down
68 changes: 37 additions & 31 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
alias(libs.plugins.jetbrains.kotlin.serialization)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.google.gms.google.services)
alias(libs.plugins.hilt.plugin)
alias(libs.plugins.jetbrains.kotlin.android)
alias(libs.plugins.jetbrains.kotlin.serialization)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am curious why this import re-ordering isn't something that Detekt in the github action picked up. Did you run manually?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a pre-push or even pre-commit hook. For now its manual.

alias(libs.plugins.ksp)
alias(libs.plugins.compose.compiler)
}

android {
Expand All @@ -42,63 +45,66 @@ android {

buildTypes {
release {
isMinifyEnabled = false
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}
create("benchmark") {
initWith(buildTypes.getByName("release"))
signingConfig = signingConfigs.getByName("debug")
matchingFallbacks += listOf("release")
isDebuggable = false
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
kotlin {
compilerOptions { jvmTarget.set(JvmTarget.JVM_17) }
}
buildFeatures {
compose = true
}
}

dependencies {

androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.ui.test.junit4)
androidTestImplementation(platform(libs.androidx.compose.bom))
debugImplementation(libs.androidx.ui.test.manifest)
debugImplementation(libs.androidx.ui.tooling)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
implementation(libs.androidx.navigation.compose)
implementation(libs.kotlinx.serialization.json)
implementation(libs.androidx.navigation.runtime.ktx)
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.firebase.ai)
implementation(libs.hilt.android)
implementation(libs.hilt.navigation.compose)
implementation(libs.kotlinx.serialization.json)
implementation(platform(libs.androidx.compose.bom))
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.ai)
ksp(libs.hilt.compiler)

implementation(project(":ui-component"))
implementation(project(":samples:gemini-multimodal"))
implementation(project(":samples:gemini-chatbot"))
implementation(project(":samples:genai-summarization"))
implementation(project(":samples:gemini-image-chat"))
implementation(project(":samples:gemini-live-todo"))
implementation(project(":samples:gemini-multimodal"))
implementation(project(":samples:gemini-video-metadata-creation"))
implementation(project(":samples:gemini-video-summarization"))
implementation(project(":samples:genai-image-description"))
implementation(project(":samples:genai-summarization"))
implementation(project(":samples:genai-writing-assistance"))
implementation(project(":samples:imagen"))
implementation(project(":samples:imagen-editing"))
implementation(project(":samples:magic-selfie"))
implementation(project(":samples:gemini-video-summarization"))
implementation(project(":samples:gemini-live-todo"))
implementation(project(":samples:gemini-video-metadata-creation"))
implementation(project(":samples:gemini-image-chat"))

implementation(project(":ui-component"))
ksp(libs.hilt.compiler)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
}
21 changes: 0 additions & 21 deletions app/proguard-rules.pro

This file was deleted.

16 changes: 10 additions & 6 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,31 @@
<uses-permission android:name="android.permission.RECORD_AUDIO" />

<application
android:name=".CatalogApplication"
android:allowBackup="true"
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.AISampleCatalog"
tools:targetApi="31"
android:name=".CatalogApplication"
android:enableOnBackInvokedCallback="true"
>
tools:targetApi="31">
<profileable
android:shell="true"
tools:targetApi="29" />

<activity
android:name=".MainActivity"
android:exported="true"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.AISampleCatalog">
android:theme="@style/Theme.AISampleCatalog"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,14 @@ val sampleCatalog = listOf(
)

data class SampleCatalogItem(
@StringRes val title: Int,
@StringRes val description: Int,
@param:StringRes val title: Int,
@param:StringRes val description: Int,
val route: String,
val sampleEntryScreen: @Composable () -> Unit,
val tags: List<SampleTags> = emptyList(),
val needsFirebase: Boolean = false,
val isFeatured: Boolean = false,
@DrawableRes val keyArt: Int? = null,
@param:DrawableRes val keyArt: Int? = null,
)

enum class SampleTags(
Expand Down
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
85 changes: 85 additions & 0 deletions benchmark/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright 2026 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

/*
* Copyright 2026 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
plugins {
alias(libs.plugins.android.test)
alias(libs.plugins.jetbrains.kotlin.android)
}

android {
namespace = "com.android.ai.catalog.benchmark"
compileSdk {
version = release(36)
}

defaultConfig {
minSdk = 24
targetSdk = 36

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
// This benchmark buildType is used for benchmarking, and should function like your
// release build (for example, with minification on). It"s signed with a debug key
// for easy local/CI testing.
create("benchmark") {
isDebuggable = true
signingConfig = getByName("debug").signingConfig
matchingFallbacks += listOf("release")
}
}

targetProjectPath = ":app"
experimentalProperties["android.experimental.self-instrumenting"] = true

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlin {
compilerOptions { jvmTarget.set(JvmTarget.JVM_17) }
}
}

dependencies {
implementation(libs.androidx.junit)
implementation(libs.androidx.espresso.core)
implementation(libs.androidx.uiautomator)
implementation(libs.androidx.benchmark.macro.junit4)
}

androidComponents {
beforeVariants(selector().all()) {
it.enable = it.buildType == "benchmark"
}
}
1 change: 1 addition & 0 deletions benchmark/src/main/AndroidManifest.xml
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove this, if we don't need it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even without manual content the AndroidManifest will be populated by tools. As part of that the empty file needs to exist.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<manifest />
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2026 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ai.catalog.benchmark

import androidx.benchmark.macro.StartupMode
import androidx.benchmark.macro.StartupTimingMetric
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

/**
* Benchmark class to measure the startup timing of the application.
*
* This benchmark uses [MacrobenchmarkRule] to measure the time it takes for the application
* to start up in [StartupMode.COLD] mode.
*/
@RunWith(AndroidJUnit4::class)
class StartupBenchmark {
@get:Rule
val benchmarkRule = MacrobenchmarkRule()

/**
* Measures the application startup time.
*
* It runs the benchmark for 5 iterations using [StartupTimingMetric].
* The application is started in [StartupMode.COLD] mode, ensuring a fresh start for each iteration.
*/
@Test
fun startup() = benchmarkRule.measureRepeated(
packageName = "com.android.ai.catalog",
metrics = listOf(StartupTimingMetric()),
iterations = 5,
startupMode = StartupMode.COLD,
) {
startApp(packageName)
}
}
8 changes: 7 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ plugins {
alias(libs.plugins.ksp) apply false
alias(libs.plugins.compose.compiler) apply false
alias(libs.plugins.spotless) apply false
alias(libs.plugins.android.test) apply false
}

subprojects {
Expand All @@ -43,5 +44,10 @@ subprojects {
// Look for the first line that doesn't have a block comment (assumed to be the license)
licenseHeaderFile(rootProject.file("spotless/copyright.kt"), "(^(?![\\/ ]\\*).*$)")
}
format("toml") {
target("gradle/libs.versions.toml")
prettier(mapOf("prettier" to "3.2.5", "prettier-plugin-toml" to "2.0.1"))
.config(mapOf("plugins" to listOf("prettier-plugin-toml")))
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

}
}
}
Loading
Loading