Merge remote-tracking branch 'origin/main' into migration-coil2-coil3

pull/1860/head
Simon Marquis 7 days ago
commit d4df5c8a55

@ -1,6 +1,7 @@
name: Build name: Build
on: on:
workflow_dispatch:
push: push:
branches: branches:
- main - main
@ -29,16 +30,19 @@ jobs:
- name: Copy CI gradle.properties - name: Copy CI gradle.properties
run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties
- name: Set up JDK 17 - name: Set up JDK 21
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
distribution: 'zulu' distribution: 'zulu'
java-version: 17 java-version: 21
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v4 uses: gradle/actions/setup-gradle@v4
with: with:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
build-scan-publish: true
build-scan-terms-of-use-url: "https://gradle.com/terms-of-service"
build-scan-terms-of-use-agree: "yes"
- name: Check build-logic - name: Check build-logic
run: ./gradlew :build-logic:convention:check run: ./gradlew :build-logic:convention:check
@ -139,11 +143,26 @@ jobs:
name: lint-reports name: lint-reports
path: '**/build/reports/lint-results-*.html' path: '**/build/reports/lint-results-*.html'
- name: Upload lint reports (SARIF) - name: Upload lint reports (SARIF) for app module
if: ${{ !cancelled() && hashFiles('**/*.sarif') != '' }} if: ${{ !cancelled() && hashFiles('app/**/*.sarif') != '' }}
uses: github/codeql-action/upload-sarif@v3 uses: github/codeql-action/upload-sarif@v3
with: with:
sarif_file: './' sarif_file: './app/'
category: app
- name: Upload lint reports (SARIF) for app-nia-catalog module
if: ${{ !cancelled() && hashFiles('app-nia-catalog/**/*.sarif') != '' }}
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: './app-nia-catalog/'
category: app-nia-catalog
- name: Upload lint reports (SARIF) for lint module
if: ${{ !cancelled() && hashFiles('lint/**/*.sarif') != '' }}
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: './lint/'
category: lint
- name: Check badging - name: Check badging
run: ./gradlew :app:checkProdReleaseBadging run: ./gradlew :app:checkProdReleaseBadging
@ -180,16 +199,19 @@ jobs:
- name: Copy CI gradle.properties - name: Copy CI gradle.properties
run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties
- name: Set up JDK 17 - name: Set up JDK 21
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
distribution: 'zulu' distribution: 'zulu'
java-version: 17 java-version: 21
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v4 uses: gradle/actions/setup-gradle@v4
with: with:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
build-scan-publish: true
build-scan-terms-of-use-url: "https://gradle.com/terms-of-service"
build-scan-terms-of-use-agree: "yes"
- name: Build projects and run instrumentation tests - name: Build projects and run instrumentation tests
uses: reactivecircus/android-emulator-runner@v2 uses: reactivecircus/android-emulator-runner@v2

@ -1,6 +1,7 @@
name: NightlyBaselineProfiles name: NightlyBaselineProfiles
on: on:
workflow_dispatch:
schedule: schedule:
- cron: '42 4 * * *' - cron: '42 4 * * *'
@ -39,6 +40,9 @@ jobs:
uses: gradle/actions/setup-gradle@v4 uses: gradle/actions/setup-gradle@v4
with: with:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
build-scan-publish: true
build-scan-terms-of-use-url: "https://gradle.com/terms-of-service"
build-scan-terms-of-use-agree: "yes"
- name: Setup Android SDK - name: Setup Android SDK
uses: android-actions/setup-android@v3 uses: android-actions/setup-android@v3

@ -1,6 +1,7 @@
name: GitHub Release with APKs name: GitHub Release with APKs
on: on:
workflow_dispatch:
push: push:
tags: tags:
- 'v*' - 'v*'
@ -36,6 +37,9 @@ jobs:
uses: gradle/actions/setup-gradle@v4 uses: gradle/actions/setup-gradle@v4
with: with:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
build-scan-publish: true
build-scan-terms-of-use-url: "https://gradle.com/terms-of-service"
build-scan-terms-of-use-agree: "yes"
- name: Setup Android SDK - name: Setup Android SDK
uses: android-actions/setup-android@v3 uses: android-actions/setup-android@v3

@ -0,0 +1 @@
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.

@ -0,0 +1 @@
* @dturner

