diff --git a/AGENT.md b/AGENT.md deleted file mode 100644 index efb39ef19..000000000 --- a/AGENT.md +++ /dev/null @@ -1,58 +0,0 @@ -# Now in Android Project - -Now in Android is a native Android mobile application written in Kotlin. It provides regular news -about Android development. Users can choose to follow topics, be notified when new content is -available, and bookmark items. - -## Architecture - -This project is a modern Android application that follows the official architecture guidance from Google. It is a reactive, single-activity app that uses the following: - -- **UI:** Built entirely with Jetpack Compose, including Material 3 components and adaptive layouts for different screen sizes. -- **State Management:** Unidirectional Data Flow (UDF) is implemented using Kotlin Coroutines and `Flow`s. `ViewModel`s act as state holders, exposing UI state as streams of data. -- **Dependency Injection:** Hilt is used for dependency injection throughout the app, simplifying the management of dependencies and improving testability. -- **Navigation:** Navigation is handled by Jetpack Navigation 2 for Compose, allowing for a declarative and type-safe way to navigate between screens. -- **Data:** The data layer is implemented using the repository pattern. - - **Local Data:** Room and DataStore are used for local data persistence. - - **Remote Data:** Retrofit and OkHttp are used for fetching data from the network. -- **Background Processing:** WorkManager is used for deferrable background tasks. - -## Modules - -The main Android app lives in the `app/` folder. Feature modules live in `feature/` and core and shared modules in `core/`. - -## Commands to Build & Test - -The app and Android libraries have two product flavors: `demo` and `prod`, and two build types: `debug` and `release`. - -- Build: `./gradlew assemble{Variant}`. Typically `assembleDemoDebug`. -- Fix linting/formatting: `./gradlew --init-script gradle/init.gradle.kts spotlessApply` -- Run local tests: `./gradlew {variant}Test` -- Run single test: `./gradlew {variant}Test --tests "com.example.myapp.MyTestClass"` -- Run local screenshot tests: `./gradlew verifyRoborazziDemoDebug` - -### Instrumented tests - -- Gradle-managed devices to run on device tests: `./gradlew pixel6api31aospDebugAndroidTest`. Also `pixel4api30aospatdDebugAndroidTest` and `pixelcapi30aospatdDebugAndroidTest`. - -### Creating tests - -#### Instrumented tests - -- Tests for UI features should only use `ComposeTestRule` with a `ComponentActivity`. -- Bigger tests live in the `:app` module and they can start activities like `MainActivity`. - -#### Local tests - -- [kotlinx.coroutines](https://github.com/Kotlin/kotlinx.coroutines) for most assertions -- [cashapp/turbine](https://github.com/cashapp/turbine) for complex coroutine tests -- [google/truth](https://github.com/google/truth) for assertions - -## Continuous integration - -- The workflows are defined in `.github/workflows/*.yaml` and they contain various checks. -- Screenshot tests are generated by CI, so they shouldn't be checked into the repo from a workstation. - -## Version control and code location - -- The project uses git and is hosted in https://github.com/android/nowinandroid. diff --git a/AGENT.md b/AGENT.md new file mode 120000 index 000000000..47dc3e3d8 --- /dev/null +++ b/AGENT.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..efb39ef19 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,58 @@ +# Now in Android Project + +Now in Android is a native Android mobile application written in Kotlin. It provides regular news +about Android development. Users can choose to follow topics, be notified when new content is +available, and bookmark items. + +## Architecture + +This project is a modern Android application that follows the official architecture guidance from Google. It is a reactive, single-activity app that uses the following: + +- **UI:** Built entirely with Jetpack Compose, including Material 3 components and adaptive layouts for different screen sizes. +- **State Management:** Unidirectional Data Flow (UDF) is implemented using Kotlin Coroutines and `Flow`s. `ViewModel`s act as state holders, exposing UI state as streams of data. +- **Dependency Injection:** Hilt is used for dependency injection throughout the app, simplifying the management of dependencies and improving testability. +- **Navigation:** Navigation is handled by Jetpack Navigation 2 for Compose, allowing for a declarative and type-safe way to navigate between screens. +- **Data:** The data layer is implemented using the repository pattern. + - **Local Data:** Room and DataStore are used for local data persistence. + - **Remote Data:** Retrofit and OkHttp are used for fetching data from the network. +- **Background Processing:** WorkManager is used for deferrable background tasks. + +## Modules + +The main Android app lives in the `app/` folder. Feature modules live in `feature/` and core and shared modules in `core/`. + +## Commands to Build & Test + +The app and Android libraries have two product flavors: `demo` and `prod`, and two build types: `debug` and `release`. + +- Build: `./gradlew assemble{Variant}`. Typically `assembleDemoDebug`. +- Fix linting/formatting: `./gradlew --init-script gradle/init.gradle.kts spotlessApply` +- Run local tests: `./gradlew {variant}Test` +- Run single test: `./gradlew {variant}Test --tests "com.example.myapp.MyTestClass"` +- Run local screenshot tests: `./gradlew verifyRoborazziDemoDebug` + +### Instrumented tests + +- Gradle-managed devices to run on device tests: `./gradlew pixel6api31aospDebugAndroidTest`. Also `pixel4api30aospatdDebugAndroidTest` and `pixelcapi30aospatdDebugAndroidTest`. + +### Creating tests + +#### Instrumented tests + +- Tests for UI features should only use `ComposeTestRule` with a `ComponentActivity`. +- Bigger tests live in the `:app` module and they can start activities like `MainActivity`. + +#### Local tests + +- [kotlinx.coroutines](https://github.com/Kotlin/kotlinx.coroutines) for most assertions +- [cashapp/turbine](https://github.com/cashapp/turbine) for complex coroutine tests +- [google/truth](https://github.com/google/truth) for assertions + +## Continuous integration + +- The workflows are defined in `.github/workflows/*.yaml` and they contain various checks. +- Screenshot tests are generated by CI, so they shouldn't be checked into the repo from a workstation. + +## Version control and code location + +- The project uses git and is hosted in https://github.com/android/nowinandroid. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 60884a3b5..a706c78b0 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -22,7 +22,7 @@ plugins { alias(libs.plugins.nowinandroid.android.application.jacoco) alias(libs.plugins.nowinandroid.android.application.firebase) alias(libs.plugins.nowinandroid.hilt) - id("com.google.android.gms.oss-licenses-plugin") + alias(libs.plugins.google.osslicenses) alias(libs.plugins.baselineprofile) alias(libs.plugins.roborazzi) alias(libs.plugins.kotlin.serialization) diff --git a/build.gradle.kts b/build.gradle.kts index b7989bab4..425b2c640 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,28 +14,6 @@ * limitations under the License. */ -buildscript { - repositories { - google { - content { - includeGroupByRegex("com\\.android.*") - includeGroupByRegex("com\\.google.*") - includeGroupByRegex("androidx.*") - } - } - mavenCentral() - - // This is used only for internal Google builds. - maven { url = uri("../nowinandroid-prebuilts/m2repository") } - } - dependencies { - classpath(libs.google.oss.licenses.plugin) { - exclude(group = "com.google.protobuf") - } - } - -} - /* * By listing all the plugins used throughout all subprojects in the root project build script, it * ensures that the build script classpath remains the same for all projects. This avoids potential @@ -58,7 +36,7 @@ plugins { alias(libs.plugins.hilt) apply false alias(libs.plugins.ksp) apply false alias(libs.plugins.roborazzi) apply false - alias(libs.plugins.secrets) apply false + alias(libs.plugins.google.osslicenses) apply false alias(libs.plugins.room) apply false alias(libs.plugins.module.graph) apply true // Plugin applied to allow module graph generation } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e79c60cf5..15980c87f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -36,7 +36,7 @@ firebaseCrashlyticsPlugin = "3.0.6" firebasePerfPlugin = "2.0.1" gmsPlugin = "4.4.2" googleOss = "17.1.0" -googleOssPlugin = "0.10.7" +googleOssPlugin = "0.10.8" hilt = "2.56" hiltExt = "1.2.0" jacoco = "0.8.12" @@ -54,7 +54,6 @@ retrofit = "2.11.0" robolectric = "4.14.1" roborazzi = "1.39.0" room = "2.7.2" -secrets = "2.0.1" truth = "1.4.4" turbine = "1.2.0" @@ -116,7 +115,6 @@ firebase-cloud-messaging = { module = "com.google.firebase:firebase-messaging" } firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics" } firebase-performance = { module = "com.google.firebase:firebase-perf" } google-oss-licenses = { module = "com.google.android.gms:play-services-oss-licenses", version.ref = "googleOss" } -google-oss-licenses-plugin = { module = "com.google.android.gms:oss-licenses-plugin", version.ref = "googleOssPlugin" } hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" } hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", version.ref = "hilt" } hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" } @@ -176,10 +174,10 @@ kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } module-graph = { id = "com.jraska.module.graph.assertion", version.ref = "moduleGraph" } +google-osslicenses = { id = "com.google.android.gms.oss-licenses-plugin", version.ref = "googleOssPlugin" } protobuf = { id = "com.google.protobuf", version.ref = "protobufPlugin" } roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" } room = { id = "androidx.room", version.ref = "room" } -secrets = { id = "com.google.android.libraries.mapsplatform.secrets-gradle-plugin", version.ref = "secrets" } # Plugins defined by this project nowinandroid-android-application = { id = "nowinandroid.android.application" }