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
5 changes: 3 additions & 2 deletions CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
* @yrezgui @kkuan2011
/compose/ @android/devrel-compose
/ai/ @android/devrel-ai
/car/ @android/devrel-car
/compose/ @android/devrel-compose
/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/ @android/devrel-adaptive-apps
/watchface/ @android/devrel-wear
/wear/ @android/devrel-wear
/wearcompanion/ @android/devrel-wear
/xr/ @android/devrel-xr
/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/ @android/devrel-adaptive-apps
93 changes: 93 additions & 0 deletions ai/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.ksp)
alias(libs.plugins.hilt)
alias(libs.plugins.compose.compiler)
}

android {
compileSdk = libs.versions.compileSdk.get().toInt()
namespace = "com.example.snippets"
Copy link
Contributor

Choose a reason for hiding this comment

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

can we pick a more specific name to ai?


defaultConfig {
applicationId = "com.example.snippets"
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

kotlin {
jvmToolchain(17)
}

buildTypes {
getByName("debug") {
signingConfig = signingConfigs.getByName("debug")
}

getByName("release") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
buildFeatures {
compose = true
// Disable unused AGP features
viewBinding = true
}

}
dependencies {
Copy link
Contributor

Choose a reason for hiding this comment

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

are all these dependencies needed for the ai module? can we omit the ones that are not needed?

val composeBom = platform(libs.androidx.compose.bom)
implementation(composeBom)
androidTestImplementation(composeBom)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.activity.compose)

implementation(libs.androidx.appfunctions)
implementation(libs.androidx.appfunctions.service)
ksp(libs.androidx.appfunctions.compiler)

implementation(libs.androidx.compose.runtime)
implementation(libs.androidx.compose.foundation)
implementation(libs.androidx.compose.foundation.layout)
implementation(libs.androidx.compose.ui.util)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.media3.common)
implementation(libs.androidx.media3.exoplayer)
implementation(libs.androidx.tracing)
implementation(libs.androidx.work.runtime)

implementation(libs.hilt.android)
implementation(libs.androidx.hilt.navigation.compose)
implementation(libs.kotlinx.serialization.json)
ksp(libs.hilt.compiler)
ksp(libs.kotlinx.metadata.jvm)

implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.lifecycle.runtime)
implementation(libs.androidx.window)
implementation(libs.androidx.startup.runtime)
implementation(libs.androidx.window.java)
implementation(libs.appcompat)
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.ai)
implementation(libs.guava.android)
implementation(libs.reactive.streams)
testImplementation(libs.junit)
testImplementation(kotlin("test"))
androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.core)
androidTestImplementation(libs.androidx.test.runner)
androidTestImplementation(libs.androidx.test.espresso.core)
}
21 changes: 21 additions & 0 deletions ai/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
Copy link
Contributor

Choose a reason for hiding this comment

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

is this proguard file deprecated now? can we remove it?

# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.kts.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2025 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.example.snippets;
Copy link
Contributor

Choose a reason for hiding this comment

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

should we specify a more specific pacakge? like com.example.snippets.ai?


import androidx.appcompat.app.AppCompatActivity;
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import org.junit.Rule;
import org.junit.Test;
import static org.junit.Assert.assertFalse;

public class DeviceCompatibilityModeTestJavaSnippets {
Copy link
Contributor

Choose a reason for hiding this comment

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

is this an AI snippet?


// [START android_device_compatibility_mode_assert_isLetterboxed_java]
@Rule
public ActivityScenarioRule<MainActivity> rule = new ActivityScenarioRule<>(MainActivity.class);

@Test
public void activity_launched_notLetterBoxed() {
try (ActivityScenario<MainActivity> scenario =
ActivityScenario.launch(MainActivity.class)) {
scenario.onActivity( activity -> {
assertFalse(activity.isLetterboxed());
});
}
}
// [END android_device_compatibility_mode_assert_isLetterboxed_java]


Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: we can remove these comments like these since it's implied and remove the extra blank lines too

// Class used by snippets.

class MainActivity extends AppCompatActivity {
public boolean isLetterboxed() {
return true;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2025 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.example.snippets

import androidx.appcompat.app.AppCompatActivity
import androidx.test.ext.junit.rules.ActivityScenarioRule
import org.junit.Assert.assertFalse
import org.junit.Rule
import org.junit.Test

class DeviceCompatibilityModeTestKotlinSnippets {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comments in this class as in DeviceCompatibilityModeTestJavaSnippets


// [START android_device_compatibility_mode_assert_isLetterboxed_kotlin]
@get:Rule
val activityRule = ActivityScenarioRule(MainActivity::class.java)

@Test
fun activity_launched_notLetterBoxed() {
activityRule.scenario.onActivity {
assertFalse(it.isLetterboxed())
}
}
// [END android_device_compatibility_mode_assert_isLetterboxed_kotlin]

// Class used by snippets.

class MainActivity : AppCompatActivity() {
fun isLetterboxed(): Boolean {
return true
}
}
}
52 changes: 52 additions & 0 deletions ai/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2025 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<permission android:name="com.example.snippets.CUSTOM_PERMISSION"/>

<!--[START android_broadcast_receiver_10_manifest_permission]-->
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need these region tags in the manifest file? we generally discourage doing so, and just hardcode any manifest snippets in the markdown file

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!--[END android_broadcast_receiver_10_manifest_permission]-->

<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Snippets">
<activity
android:name="com.example.snippets.MainActivity"
android:exported="true"
android:theme="@style/Theme.Snippets">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="com.example.snippets.androidx-startup"
android:exported="false">
<meta-data
android:name="com.example.snippets.ActivityEmbeddingKotlinSnippets.SplitInitializer"
android:value="androidx.startup" />
<meta-data
android:name="com.example.snippets.ActivityEmbeddingJavaSnippets.SplitInitializer"
android:value="androidx.startup" />
</provider>
</application>

</manifest>
57 changes: 57 additions & 0 deletions ai/src/main/java/com/example/snippets/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2024 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.example.snippets
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we use a more specific package name?


import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.example.snippets.navigation.LandingScreen
import com.example.snippets.ui.theme.SnippetsTheme
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
SnippetsTheme {
val navController = rememberNavController()
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this activity show any AI-specific content? Maybe we should just have it display a more simple screen or Text field, so we don't add more Nav2 code to the repo.

// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
NavHost(navController, startDestination = "LandingScreen") {
composable("LandingScreen") {
LandingScreen { navController.navigate(it.route) }
}
}
}
}
}
}
}
21 changes: 21 additions & 0 deletions ai/src/main/java/com/example/snippets/navigation/Destination.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright 2024 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.example.snippets.navigation

enum class Destination(val route: String, val title: String) {
Copy link
Contributor

Choose a reason for hiding this comment

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

can we move this into the file that uses Destination?

// Add your example here
}
Loading
Loading