@ -1,7 +1,7 @@
androidx.activity:activity-compose:1.9.3 androidx.activity:activity-compose:1.9.3
androidx.activity:activity-ktx:1.9.3 androidx.activity:activity-ktx:1.9.3
androidx.activity:activity:1.9.3 androidx.activity:activity:1.9.3
androidx.annotation:annotation-experimental:1.4.1 androidx.annotation:annotation-experimental:1.5.1
androidx.annotation:annotation-jvm:1.9.1 androidx.annotation:annotation-jvm:1.9.1
androidx.annotation:annotation:1.9.1 androidx.annotation:annotation:1.9.1
androidx.appcompat:appcompat-resources:1.7.0 androidx.appcompat:appcompat-resources:1.7.0
@ -9,53 +9,58 @@ androidx.arch.core:core-common:2.2.0
androidx.arch.core:core-runtime:2.2.0 androidx.arch.core:core-runtime:2.2.0
androidx.autofill:autofill:1.0.0 androidx.autofill:autofill:1.0.0
androidx.browser:browser:1.8.0 androidx.browser:browser:1.8.0
androidx.collection:collection-jvm:1.5.0-beta03 androidx.collection:collection-jvm:1.5.0
androidx.collection:collection-ktx:1.5.0-beta03 androidx.collection:collection-ktx:1.5.0
androidx.collection:collection:1.5.0-beta03 androidx.collection:collection:1.5.0
androidx.compose.animation:animation-android:1.8.0-beta02 androidx.compose.animation:animation-android:1.10.0-alpha02
androidx.compose.animation:animation-core-android:1.8.0-beta02 androidx.compose.animation:animation-core-android:1.10.0-alpha02
androidx.compose.animation:animation-core:1.8.0-beta02 androidx.compose.animation:animation-core:1.10.0-alpha02
androidx.compose.animation:animation:1.8.0-beta02 androidx.compose.animation:animation:1.10.0-alpha02
androidx.compose.foundation:foundation-android:1.8.0-beta02 androidx.compose.foundation:foundation-android:1.10.0-alpha02
androidx.compose.foundation:foundation-layout-android:1.8.0-beta02 androidx.compose.foundation:foundation-layout-android:1.10.0-alpha02
androidx.compose.foundation:foundation-layout:1.8.0-beta02 androidx.compose.foundation:foundation-layout:1.10.0-alpha02
androidx.compose.foundation:foundation:1.8.0-beta02 androidx.compose.foundation:foundation:1.10.0-alpha02
androidx.compose.material3.adaptive:adaptive-android:1.1.0-rc01 androidx.compose.material3.adaptive:adaptive-android:1.2.0-beta01
androidx.compose.material3.adaptive:adaptive:1.1.0-rc01 androidx.compose.material3.adaptive:adaptive:1.2.0-beta01
androidx.compose.material3:material3-adaptive-navigation-suite-android:1.4.0-alpha08 androidx.compose.material3:material3-adaptive-navigation-suite-android:1.5.0-alpha03
androidx.compose.material3:material3-adaptive-navigation-suite:1.4.0-alpha08 androidx.compose.material3:material3-adaptive-navigation-suite:1.5.0-alpha03
androidx.compose.material3:material3-android:1.4.0-alpha08 androidx.compose.material3:material3-android:1.5.0-alpha03
androidx.compose.material3:material3:1.4.0-alpha08 androidx.compose.material3:material3:1.5.0-alpha03
androidx.compose.material:material-icons-core-android:1.7.8 androidx.compose.material:material-icons-core-android:1.7.8
androidx.compose.material:material-icons-core:1.7.8 androidx.compose.material:material-icons-core:1.7.8
androidx.compose.material:material-icons-extended-android:1.7.8 androidx.compose.material:material-icons-extended-android:1.7.8
androidx.compose.material:material-icons-extended:1.7.8 androidx.compose.material:material-icons-extended:1.7.8
androidx.compose.material:material-ripple-android:1.8.0-beta02 androidx.compose.material:material-ripple-android:1.10.0-alpha02
androidx.compose.material:material-ripple:1.8.0-beta02 androidx.compose.material:material-ripple:1.10.0-alpha02
androidx.compose.runtime:runtime-android:1.8.0-beta02 androidx.compose.runtime:runtime-android:1.10.0-alpha02
androidx.compose.runtime:runtime-saveable-android:1.8.0-beta02 androidx.compose.runtime:runtime-annotation-android:1.10.0-alpha02
androidx.compose.runtime:runtime-saveable:1.8.0-beta02 androidx.compose.runtime:runtime-annotation:1.10.0-alpha02
androidx.compose.runtime:runtime:1.8.0-beta02 androidx.compose.runtime:runtime-saveable-android:1.10.0-alpha02
androidx.compose.ui:ui-android:1.8.0-beta02 androidx.compose.runtime:runtime-saveable:1.10.0-alpha02
androidx.compose.ui:ui-geometry-android:1.8.0-beta02 androidx.compose.runtime:runtime:1.10.0-alpha02
androidx.compose.ui:ui-geometry:1.8.0-beta02 androidx.compose.ui:ui-android:1.10.0-alpha02
androidx.compose.ui:ui-graphics-android:1.8.0-beta02 androidx.compose.ui:ui-geometry-android:1.10.0-alpha02
androidx.compose.ui:ui-graphics:1.8.0-beta02 androidx.compose.ui:ui-geometry:1.10.0-alpha02
androidx.compose.ui:ui-text-android:1.8.0-beta02 androidx.compose.ui:ui-graphics-android:1.10.0-alpha02
androidx.compose.ui:ui-text:1.8.0-beta02 androidx.compose.ui:ui-graphics:1.10.0-alpha02
androidx.compose.ui:ui-tooling-preview-android:1.8.0-beta02 androidx.compose.ui:ui-text-android:1.10.0-alpha02
androidx.compose.ui:ui-tooling-preview:1.8.0-beta02 androidx.compose.ui:ui-text:1.10.0-alpha02
androidx.compose.ui:ui-unit-android:1.8.0-beta02 androidx.compose.ui:ui-tooling-preview-android:1.10.0-alpha02
androidx.compose.ui:ui-unit:1.8.0-beta02 androidx.compose.ui:ui-tooling-preview:1.10.0-alpha02
androidx.compose.ui:ui-util-android:1.8.0-beta02 androidx.compose.ui:ui-unit-android:1.10.0-alpha02
androidx.compose.ui:ui-util:1.8.0-beta02 androidx.compose.ui:ui-unit:1.10.0-alpha02
androidx.compose.ui:ui:1.8.0-beta02 androidx.compose.ui:ui-util-android:1.10.0-alpha02
androidx.compose:compose-bom-alpha:2025.02.00 androidx.compose.ui:ui-util:1.10.0-alpha02
androidx.compose.ui:ui:1.10.0-alpha02
androidx.compose:compose-bom-alpha:2025.08.01
androidx.concurrent:concurrent-futures:1.1.0 androidx.concurrent:concurrent-futures:1.1.0
androidx.core:core-ktx:1.15.0 androidx.core:core-ktx:1.16.0
androidx.core:core:1.15.0 androidx.core:core-viewtree:1.0.0
androidx.core:core:1.16.0
androidx.customview:customview-poolingcontainer:1.0.0 androidx.customview:customview-poolingcontainer:1.0.0
androidx.customview:customview:1.0.0 androidx.customview:customview:1.0.0
androidx.documentfile:documentfile:1.0.0
androidx.dynamicanimation:dynamicanimation:1.0.0
androidx.emoji2:emoji2:1.4.0 androidx.emoji2:emoji2:1.4.0
androidx.exifinterface:exifinterface:1.3.7 androidx.exifinterface:exifinterface:1.3.7
androidx.fragment:fragment:1.5.1 androidx.fragment:fragment:1.5.1
@ -63,39 +68,46 @@ androidx.graphics:graphics-path:1.0.1
androidx.graphics:graphics-shapes-android:1.0.1 androidx.graphics:graphics-shapes-android:1.0.1
androidx.graphics:graphics-shapes:1.0.1 androidx.graphics:graphics-shapes:1.0.1
androidx.interpolator:interpolator:1.0.0 androidx.interpolator:interpolator:1.0.0
androidx.lifecycle:lifecycle-common-java8:2.8.7 androidx.legacy:legacy-support-core-utils:1.0.0
androidx.lifecycle:lifecycle-common-jvm:2.8.7 androidx.lifecycle:lifecycle-common-java8:2.10.0-alpha03
androidx.lifecycle:lifecycle-common:2.8.7 androidx.lifecycle:lifecycle-common-jvm:2.10.0-alpha03
androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.7 androidx.lifecycle:lifecycle-common:2.10.0-alpha03
androidx.lifecycle:lifecycle-livedata-core:2.8.7 androidx.lifecycle:lifecycle-livedata-core-ktx:2.10.0-alpha03
androidx.lifecycle:lifecycle-livedata:2.8.7 androidx.lifecycle:lifecycle-livedata-core:2.10.0-alpha03
androidx.lifecycle:lifecycle-process:2.8.7 androidx.lifecycle:lifecycle-livedata:2.10.0-alpha03
androidx.lifecycle:lifecycle-runtime-android:2.8.7 androidx.lifecycle:lifecycle-process:2.10.0-alpha03
androidx.lifecycle:lifecycle-runtime-compose-android:2.8.7 androidx.lifecycle:lifecycle-runtime-android:2.10.0-alpha03
androidx.lifecycle:lifecycle-runtime-compose:2.8.7 androidx.lifecycle:lifecycle-runtime-compose-android:2.10.0-alpha03
androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.7 androidx.lifecycle:lifecycle-runtime-compose:2.10.0-alpha03
androidx.lifecycle:lifecycle-runtime-ktx:2.8.7 androidx.lifecycle:lifecycle-runtime-ktx-android:2.10.0-alpha03
androidx.lifecycle:lifecycle-runtime:2.8.7 androidx.lifecycle:lifecycle-runtime-ktx:2.10.0-alpha03
androidx.lifecycle:lifecycle-viewmodel-android:2.8.7 androidx.lifecycle:lifecycle-runtime:2.10.0-alpha03
androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7 androidx.lifecycle:lifecycle-viewmodel-android:2.10.0-alpha03
androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.7 androidx.lifecycle:lifecycle-viewmodel-ktx:2.10.0-alpha03
androidx.lifecycle:lifecycle-viewmodel:2.8.7 androidx.lifecycle:lifecycle-viewmodel-savedstate-android:2.10.0-alpha03
androidx.lifecycle:lifecycle-viewmodel-savedstate:2.10.0-alpha03
androidx.lifecycle:lifecycle-viewmodel:2.10.0-alpha03
androidx.loader:loader:1.0.0 androidx.loader:loader:1.0.0
androidx.localbroadcastmanager:localbroadcastmanager:1.0.0
androidx.metrics:metrics-performance:1.0.0-beta01 androidx.metrics:metrics-performance:1.0.0-beta01
androidx.print:print:1.0.0
androidx.profileinstaller:profileinstaller:1.4.1 androidx.profileinstaller:profileinstaller:1.4.1
androidx.savedstate:savedstate-ktx:1.2.1 androidx.savedstate:savedstate-android:1.4.0-alpha03
androidx.savedstate:savedstate:1.2.1 androidx.savedstate:savedstate-compose-android:1.4.0-alpha03
androidx.savedstate:savedstate-compose:1.4.0-alpha03
androidx.savedstate:savedstate-ktx:1.4.0-alpha03
androidx.savedstate:savedstate:1.4.0-alpha03
androidx.startup:startup-runtime:1.1.1 androidx.startup:startup-runtime:1.1.1
androidx.tracing:tracing-ktx:1.3.0-alpha02 androidx.tracing:tracing-ktx:1.3.0-alpha02
androidx.tracing:tracing:1.3.0-alpha02 androidx.tracing:tracing:1.3.0-alpha02
androidx.transition:transition:1.6.0
androidx.vectordrawable:vectordrawable-animated:1.1.0 androidx.vectordrawable:vectordrawable-animated:1.1.0
androidx.vectordrawable:vectordrawable:1.1.0 androidx.vectordrawable:vectordrawable:1.1.0
androidx.versionedparcelable:versionedparcelable:1.1.1 androidx.versionedparcelable:versionedparcelable:1.1.1
androidx.viewpager:viewpager:1.0.0 androidx.viewpager:viewpager:1.0.0
androidx.window.extensions.core:core:1.0.0 androidx.window:window-core-android:1.4.0
androidx.window:window-core-android:1.3.0 androidx.window:window-core:1.4.0
androidx.window:window-core:1.3.0 androidx.window:window:1.4.0
androidx.window:window:1.3.0
com.google.accompanist:accompanist-drawablepainter:0.36.0 com.google.accompanist:accompanist-drawablepainter:0.36.0
com.google.code.findbugs:jsr305:3.0.2 com.google.code.findbugs:jsr305:3.0.2
com.google.dagger:dagger-lint-aar:2.56 com.google.dagger:dagger-lint-aar:2.56
@ -144,5 +156,8 @@ org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.10.1
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1
org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.6.1 org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.6.1
org.jetbrains.kotlinx:kotlinx-datetime:0.6.1 org.jetbrains.kotlinx:kotlinx-datetime:0.6.1
org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3
org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3
org.jetbrains:annotations:23.0.0 org.jetbrains:annotations:23.0.0
org.jspecify:jspecify:1.0.0 org.jspecify:jspecify:1.0.0

