diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index e3e8768b3..1a98c8a1b 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -86,8 +86,8 @@ jobs: api-level: ${{ matrix.api-level }} arch: x86_64 disable-animations: true - disk-size: 1500M - heap-size: 512M + disk-size: 2000M + heap-size: 600M script: ./gradlew connectedProdDebugAndroidTest -x :benchmark:connectedProdBenchmarkAndroidTest --stacktrace - name: Upload test reports diff --git a/README.md b/README.md index cb378e025..92ac2fb05 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ The app also uses [product flavors](https://developer.android.com/studio/build/build-variants#product-flavors) to control where content for the app should be loaded from. -The `demo` flavor uses static local data to allow immediate building and exploring the UI. +The `demo` flavor uses static local data to allow immediate building and exploring of the UI. The `prod` flavor makes real network calls to a backend server, providing up-to-date content. At this time, there is not a public backend available. @@ -90,21 +90,21 @@ In tests, **Now in Android** notably does _not_ use any mocking libraries. Instead, the production implementations can be replaced with test doubles using Hilt's testing APIs (or via manual constructor injection for `ViewModel` tests). -These test doubles implement the same interface as the production implementations, and generally +These test doubles implement the same interface as the production implementations and generally provide a simplified (but still realistic) implementation with additional testing hooks. This results in less brittle tests that may exercise more production code, instead of just verifying specific calls against mocks. Examples: - In instrumentation tests, a temporary folder is used to store the user's preferences, which is - wiped after reach test. + wiped after each test. This allows using the real `DataStore` and exercising all related code, instead of mocking the flow of data updates. - There are `Test` implementations of each repository, which implement the normal, full repository interface and also provide test-only hooks. `ViewModel` tests use these `Test` repositories, and thus can use the test-only hooks to - manipulate the the state of the `Test` repository and verify the resulting behavior, instead of + manipulate the state of the `Test` repository and verify the resulting behavior, instead of checking that specific repository methods were called. # UI @@ -130,7 +130,7 @@ The baseline profile for this app is located at [`app/src/main/baseline-prof.txt It contains rules that enable AOT compilation of the critical user path taken during app launch. For more information on baseline profiles, read [this document](https://developer.android.com/studio/profile/baselineprofiles). -> Note: The baseline profile needs to be re-generated for release builds that touched code which changes app startup. +> Note: The baseline profile needs to be re-generated for release builds that touch code which changes app startup. To generate the baseline profile, select the `benchmark` build variant and run the `BaselineProfileGenerator` benchmark test on an AOSP Android Emulator. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7f9fb1b30..0ce7872b3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import com.google.samples.apps.nowinandroid.FlavorDimension import com.google.samples.apps.nowinandroid.Flavor +import com.google.samples.apps.nowinandroid.FlavorDimension plugins { id("nowinandroid.android.application") @@ -115,9 +115,9 @@ dependencies { implementation(libs.androidx.activity.compose) implementation(libs.androidx.appcompat) implementation(libs.androidx.core.ktx) + implementation(libs.androidx.core.splashscreen) implementation(libs.androidx.compose.material3.windowSizeClass) implementation(libs.androidx.window.manager) - implementation(libs.material3) implementation(libs.androidx.profileinstaller) implementation(libs.coil.kt) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f21692f5f..821bc605e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,7 +27,7 @@ android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" - android:theme="@style/Theme.Nia"> + android:theme="@style/Theme.Nia.Splash"> override fun onCreate(savedInstanceState: Bundle?) { + installSplashScreen() super.onCreate(savedInstanceState) // Turn off the decor fitting system windows, which allows us to handle insets, diff --git a/app/src/main/java/com/google/samples/apps/nowinandroid/di/JankStatsModule.kt b/app/src/main/java/com/google/samples/apps/nowinandroid/di/JankStatsModule.kt index 6d11a9f68..90f844c1b 100644 --- a/app/src/main/java/com/google/samples/apps/nowinandroid/di/JankStatsModule.kt +++ b/app/src/main/java/com/google/samples/apps/nowinandroid/di/JankStatsModule.kt @@ -24,9 +24,6 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.components.ActivityComponent -import java.util.concurrent.Executor -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.asExecutor @Module @InstallIn(ActivityComponent::class) @@ -47,17 +44,11 @@ object JankStatsModule { return activity.window } - @Provides - fun providesDefaultExecutor(): Executor { - return Dispatchers.Default.asExecutor() - } - @Provides fun providesJankStats( window: Window, - executor: Executor, frameListener: JankStats.OnFrameListener ): JankStats { - return JankStats.createAndTrack(window, executor, frameListener) + return JankStats.createAndTrack(window, frameListener) } } diff --git a/app/src/main/java/com/google/samples/apps/nowinandroid/navigation/NiaNavHost.kt b/app/src/main/java/com/google/samples/apps/nowinandroid/navigation/NiaNavHost.kt index 92c0000e2..6d2206743 100644 --- a/app/src/main/java/com/google/samples/apps/nowinandroid/navigation/NiaNavHost.kt +++ b/app/src/main/java/com/google/samples/apps/nowinandroid/navigation/NiaNavHost.kt @@ -16,7 +16,6 @@ package com.google.samples.apps.nowinandroid.navigation -import androidx.compose.material3.windowsizeclass.WindowSizeClass import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.navigation.NavHostController @@ -43,7 +42,6 @@ fun NiaNavHost( navController: NavHostController, onNavigateToDestination: (NiaNavigationDestination, String) -> Unit, onBackClick: () -> Unit, - windowSizeClass: WindowSizeClass, modifier: Modifier = Modifier, startDestination: String = ForYouDestination.route ) { @@ -52,10 +50,8 @@ fun NiaNavHost( startDestination = startDestination, modifier = modifier, ) { - forYouGraph( - windowSizeClass = windowSizeClass - ) - bookmarksGraph(windowSizeClass) + forYouGraph() + bookmarksGraph() interestsGraph( navigateToTopic = { onNavigateToDestination( diff --git a/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaApp.kt b/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaApp.kt index 29fc62b67..5bb603911 100644 --- a/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaApp.kt +++ b/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaApp.kt @@ -105,7 +105,6 @@ fun NiaApp( navController = appState.navController, onBackClick = appState::onBackClick, onNavigateToDestination = appState::navigate, - windowSizeClass = appState.windowSizeClass, modifier = Modifier .padding(padding) .consumedWindowInsets(padding) diff --git a/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt b/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt index dc620490a..bf80984fa 100644 --- a/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt +++ b/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt @@ -143,7 +143,7 @@ class NiaAppState( private fun NavigationTrackingSideEffect(navController: NavHostController) { JankMetricDisposableEffect(navController) { metricsHolder -> val listener = NavController.OnDestinationChangedListener { _, destination, _ -> - metricsHolder.state?.addState("Navigation", destination.route.toString()) + metricsHolder.state?.putState("Navigation", destination.route.toString()) } navController.addOnDestinationChangedListener(listener) diff --git a/app/src/main/res/drawable/ic_splash.xml b/app/src/main/res/drawable/ic_splash.xml new file mode 100644 index 000000000..291d88677 --- /dev/null +++ b/app/src/main/res/drawable/ic_splash.xml @@ -0,0 +1,34 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index 78ed557f4..767663342 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -14,13 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. --> - + - - + + diff --git a/app/src/main/res/values-v23/themes.xml b/app/src/main/res/values-v23/themes.xml index 2a13f9c35..b637b1413 100644 --- a/app/src/main/res/values-v23/themes.xml +++ b/app/src/main/res/values-v23/themes.xml @@ -16,8 +16,7 @@ --> - diff --git a/app/src/main/res/values-v27/themes.xml b/app/src/main/res/values-v27/themes.xml index b322aee6b..969e51914 100644 --- a/app/src/main/res/values-v27/themes.xml +++ b/app/src/main/res/values-v27/themes.xml @@ -16,10 +16,8 @@ --> - diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 9ace165b5..82456f53a 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -14,29 +14,32 @@ See the License for the specific language governing permissions and limitations under the License. --> - + + + + - - - - + + - -