@ -22,7 +22,7 @@ plugins {
alias(libs.plugins.nowinandroid.android.application.jacoco) alias(libs.plugins.nowinandroid.android.application.jacoco)
alias(libs.plugins.nowinandroid.android.application.firebase) alias(libs.plugins.nowinandroid.android.application.firebase)
alias(libs.plugins.nowinandroid.hilt) 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.baselineprofile)
alias(libs.plugins.roborazzi) alias(libs.plugins.roborazzi)
alias(libs.plugins.kotlin.serialization) alias(libs.plugins.kotlin.serialization)
@ -45,7 +45,8 @@ android {
release { release {
isMinifyEnabled = true isMinifyEnabled = true
applicationIdSuffix = NiaBuildType.RELEASE.applicationIdSuffix applicationIdSuffix = NiaBuildType.RELEASE.applicationIdSuffix
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro")
// To publish on the Play store a private signing key is required, but to allow anyone // To publish on the Play store a private signing key is required, but to allow anyone
// who clones the code to sign and run the release variant, use the debug signing key. // who clones the code to sign and run the release variant, use the debug signing key.
@ -61,11 +62,7 @@ android {
excludes.add("/META-INF/{AL2.0,LGPL2.1}") excludes.add("/META-INF/{AL2.0,LGPL2.1}")
} }
} }
testOptions { testOptions.unitTests.isIncludeAndroidResources = true
unitTests {
isIncludeAndroidResources = true
}
}
namespace = "com.google.samples.apps.nowinandroid" namespace = "com.google.samples.apps.nowinandroid"
} }

@ -1,7 +1,7 @@
androidx.activity:activity-compose:1.9.3 androidx.activity:activity-compose:1.10.1
androidx.activity:activity-ktx:1.9.3 androidx.activity:activity-ktx:1.10.1
androidx.activity:activity:1.9.3 androidx.activity:activity:1.10.1
androidx.annotation:annotation-experimental:1.4.1 androidx.annotation:annotation-experimental:1.5.1
androidx.annotation:annotation-jvm:1.9.1 androidx.annotation:annotation-jvm:1.9.1
androidx.annotation:annotation:1.9.1 androidx.annotation:annotation:1.9.1
androidx.appcompat:appcompat-resources:1.7.0 androidx.appcompat:appcompat-resources:1.7.0
@ -10,60 +10,63 @@ androidx.arch.core:core-common:2.2.0
androidx.arch.core:core-runtime:2.2.0 androidx.arch.core:core-runtime:2.2.0
androidx.autofill:autofill:1.0.0 androidx.autofill:autofill:1.0.0
androidx.browser:browser:1.8.0 androidx.browser:browser:1.8.0
androidx.collection:collection-jvm:1.5.0-beta03 androidx.collection:collection-jvm:1.5.0
androidx.collection:collection-ktx:1.5.0-beta03 androidx.collection:collection-ktx:1.5.0
androidx.collection:collection:1.5.0-beta03 androidx.collection:collection:1.5.0
androidx.compose.animation:animation-android:1.8.0-beta02 androidx.compose.animation:animation-android:1.10.0-alpha02
androidx.compose.animation:animation-core-android:1.8.0-beta02 androidx.compose.animation:animation-core-android:1.10.0-alpha02
androidx.compose.animation:animation-core:1.8.0-beta02 androidx.compose.animation:animation-core:1.10.0-alpha02
androidx.compose.animation:animation:1.8.0-beta02 androidx.compose.animation:animation:1.10.0-alpha02
androidx.compose.foundation:foundation-android:1.8.0-beta02 androidx.compose.foundation:foundation-android:1.10.0-alpha02
androidx.compose.foundation:foundation-layout-android:1.8.0-beta02 androidx.compose.foundation:foundation-layout-android:1.10.0-alpha02
androidx.compose.foundation:foundation-layout:1.8.0-beta02 androidx.compose.foundation:foundation-layout:1.10.0-alpha02
androidx.compose.foundation:foundation:1.8.0-beta02 androidx.compose.foundation:foundation:1.10.0-alpha02
androidx.compose.material3.adaptive:adaptive-android:1.1.0-rc01 androidx.compose.material3.adaptive:adaptive-android:1.2.0-beta01
androidx.compose.material3.adaptive:adaptive-layout-android:1.1.0-rc01 androidx.compose.material3.adaptive:adaptive-layout-android:1.2.0-beta01
androidx.compose.material3.adaptive:adaptive-layout:1.1.0-rc01 androidx.compose.material3.adaptive:adaptive-layout:1.2.0-beta01
androidx.compose.material3.adaptive:adaptive-navigation-android:1.1.0-rc01 androidx.compose.material3.adaptive:adaptive-navigation-android:1.2.0-beta01
androidx.compose.material3.adaptive:adaptive-navigation:1.1.0-rc01 androidx.compose.material3.adaptive:adaptive-navigation:1.2.0-beta01
androidx.compose.material3.adaptive:adaptive:1.1.0-rc01 androidx.compose.material3.adaptive:adaptive:1.2.0-beta01
androidx.compose.material3:material3-adaptive-navigation-suite-android:1.4.0-alpha08 androidx.compose.material3:material3-adaptive-navigation-suite-android:1.5.0-alpha03
androidx.compose.material3:material3-adaptive-navigation-suite:1.4.0-alpha08 androidx.compose.material3:material3-adaptive-navigation-suite:1.5.0-alpha03
androidx.compose.material3:material3-android:1.4.0-alpha08 androidx.compose.material3:material3-android:1.5.0-alpha03
androidx.compose.material3:material3-window-size-class-android:1.4.0-alpha08 androidx.compose.material3:material3-window-size-class-android:1.5.0-alpha03
androidx.compose.material3:material3-window-size-class:1.4.0-alpha08 androidx.compose.material3:material3-window-size-class:1.5.0-alpha03
androidx.compose.material3:material3:1.4.0-alpha08 androidx.compose.material3:material3:1.5.0-alpha03
androidx.compose.material:material-icons-core-android:1.7.8 androidx.compose.material:material-icons-core-android:1.7.8
androidx.compose.material:material-icons-core:1.7.8 androidx.compose.material:material-icons-core:1.7.8
androidx.compose.material:material-icons-extended-android:1.7.8 androidx.compose.material:material-icons-extended-android:1.7.8
androidx.compose.material:material-icons-extended:1.7.8 androidx.compose.material:material-icons-extended:1.7.8
androidx.compose.material:material-ripple-android:1.8.0-beta02 androidx.compose.material:material-ripple-android:1.10.0-alpha02
androidx.compose.material:material-ripple:1.8.0-beta02 androidx.compose.material:material-ripple:1.10.0-alpha02
androidx.compose.runtime:runtime-android:1.8.0-beta02 androidx.compose.runtime:runtime-android:1.10.0-alpha02
androidx.compose.runtime:runtime-saveable-android:1.8.0-beta02 androidx.compose.runtime:runtime-annotation-android:1.10.0-alpha02
androidx.compose.runtime:runtime-saveable:1.8.0-beta02 androidx.compose.runtime:runtime-annotation:1.10.0-alpha02
androidx.compose.runtime:runtime-tracing:1.8.0-beta02 androidx.compose.runtime:runtime-saveable-android:1.10.0-alpha02
androidx.compose.runtime:runtime:1.8.0-beta02 androidx.compose.runtime:runtime-saveable:1.10.0-alpha02
androidx.compose.ui:ui-android:1.8.0-beta02 androidx.compose.runtime:runtime-tracing:1.10.0-alpha02
androidx.compose.ui:ui-geometry-android:1.8.0-beta02 androidx.compose.runtime:runtime:1.10.0-alpha02
androidx.compose.ui:ui-geometry:1.8.0-beta02 androidx.compose.ui:ui-android:1.10.0-alpha02
androidx.compose.ui:ui-graphics-android:1.8.0-beta02 androidx.compose.ui:ui-geometry-android:1.10.0-alpha02
androidx.compose.ui:ui-graphics:1.8.0-beta02 androidx.compose.ui:ui-geometry:1.10.0-alpha02
androidx.compose.ui:ui-text-android:1.8.0-beta02 androidx.compose.ui:ui-graphics-android:1.10.0-alpha02
androidx.compose.ui:ui-text:1.8.0-beta02 androidx.compose.ui:ui-graphics:1.10.0-alpha02
androidx.compose.ui:ui-tooling-preview-android:1.8.0-beta02 androidx.compose.ui:ui-text-android:1.10.0-alpha02
androidx.compose.ui:ui-tooling-preview:1.8.0-beta02 androidx.compose.ui:ui-text:1.10.0-alpha02
androidx.compose.ui:ui-unit-android:1.8.0-beta02 androidx.compose.ui:ui-tooling-preview-android:1.10.0-alpha02
androidx.compose.ui:ui-unit:1.8.0-beta02 androidx.compose.ui:ui-tooling-preview:1.10.0-alpha02
androidx.compose.ui:ui-util-android:1.8.0-beta02 androidx.compose.ui:ui-unit-android:1.10.0-alpha02
androidx.compose.ui:ui-util:1.8.0-beta02 androidx.compose.ui:ui-unit:1.10.0-alpha02
androidx.compose.ui:ui:1.8.0-beta02 androidx.compose.ui:ui-util-android:1.10.0-alpha02
androidx.compose:compose-bom-alpha:2025.02.00 androidx.compose.ui:ui-util:1.10.0-alpha02
androidx.compose.ui:ui:1.10.0-alpha02
androidx.compose:compose-bom-alpha:2025.08.01
androidx.concurrent:concurrent-futures-ktx:1.1.0 androidx.concurrent:concurrent-futures-ktx:1.1.0
androidx.concurrent:concurrent-futures:1.1.0 androidx.concurrent:concurrent-futures:1.1.0
androidx.core:core-ktx:1.15.0 androidx.core:core-ktx:1.16.0
androidx.core:core-splashscreen:1.0.1 androidx.core:core-splashscreen:1.0.1
androidx.core:core:1.15.0 androidx.core:core-viewtree:1.0.0
androidx.core:core:1.16.0
androidx.cursoradapter:cursoradapter:1.0.0 androidx.cursoradapter:cursoradapter:1.0.0
androidx.customview:customview-poolingcontainer:1.0.0 androidx.customview:customview-poolingcontainer:1.0.0
androidx.customview:customview:1.0.0 androidx.customview:customview:1.0.0
@ -79,6 +82,7 @@ androidx.datastore:datastore-preferences:1.1.1
androidx.datastore:datastore:1.1.1 androidx.datastore:datastore:1.1.1
androidx.documentfile:documentfile:1.0.0 androidx.documentfile:documentfile:1.0.0
androidx.drawerlayout:drawerlayout:1.0.0 androidx.drawerlayout:drawerlayout:1.0.0
androidx.dynamicanimation:dynamicanimation:1.0.0
androidx.emoji2:emoji2-views-helper:1.4.0 androidx.emoji2:emoji2-views-helper:1.4.0
androidx.emoji2:emoji2:1.4.0 androidx.emoji2:emoji2:1.4.0
androidx.exifinterface:exifinterface:1.3.7 androidx.exifinterface:exifinterface:1.3.7
@ -92,26 +96,27 @@ androidx.hilt:hilt-navigation:1.2.0
androidx.hilt:hilt-work:1.2.0 androidx.hilt:hilt-work:1.2.0
androidx.interpolator:interpolator:1.0.0 androidx.interpolator:interpolator:1.0.0
androidx.legacy:legacy-support-core-utils:1.0.0 androidx.legacy:legacy-support-core-utils:1.0.0
androidx.lifecycle:lifecycle-common-java8:2.8.7 androidx.lifecycle:lifecycle-common-java8:2.10.0-alpha03
androidx.lifecycle:lifecycle-common-jvm:2.8.7 androidx.lifecycle:lifecycle-common-jvm:2.10.0-alpha03
androidx.lifecycle:lifecycle-common:2.8.7 androidx.lifecycle:lifecycle-common:2.10.0-alpha03
androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.7 androidx.lifecycle:lifecycle-livedata-core-ktx:2.10.0-alpha03
androidx.lifecycle:lifecycle-livedata-core:2.8.7 androidx.lifecycle:lifecycle-livedata-core:2.10.0-alpha03
androidx.lifecycle:lifecycle-livedata:2.8.7 androidx.lifecycle:lifecycle-livedata:2.10.0-alpha03
androidx.lifecycle:lifecycle-process:2.8.7 androidx.lifecycle:lifecycle-process:2.10.0-alpha03
androidx.lifecycle:lifecycle-runtime-android:2.8.7 androidx.lifecycle:lifecycle-runtime-android:2.10.0-alpha03
androidx.lifecycle:lifecycle-runtime-compose-android:2.8.7 androidx.lifecycle:lifecycle-runtime-compose-android:2.10.0-alpha03
androidx.lifecycle:lifecycle-runtime-compose:2.8.7 androidx.lifecycle:lifecycle-runtime-compose:2.10.0-alpha03
androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.7 androidx.lifecycle:lifecycle-runtime-ktx-android:2.10.0-alpha03
androidx.lifecycle:lifecycle-runtime-ktx:2.8.7 androidx.lifecycle:lifecycle-runtime-ktx:2.10.0-alpha03
androidx.lifecycle:lifecycle-runtime:2.8.7 androidx.lifecycle:lifecycle-runtime:2.10.0-alpha03
androidx.lifecycle:lifecycle-service:2.8.7 androidx.lifecycle:lifecycle-service:2.10.0-alpha03
androidx.lifecycle:lifecycle-viewmodel-android:2.8.7 androidx.lifecycle:lifecycle-viewmodel-android:2.10.0-alpha03
androidx.lifecycle:lifecycle-viewmodel-compose-android:2.8.7 androidx.lifecycle:lifecycle-viewmodel-compose-android:2.10.0-alpha03
androidx.lifecycle:lifecycle-viewmodel-compose:2.8.7 androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0-alpha03
androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7 androidx.lifecycle:lifecycle-viewmodel-ktx:2.10.0-alpha03
androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.7 androidx.lifecycle:lifecycle-viewmodel-savedstate-android:2.10.0-alpha03
androidx.lifecycle:lifecycle-viewmodel:2.8.7 androidx.lifecycle:lifecycle-viewmodel-savedstate:2.10.0-alpha03
androidx.lifecycle:lifecycle-viewmodel:2.10.0-alpha03
androidx.loader:loader:1.0.0 androidx.loader:loader:1.0.0
androidx.localbroadcastmanager:localbroadcastmanager:1.0.0 androidx.localbroadcastmanager:localbroadcastmanager:1.0.0
androidx.metrics:metrics-performance:1.0.0-beta01 androidx.metrics:metrics-performance:1.0.0-beta01
@ -125,25 +130,32 @@ androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05
androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05 androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05
androidx.profileinstaller:profileinstaller:1.4.1 androidx.profileinstaller:profileinstaller:1.4.1
androidx.resourceinspection:resourceinspection-annotation:1.0.1 androidx.resourceinspection:resourceinspection-annotation:1.0.1
androidx.room:room-common:2.6.1 androidx.room:room-common-jvm:2.7.2
androidx.room:room-ktx:2.6.1 androidx.room:room-common:2.7.2
androidx.room:room-runtime:2.6.1 androidx.room:room-ktx:2.7.2
androidx.savedstate:savedstate-ktx:1.2.1 androidx.room:room-runtime-android:2.7.2
androidx.savedstate:savedstate:1.2.1 androidx.room:room-runtime:2.7.2
androidx.sqlite:sqlite-framework:2.4.0 androidx.savedstate:savedstate-android:1.4.0-alpha03
androidx.sqlite:sqlite:2.4.0 androidx.savedstate:savedstate-compose-android:1.4.0-alpha03
androidx.savedstate:savedstate-compose:1.4.0-alpha03
androidx.savedstate:savedstate-ktx:1.4.0-alpha03
androidx.savedstate:savedstate:1.4.0-alpha03
androidx.sqlite:sqlite-android:2.5.1
androidx.sqlite:sqlite-framework-android:2.5.1
androidx.sqlite:sqlite-framework:2.5.1
androidx.sqlite:sqlite:2.5.1
androidx.startup:startup-runtime:1.1.1 androidx.startup:startup-runtime:1.1.1
androidx.tracing:tracing-ktx:1.3.0-alpha02 androidx.tracing:tracing-ktx:1.3.0-alpha02
androidx.tracing:tracing-perfetto:1.0.0 androidx.tracing:tracing-perfetto:1.0.0
androidx.tracing:tracing:1.3.0-alpha02 androidx.tracing:tracing:1.3.0-alpha02
androidx.transition:transition:1.6.0
androidx.vectordrawable:vectordrawable-animated:1.1.0 androidx.vectordrawable:vectordrawable-animated:1.1.0
androidx.vectordrawable:vectordrawable:1.1.0 androidx.vectordrawable:vectordrawable:1.1.0
androidx.versionedparcelable:versionedparcelable:1.1.1 androidx.versionedparcelable:versionedparcelable:1.1.1
androidx.viewpager:viewpager:1.0.0 androidx.viewpager:viewpager:1.0.0
androidx.window.extensions.core:core:1.0.0 androidx.window:window-core-android:1.4.0
androidx.window:window-core-android:1.3.0 androidx.window:window-core:1.4.0
androidx.window:window-core:1.3.0 androidx.window:window:1.4.0
androidx.window:window:1.3.0
androidx.work:work-runtime-ktx:2.10.0 androidx.work:work-runtime-ktx:2.10.0
androidx.work:work-runtime:2.10.0 androidx.work:work-runtime:2.10.0
com.caverock:androidsvg-aar:1.4 com.caverock:androidsvg-aar:1.4

@ -1,5 +1,5 @@
package: name='com.google.samples.apps.nowinandroid' versionCode='8' versionName='0.1.2' platformBuildVersionName='15' platformBuildVersionCode='35' compileSdkVersion='35' compileSdkVersionCodename='15' package: name='com.google.samples.apps.nowinandroid' versionCode='8' versionName='0.1.2' platformBuildVersionName='15' platformBuildVersionCode='35' compileSdkVersion='35' compileSdkVersionCodename='15'
minSdkVersion:'21' minSdkVersion:'23'
targetSdkVersion:'35' targetSdkVersion:'35'
uses-permission: name='android.permission.INTERNET' uses-permission: name='android.permission.INTERNET'
uses-permission: name='android.permission.ACCESS_NETWORK_STATE' uses-permission: name='android.permission.ACCESS_NETWORK_STATE'
@ -105,9 +105,9 @@ application-icon-640:'res/mipmap-anydpi-v26/ic_launcher.xml'
application-icon-65534:'res/mipmap-anydpi-v26/ic_launcher.xml' application-icon-65534:'res/mipmap-anydpi-v26/ic_launcher.xml'
application: label='Now in Android' icon='res/mipmap-anydpi-v26/ic_launcher.xml' application: label='Now in Android' icon='res/mipmap-anydpi-v26/ic_launcher.xml'
launchable-activity: name='com.google.samples.apps.nowinandroid.MainActivity' label='' icon='' launchable-activity: name='com.google.samples.apps.nowinandroid.MainActivity' label='' icon=''
uses-library-not-required:'android.ext.adservices'
uses-library-not-required:'androidx.window.extensions' uses-library-not-required:'androidx.window.extensions'
uses-library-not-required:'androidx.window.sidecar' uses-library-not-required:'androidx.window.sidecar'
uses-library-not-required:'android.ext.adservices'
feature-group: label='' feature-group: label=''
uses-feature: name='android.hardware.faketouch' uses-feature: name='android.hardware.faketouch'
uses-implied-feature: name='android.hardware.faketouch' reason='default feature for all apps' uses-implied-feature: name='android.hardware.faketouch' reason='default feature for all apps'

@ -0,0 +1,2 @@
# Repackage classes into the default package to reduce the size of descriptors.
-repackageclasses

@ -21,7 +21,9 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.exclude
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.safeDrawing
@ -166,8 +168,7 @@ internal fun NiaApp(
) )
}, },
label = { Text(stringResource(destination.iconTextId)) }, label = { Text(stringResource(destination.iconTextId)) },
modifier = modifier = Modifier
Modifier
.testTag("NiaNavItem") .testTag("NiaNavItem")
.then(if (hasUnread) Modifier.notificationDot() else Modifier), .then(if (hasUnread) Modifier.notificationDot() else Modifier),
) )
@ -185,7 +186,11 @@ internal fun NiaApp(
snackbarHost = { snackbarHost = {
SnackbarHost( SnackbarHost(
snackbarHostState, snackbarHostState,
modifier = Modifier.windowInsetsPadding(WindowInsets.safeDrawing), modifier = Modifier.windowInsetsPadding(
WindowInsets.safeDrawing.exclude(
WindowInsets.ime,
),
),
) )
}, },
) { padding -> ) { padding ->

@ -45,8 +45,8 @@ android {
) )
} }
testOptions.managedDevices.devices { testOptions.managedDevices.localDevices {
create<com.android.build.api.dsl.ManagedVirtualDevice>("pixel6Api33") { create("pixel6Api33") {
device = "Pixel 6" device = "Pixel 6"
apiLevel = 33 apiLevel = 33
systemImageSource = "aosp" systemImageSource = "aosp"

@ -37,7 +37,7 @@ kotlin {
} }
dependencies { dependencies {
compileOnly(libs.android.gradlePlugin) compileOnly(libs.android.gradleApiPlugin)
compileOnly(libs.android.tools.common) compileOnly(libs.android.tools.common)
compileOnly(libs.compose.gradlePlugin) compileOnly(libs.compose.gradlePlugin)
compileOnly(libs.firebase.crashlytics.gradlePlugin) compileOnly(libs.firebase.crashlytics.gradlePlugin)

@ -16,7 +16,6 @@
import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.variant.ApplicationAndroidComponentsExtension import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.android.build.gradle.BaseExtension
import com.google.samples.apps.nowinandroid.configureBadgingTasks import com.google.samples.apps.nowinandroid.configureBadgingTasks
import com.google.samples.apps.nowinandroid.configureGradleManagedDevices import com.google.samples.apps.nowinandroid.configureGradleManagedDevices
import com.google.samples.apps.nowinandroid.configureKotlinAndroid import com.google.samples.apps.nowinandroid.configureKotlinAndroid
@ -44,7 +43,7 @@ class AndroidApplicationConventionPlugin : Plugin<Project> {
} }
extensions.configure<ApplicationAndroidComponentsExtension> { extensions.configure<ApplicationAndroidComponentsExtension> {
configurePrintApksTask(this) configurePrintApksTask(this)
configureBadgingTasks(extensions.getByType<BaseExtension>(), this) configureBadgingTasks(extensions.getByType<ApplicationExtension>(), this)
} }
} }
} }

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.gradle.LibraryExtension import com.android.build.api.dsl.LibraryExtension
import com.google.samples.apps.nowinandroid.configureGradleManagedDevices import com.google.samples.apps.nowinandroid.configureGradleManagedDevices
import com.google.samples.apps.nowinandroid.libs import com.google.samples.apps.nowinandroid.libs
import org.gradle.api.Plugin import org.gradle.api.Plugin

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.gradle.LibraryExtension import com.android.build.api.dsl.LibraryExtension
import com.google.samples.apps.nowinandroid.configureAndroidCompose import com.google.samples.apps.nowinandroid.configureAndroidCompose
import org.gradle.api.Plugin import org.gradle.api.Plugin
import org.gradle.api.Project import org.gradle.api.Project

@ -14,8 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.dsl.LibraryExtension
import com.android.build.api.variant.LibraryAndroidComponentsExtension import com.android.build.api.variant.LibraryAndroidComponentsExtension
import com.android.build.gradle.LibraryExtension
import com.google.samples.apps.nowinandroid.configureFlavors import com.google.samples.apps.nowinandroid.configureFlavors
import com.google.samples.apps.nowinandroid.configureGradleManagedDevices import com.google.samples.apps.nowinandroid.configureGradleManagedDevices
import com.google.samples.apps.nowinandroid.configureKotlinAndroid import com.google.samples.apps.nowinandroid.configureKotlinAndroid
@ -37,7 +37,8 @@ class AndroidLibraryConventionPlugin : Plugin<Project> {
extensions.configure<LibraryExtension> { extensions.configure<LibraryExtension> {
configureKotlinAndroid(this) configureKotlinAndroid(this)
defaultConfig.targetSdk = 35 testOptions.targetSdk = 35
lint.targetSdk = 35
defaultConfig.testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" defaultConfig.testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testOptions.animationsDisabled = true testOptions.animationsDisabled = true
configureFlavors(this) configureFlavors(this)

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.gradle.TestExtension import com.android.build.api.dsl.TestExtension
import com.google.samples.apps.nowinandroid.configureGradleManagedDevices import com.google.samples.apps.nowinandroid.configureGradleManagedDevices
import com.google.samples.apps.nowinandroid.configureKotlinAndroid import com.google.samples.apps.nowinandroid.configureKotlinAndroid
import org.gradle.api.Plugin import org.gradle.api.Plugin

@ -42,13 +42,6 @@ internal fun Project.configureAndroidCompose(
"implementation"(libs.findLibrary("androidx-compose-ui-tooling-preview").get()) "implementation"(libs.findLibrary("androidx-compose-ui-tooling-preview").get())
"debugImplementation"(libs.findLibrary("androidx-compose-ui-tooling").get()) "debugImplementation"(libs.findLibrary("androidx-compose-ui-tooling").get())
} }
testOptions {
unitTests {
// For Robolectric
isIncludeAndroidResources = true
}
}
} }
extensions.configure<ComposeCompilerGradlePluginExtension> { extensions.configure<ComposeCompilerGradlePluginExtension> {

@ -18,8 +18,8 @@ package com.google.samples.apps.nowinandroid
import com.android.SdkConstants import com.android.SdkConstants
import com.android.build.api.artifact.SingleArtifact import com.android.build.api.artifact.SingleArtifact
import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.variant.ApplicationAndroidComponentsExtension import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.android.build.gradle.BaseExtension
import com.google.common.truth.Truth.assertWithMessage import com.google.common.truth.Truth.assertWithMessage
import org.gradle.api.DefaultTask import org.gradle.api.DefaultTask
import org.gradle.api.Project import org.gradle.api.Project
@ -110,7 +110,7 @@ private fun String.capitalized() = replaceFirstChar {
} }
fun Project.configureBadgingTasks( fun Project.configureBadgingTasks(
baseExtension: BaseExtension, baseExtension: ApplicationExtension,
componentsExtension: ApplicationAndroidComponentsExtension, componentsExtension: ApplicationAndroidComponentsExtension,
) { ) {
// Registers a callback to be called, when a new variant is configured // Registers a callback to be called, when a new variant is configured

@ -38,7 +38,7 @@ internal fun Project.configureKotlinAndroid(
compileSdk = 35 compileSdk = 35
defaultConfig { defaultConfig {
minSdk = 21 minSdk = 23
} }
compileOptions { compileOptions {

@ -14,28 +14,6 @@
* limitations under the License. * 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 * 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 * 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.hilt) apply false
alias(libs.plugins.ksp) apply false alias(libs.plugins.ksp) apply false
alias(libs.plugins.roborazzi) 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.room) apply false
alias(libs.plugins.module.graph) apply true // Plugin applied to allow module graph generation alias(libs.plugins.module.graph) apply true // Plugin applied to allow module graph generation
} }

@ -22,11 +22,7 @@ plugins {
android { android {
namespace = "com.google.samples.apps.nowinandroid.core.data" namespace = "com.google.samples.apps.nowinandroid.core.data"
testOptions { testOptions.unitTests.isIncludeAndroidResources = true
unitTests {
isIncludeAndroidResources = true
}
}
} }
dependencies { dependencies {

@ -36,7 +36,7 @@ class TestNewsResourceDao : NewsResourceDao {
private val entitiesStateFlow = MutableStateFlow(emptyList<NewsResourceEntity>()) private val entitiesStateFlow = MutableStateFlow(emptyList<NewsResourceEntity>())
internal var topicCrossReferences: List<NewsResourceTopicCrossRef> = listOf() internal var topicCrossReferences: List<NewsResourceTopicCrossRef> = emptyList()
override fun getNewsResources( override fun getNewsResources(
useFilterTopicIds: Boolean, useFilterTopicIds: Boolean,

@ -49,5 +49,5 @@ fun NewsResourceEntity.asExternalModel() = NewsResource(
headerImageUrl = headerImageUrl, headerImageUrl = headerImageUrl,
publishDate = publishDate, publishDate = publishDate,
type = type, type = type,
topics = listOf(), topics = emptyList(),
) )

@ -22,6 +22,7 @@ plugins {
android { android {
namespace = "com.google.samples.apps.nowinandroid.core.designsystem" namespace = "com.google.samples.apps.nowinandroid.core.designsystem"
testOptions.unitTests.isIncludeAndroidResources = true
} }
dependencies { dependencies {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

@ -14,12 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.variant.BuildConfigField
import java.io.StringReader
import java.util.Properties
plugins { plugins {
alias(libs.plugins.nowinandroid.android.library) alias(libs.plugins.nowinandroid.android.library)
alias(libs.plugins.nowinandroid.android.library.jacoco) alias(libs.plugins.nowinandroid.android.library.jacoco)
alias(libs.plugins.nowinandroid.hilt) alias(libs.plugins.nowinandroid.hilt)
id("kotlinx-serialization") id("kotlinx-serialization")
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
} }
android { android {
@ -27,15 +30,7 @@ android {
buildConfig = true buildConfig = true
} }
namespace = "com.google.samples.apps.nowinandroid.core.network" namespace = "com.google.samples.apps.nowinandroid.core.network"
testOptions { testOptions.unitTests.isIncludeAndroidResources = true
unitTests {
isIncludeAndroidResources = true
}
}
}
secrets {
defaultPropertiesFileName = "secrets.defaults.properties"
} }
dependencies { dependencies {
@ -53,3 +48,19 @@ dependencies {
testImplementation(libs.kotlinx.coroutines.test) testImplementation(libs.kotlinx.coroutines.test)
} }
val backendUrl = providers.fileContents(
isolated.rootProject.projectDirectory.file("local.properties")
).asText.map { text ->
val properties = Properties()
properties.load(StringReader(text))
properties["BACKEND_URL"]
}.orElse("http://example.com")
androidComponents {
onVariants {
it.buildConfigFields!!.put("BACKEND_URL", backendUrl.map { value ->
BuildConfigField(type = "String", value = """"$value"""", comment = null)
})
}
}

@ -16,6 +16,7 @@
package com.google.samples.apps.nowinandroid.core.network.model package com.google.samples.apps.nowinandroid.core.network.model
import android.annotation.SuppressLint
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
import kotlinx.datetime.Instant import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -23,6 +24,7 @@ import kotlinx.serialization.Serializable
/** /**
* Network representation of [NewsResource] when fetched from /newsresources * Network representation of [NewsResource] when fetched from /newsresources
*/ */
@SuppressLint("UnsafeOptInUsageError")
@Serializable @Serializable
data class NetworkNewsResource( data class NetworkNewsResource(
val id: String, val id: String,
@ -32,5 +34,5 @@ data class NetworkNewsResource(
val headerImageUrl: String, val headerImageUrl: String,
val publishDate: Instant, val publishDate: Instant,
val type: String, val type: String,
val topics: List<String> = listOf(), val topics: List<String> = emptyList(),
) )

@ -23,6 +23,7 @@ plugins {
android { android {
namespace = "com.google.samples.apps.nowinandroid.feature.foryou" namespace = "com.google.samples.apps.nowinandroid.feature.foryou"
testOptions.unitTests.isIncludeAndroidResources = true
} }
dependencies { dependencies {

@ -2,12 +2,12 @@
accompanist = "0.37.0" accompanist = "0.37.0"
androidDesugarJdkLibs = "2.1.4" androidDesugarJdkLibs = "2.1.4"
# AGP and tools should be updated together # AGP and tools should be updated together
androidGradlePlugin = "8.9.0" androidGradlePlugin = "8.12.2"
androidTools = "31.9.0" androidTools = "31.12.2"
androidxActivity = "1.9.3" androidxActivity = "1.9.3"
androidxAppCompat = "1.7.0" androidxAppCompat = "1.7.0"
androidxBrowser = "1.8.0" androidxBrowser = "1.8.0"
androidxComposeBom = "2025.02.00" androidxComposeBom = "2025.08.01"
androidxComposeFoundation = "1.8.0-alpha07" androidxComposeFoundation = "1.8.0-alpha07"
androidxComposeMaterial3Adaptive = "1.1.0-rc01" androidxComposeMaterial3Adaptive = "1.1.0-rc01"
androidxComposeRuntimeTracing = "1.7.6" androidxComposeRuntimeTracing = "1.7.6"
@ -22,21 +22,21 @@ androidxMacroBenchmark = "1.3.4"
androidxMetrics = "1.0.0-beta01" androidxMetrics = "1.0.0-beta01"
androidxNavigation = "2.8.5" androidxNavigation = "2.8.5"
androidxProfileinstaller = "1.4.1" androidxProfileinstaller = "1.4.1"
androidxTestCore = "1.6.1" androidxTestCore = "1.7.0-rc01"
androidxTestExt = "1.2.1" androidxTestExt = "1.3.0-rc01"
androidxTestRules = "1.6.1" androidxTestRules = "1.7.0-rc01"
androidxTestRunner = "1.6.2" androidxTestRunner = "1.7.0-rc01"
androidxTracing = "1.3.0-alpha02" androidxTracing = "1.3.0-alpha02"
androidxUiAutomator = "2.3.0" androidxUiAutomator = "2.3.0"
androidxWindowManager = "1.3.0" androidxWindowManager = "1.3.0"
androidxWork = "2.10.0" androidxWork = "2.10.0"
dependencyGuard = "0.5.0" dependencyGuard = "0.5.0"
firebaseBom = "33.7.0" firebaseBom = "33.7.0"
firebaseCrashlyticsPlugin = "3.0.2" firebaseCrashlyticsPlugin = "3.0.6"
firebasePerfPlugin = "1.4.2" firebasePerfPlugin = "2.0.1"
gmsPlugin = "4.4.2" gmsPlugin = "4.4.2"
googleOss = "17.1.0" googleOss = "17.1.0"
googleOssPlugin = "0.10.6" googleOssPlugin = "0.10.8"
hilt = "2.56" hilt = "2.56"
hiltExt = "1.2.0" hiltExt = "1.2.0"
jacoco = "0.8.12" jacoco = "0.8.12"
@ -46,7 +46,7 @@ kotlinxCoroutines = "1.10.1"
kotlinxDatetime = "0.6.1" kotlinxDatetime = "0.6.1"
kotlinxSerializationJson = "1.8.0" kotlinxSerializationJson = "1.8.0"
ksp = "2.1.10-1.0.31" ksp = "2.1.10-1.0.31"
moduleGraph = "2.7.1" moduleGraph = "2.9.0"
okhttp = "4.12.0" okhttp = "4.12.0"
protobuf = "4.29.2" protobuf = "4.29.2"
protobufPlugin = "0.9.4" protobufPlugin = "0.9.4"
@ -54,8 +54,7 @@ retrofit = "2.11.0"
retrofitKotlinxSerializationJson = "1.0.0" retrofitKotlinxSerializationJson = "1.0.0"
robolectric = "4.14.1" robolectric = "4.14.1"
roborazzi = "1.39.0" roborazzi = "1.39.0"
room = "2.6.1" room = "2.7.2"
secrets = "2.0.1"
truth = "1.4.4" truth = "1.4.4"
turbine = "1.2.0" turbine = "1.2.0"
@ -120,7 +119,6 @@ firebase-cloud-messaging = { group = "com.google.firebase", name = "firebase-mes
firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics" } firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics" }
firebase-performance = { group = "com.google.firebase", name = "firebase-perf" } firebase-performance = { group = "com.google.firebase", name = "firebase-perf" }
google-oss-licenses = { group = "com.google.android.gms", name = "play-services-oss-licenses", version.ref = "googleOss" } google-oss-licenses = { group = "com.google.android.gms", name = "play-services-oss-licenses", version.ref = "googleOss" }
google-oss-licenses-plugin = { group = "com.google.android.gms", name = "oss-licenses-plugin", version.ref = "googleOssPlugin" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-android-testing = { group = "com.google.dagger", name = "hilt-android-testing", version.ref = "hilt" } hilt-android-testing = { group = "com.google.dagger", name = "hilt-android-testing", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" } hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }
@ -154,7 +152,7 @@ truth = { group = "com.google.truth", name = "truth", version.ref = "truth" }
turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbine" } turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbine" }
# Dependencies of the included build-logic # Dependencies of the included build-logic
android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } android-gradleApiPlugin = { group = "com.android.tools.build", name = "gradle-api", version.ref = "androidGradlePlugin" }
android-tools-common = { group = "com.android.tools", name = "common", version.ref = "androidTools" } android-tools-common = { group = "com.android.tools", name = "common", version.ref = "androidTools" }
compose-gradlePlugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" } compose-gradlePlugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" }
firebase-crashlytics-gradlePlugin = { group = "com.google.firebase", name = "firebase-crashlytics-gradle", version.ref = "firebaseCrashlyticsPlugin" } firebase-crashlytics-gradlePlugin = { group = "com.google.firebase", name = "firebase-crashlytics-gradle", version.ref = "firebaseCrashlyticsPlugin" }
@ -179,10 +177,10 @@ kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
module-graph = { id = "com.jraska.module.graph.assertion", version.ref = "moduleGraph" } 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" } protobuf = { id = "com.google.protobuf", version.ref = "protobufPlugin" }
roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" } roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" }
room = { id = "androidx.room", version.ref = "room" } 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 # Plugins defined by this project
nowinandroid-android-application = { id = "nowinandroid.android.application" } nowinandroid-android-application = { id = "nowinandroid.android.application" }

Binary file not shown.

@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionSha256Sum=8fad3d78296ca518113f3d29016617c7f9367dc005f932bd9d93bf45ba46072b
distributionSha256Sum=20f1b1176237254a6fc204d8434196fa11a4cfb387567519c61556e8710aed78 distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

8
gradlew vendored

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# Copyright © 2015-2021 the original authors. # Copyright © 2015 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -114,7 +114,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;; NONSTOP* ) nonstop=true ;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
@ -205,7 +205,7 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command: # Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped. # and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line. # treated as '${Hostname}' itself on the command line.
@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \ -classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@" "$@"
# Stop when "xargs" is not available. # Stop when "xargs" is not available.

4
gradlew.bat vendored

@ -70,11 +70,11 @@ goto fail
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

@ -1,4 +0,0 @@
## This file provides default values to modules using the secrets-gradle-plugin. It is necessary
# because the secrets properties file is not under source control so CI builds will fail without
# default values.
BACKEND_URL="http://example.com"
Loading…
Cancel
Save