diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index aa3ec5669..000000000 --- a/app/build.gradle +++ /dev/null @@ -1,105 +0,0 @@ -plugins { - id 'com.android.application' - id 'org.jetbrains.kotlin.android' - id 'kotlin-kapt' - id 'com.google.dagger.hilt.android' -} - -android { - namespace 'com.google.jetpackcamera' - compileSdk 33 - - defaultConfig { - applicationId "com.google.jetpackcamera" - minSdk 21 - targetSdk 33 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - vectorDrawables { - useSupportLibrary true - } - } - - buildTypes { - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - kotlin { - jvmToolchain(17) - } - buildFeatures { - compose true - } - composeOptions { - kotlinCompilerExtensionVersion '1.4.0' - } - packagingOptions { - resources { - excludes += '/META-INF/{AL2.0,LGPL2.1}' - } - } -} - -dependencies { - // Compose - def composeBom = platform('androidx.compose:compose-bom:2022.12.00') - implementation composeBom - androidTestImplementation composeBom - - // Compose - Material Design 3 - implementation 'androidx.compose.material3:material3' - - // Compose - Android Studio Preview support - implementation 'androidx.compose.ui:ui-tooling-preview' - debugImplementation 'androidx.compose.ui:ui-tooling' - - // Compose - Integration with ViewModels - implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1' - - // Compose - Integration with Activities - implementation 'androidx.activity:activity-compose' - - // Compose - Testing - androidTestImplementation "androidx.compose.ui:ui-test-junit4" - - // Testing - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - - implementation 'androidx.core:core-ktx:1.8.0' - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' - - // Hilt - implementation "com.google.dagger:hilt-android:2.44" - kapt "com.google.dagger:hilt-compiler:2.44" - - // Accompanist - Permissions - implementation 'com.google.accompanist:accompanist-permissions:0.26.5-rc' - - // Jetpack Navigation - def nav_version = "2.5.3" - implementation "androidx.navigation:navigation-compose:$nav_version" - - // Access Settings data - implementation project(path: ':data:settings') - - // Camera Preview - implementation(project(":feature:preview")) - - // Settings Screen - implementation(project(":feature:settings")) -} - -// Allow references to generated code -kapt { - correctErrorTypes true -} \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 000000000..2e46dcde9 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,108 @@ +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") + id("kotlin-kapt") + id("com.google.dagger.hilt.android") +} + +android { + namespace = "com.google.jetpackcamera" + compileSdk = 34 + + defaultConfig { + applicationId = "com.google.jetpackcamera" + minSdk = 21 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlin { + jvmToolchain(17) + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.4.0" + } + packagingOptions { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } +} + +dependencies { + // Compose + val composeBom = platform("androidx.compose:compose-bom:2023.08.00") + implementation(composeBom) + androidTestImplementation(composeBom) + + // Compose - Material Design 3 + implementation("androidx.compose.material3:material3") + + // Compose - Android Studio Preview support + implementation("androidx.compose.ui:ui-tooling-preview") + debugImplementation("androidx.compose.ui:ui-tooling") + + // Compose - Integration with ViewModels + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1") + + // Compose - Integration with Activities + implementation("androidx.activity:activity-compose") + + // Compose - Testing + androidTestImplementation("androidx.compose.ui:ui-test-junit4") + + // Testing + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.3") + androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") + + implementation("androidx.core:core-ktx:1.8.0") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.3.1") + + // Hilt + implementation("com.google.dagger:hilt-android:2.44") + kapt("com.google.dagger:hilt-compiler:2.44") + + // Accompanist - Permissions + implementation("com.google.accompanist:accompanist-permissions:0.26.5-rc") + + // Jetpack Navigation + val nav_version = "2.5.3" + implementation("androidx.navigation:navigation-compose:$nav_version") + + // Access Settings data + implementation(project(":data:settings")) + + // Camera Preview + implementation(project(":feature:preview")) + + // Settings Screen + implementation(project(":feature:settings")) +} + +// Allow references to generated code +kapt { + correctErrorTypes = true +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 481bb4348..ff59496d8 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/app/src/main/java/com/google/jetpackcamera/ui/JcaApp.kt b/app/src/main/java/com/google/jetpackcamera/ui/JcaApp.kt index 77ded6c4f..e17b34579 100644 --- a/app/src/main/java/com/google/jetpackcamera/ui/JcaApp.kt +++ b/app/src/main/java/com/google/jetpackcamera/ui/JcaApp.kt @@ -18,6 +18,7 @@ package com.google.jetpackcamera.ui import android.Manifest import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.navigation.NavHostController @@ -45,6 +46,7 @@ fun JcaApp() { } } +@OptIn(ExperimentalMaterial3Api::class) @Composable private fun JetpackCameraNavHost( modifier: Modifier, diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 085910fbb..000000000 --- a/build.gradle +++ /dev/null @@ -1,11 +0,0 @@ -buildscript { - ext { - compose_version = '1.3.0' - } -}// Top-level build file where you can add configuration options common to all sub-projects/modules. -plugins { - id 'com.android.application' version '8.0.0' apply false - id 'com.android.library' version '8.0.0' apply false - id 'org.jetbrains.kotlin.android' version '1.8.0' apply false - id 'com.google.dagger.hilt.android' version '2.44' apply false -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000..88ccec2a7 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,7 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + id("com.android.application") version "8.1.1" apply false + id("com.android.library") version "8.1.1" apply false + id("org.jetbrains.kotlin.android") version "1.8.0" apply false + id("com.google.dagger.hilt.android") version "2.44" apply false +} \ No newline at end of file diff --git a/camera-viewfinder-compose/build.gradle b/camera-viewfinder-compose/build.gradle deleted file mode 100644 index 69bd09c98..000000000 --- a/camera-viewfinder-compose/build.gradle +++ /dev/null @@ -1,68 +0,0 @@ -plugins { - id 'com.android.library' - id 'org.jetbrains.kotlin.android' -} - -android { - namespace 'com.google.jetpackcamera.camerax' - compileSdk 33 - - defaultConfig { - minSdk 21 - targetSdk 33 - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles "consumer-rules.pro" - } - - buildTypes { - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - kotlin { - jvmToolchain(17) - } - buildFeatures { - compose true - } - composeOptions { - kotlinCompilerExtensionVersion '1.4.0' - } -} - -dependencies { - // Compose - def composeBom = platform('androidx.compose:compose-bom:2022.12.00') - implementation composeBom - androidTestImplementation composeBom - - // Compose - Material Design 3 - implementation 'androidx.compose.material3:material3' - - // Compose - Testing - androidTestImplementation "androidx.compose.ui:ui-test-junit4" - - // Compose - Android Studio Preview support - implementation 'androidx.compose.ui:ui-tooling-preview' - implementation 'androidx.compose.ui:ui-tooling' - - // Testing - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - - // CameraX - def camerax_version = "1.3.0-alpha05" - implementation "androidx.camera:camera-core:${camerax_version}" - implementation "androidx.camera:camera-view:${camerax_version}" - - // AndroidX Core - def core_version = "1.9.0" - implementation "androidx.core:core:{$core_version}" -} diff --git a/camera-viewfinder-compose/build.gradle.kts b/camera-viewfinder-compose/build.gradle.kts new file mode 100644 index 000000000..080315eaa --- /dev/null +++ b/camera-viewfinder-compose/build.gradle.kts @@ -0,0 +1,71 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "com.google.jetpackcamera.camerax" + compileSdk = 34 + + defaultConfig { + minSdk = 21 + targetSdk = 34 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlin { + jvmToolchain(17) + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.4.0" + } +} + +dependencies { + // Compose + val composeBom = platform("androidx.compose:compose-bom:2023.08.00") + implementation(composeBom) + androidTestImplementation(composeBom) + + // Compose - Material Design 3 + implementation("androidx.compose.material3:material3") + + // Compose - Testing + androidTestImplementation("androidx.compose.ui:ui-test-junit4") + + // Compose - Android Studio Preview support + implementation("androidx.compose.ui:ui-tooling-preview") + implementation("androidx.compose.ui:ui-tooling") + + // Testing + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.3") + androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") + + // CameraX + val camerax_version = "1.3.0-SNAPSHOT" + implementation("androidx.camera:camera-core:${camerax_version}") + implementation("androidx.camera:camera-view:${camerax_version}") + + // AndroidX Core + val core_version = "1.9.0" + implementation("androidx.core:core:{$core_version}") +} diff --git a/camera-viewfinder-compose/proguard-rules.pro b/camera-viewfinder-compose/proguard-rules.pro index 481bb4348..ff59496d8 100644 --- a/camera-viewfinder-compose/proguard-rules.pro +++ b/camera-viewfinder-compose/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/core/common/build.gradle b/core/common/build.gradle deleted file mode 100644 index 65128bd1b..000000000 --- a/core/common/build.gradle +++ /dev/null @@ -1,51 +0,0 @@ -plugins { - id 'com.android.library' - id 'org.jetbrains.kotlin.android' - id 'kotlin-kapt' - id 'com.google.dagger.hilt.android' -} - -android { - namespace 'com.google.jetpackcamera.core.common' - compileSdk 33 - - defaultConfig { - minSdk 21 - targetSdk 33 - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles "consumer-rules.pro" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - kotlin { - jvmToolchain(17) - } -} - -dependencies { - - implementation 'androidx.core:core-ktx:1.8.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.8.0' - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.5' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' - - // Hilt - implementation "com.google.dagger:hilt-android:2.44" - kapt "com.google.dagger:hilt-compiler:2.44" -} - -kapt { - correctErrorTypes true -} diff --git a/core/common/build.gradle.kts b/core/common/build.gradle.kts new file mode 100644 index 000000000..9ca60cbcc --- /dev/null +++ b/core/common/build.gradle.kts @@ -0,0 +1,53 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") + id("kotlin-kapt") + id("com.google.dagger.hilt.android") +} + +android { + namespace = "com.google.jetpackcamera.core.common" + compileSdk = 34 + + defaultConfig { + minSdk = 21 + targetSdk = 34 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlin { + jvmToolchain(17) + } +} + +dependencies { + + implementation("androidx.core:core-ktx:1.8.0") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.8.0") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + + // Hilt + implementation("com.google.dagger:hilt-android:2.44") + kapt("com.google.dagger:hilt-compiler:2.44") +} + +kapt { + correctErrorTypes = true +} diff --git a/core/common/proguard-rules.pro b/core/common/proguard-rules.pro index 481bb4348..ff59496d8 100644 --- a/core/common/proguard-rules.pro +++ b/core/common/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/data/settings/build.gradle b/data/settings/build.gradle deleted file mode 100644 index 09fd73049..000000000 --- a/data/settings/build.gradle +++ /dev/null @@ -1,81 +0,0 @@ -plugins { - id 'com.android.library' - id 'org.jetbrains.kotlin.android' - id 'kotlin-kapt' - id 'com.google.dagger.hilt.android' - id 'com.google.protobuf' version "0.9.1" -} - -android { - namespace 'com.google.jetpackcamera.data.settings' - compileSdk 33 - - defaultConfig { - minSdk 21 - targetSdk 33 - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles "consumer-rules.pro" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - kotlin { - jvmToolchain(17) - } -} - -dependencies { - implementation 'androidx.test:core-ktx:1.4.0' - - // Testing - testImplementation 'junit:junit:4.13.2' - - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" - androidTestImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4' - - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - - - // Hilt - implementation "com.google.dagger:hilt-android:2.44" - kapt "com.google.dagger:hilt-compiler:2.44" - - // proto datastore - implementation "androidx.datastore:datastore:1.0.0" - implementation "com.google.protobuf:protobuf-kotlin-lite:3.21.12" - -} - -protobuf { - protoc { - artifact = "com.google.protobuf:protoc:3.21.12" - } - - generateProtoTasks { - all().each { task -> - task.builtins { - java { - option 'lite' - } - kotlin { - option 'lite' - } - } - } - } -} - -// Allow references to generated code -kapt { - correctErrorTypes true -} diff --git a/data/settings/build.gradle.kts b/data/settings/build.gradle.kts new file mode 100644 index 000000000..b725e71aa --- /dev/null +++ b/data/settings/build.gradle.kts @@ -0,0 +1,87 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") + id("kotlin-kapt") + id("com.google.dagger.hilt.android") + id("com.google.protobuf") version "0.9.1" +} + +android { + namespace = "com.google.jetpackcamera.data.settings" + compileSdk = 34 + + defaultConfig { + minSdk = 21 + targetSdk = 34 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlin { + jvmToolchain(17) + } +} + +dependencies { + implementation("androidx.test:core-ktx:1.4.0") + + // Testing + testImplementation("junit:junit:4.13.2") + + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4") + androidTestImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4") + + androidTestImplementation("androidx.test.ext:junit:1.1.3") + androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") + + + // Hilt + implementation("com.google.dagger:hilt-android:2.44") + kapt("com.google.dagger:hilt-compiler:2.44") + + // proto datastore + implementation("androidx.datastore:datastore:1.0.0") + implementation("com.google.protobuf:protobuf-kotlin-lite:3.21.12") + +} + +protobuf { + protoc { + artifact = "com.google.protobuf:protoc:3.21.12" + } + + generateProtoTasks { + all().forEach {task -> + task.builtins { + create("java") { + option("lite") + } + } + + task.builtins { + create("kotlin") { + option("lite") + } + } + } + } +} + +// Allow references to generated code +kapt { + correctErrorTypes = true +} diff --git a/data/settings/proguard-rules.pro b/data/settings/proguard-rules.pro index 481bb4348..ff59496d8 100644 --- a/data/settings/proguard-rules.pro +++ b/data/settings/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/domain/camera/build.gradle b/domain/camera/build.gradle deleted file mode 100644 index b67b1c1da..000000000 --- a/domain/camera/build.gradle +++ /dev/null @@ -1,67 +0,0 @@ -plugins { - id 'com.android.library' - id 'org.jetbrains.kotlin.android' - id 'kotlin-kapt' - id 'com.google.dagger.hilt.android' -} - -android { - namespace 'com.google.jetpackcamera.data.camera' - compileSdk 33 - - defaultConfig { - minSdk 21 - targetSdk 33 - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles "consumer-rules.pro" - } - - buildTypes { - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - kotlin { - jvmToolchain(17) - } -} - -dependencies { - // Testing - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - - // Futures - implementation 'androidx.concurrent:concurrent-futures-ktx:1.1.0' - - // CameraX - def camerax_version = "1.3.0-alpha05" - implementation "androidx.camera:camera-core:${camerax_version}" - implementation "androidx.camera:camera-camera2:${camerax_version}" - implementation "androidx.camera:camera-lifecycle:${camerax_version}" - implementation "androidx.camera:camera-video:${camerax_version}" - - implementation "androidx.camera:camera-view:${camerax_version}" - implementation "androidx.camera:camera-extensions:${camerax_version}" - - // Hilt - implementation "com.google.dagger:hilt-android:2.44" - kapt "com.google.dagger:hilt-compiler:2.44" - - // access settings data - implementation project(path: ':data:settings') - - implementation(project(":core:common")) -} - -// Allow references to generated code -kapt { - correctErrorTypes true -} diff --git a/domain/camera/build.gradle.kts b/domain/camera/build.gradle.kts new file mode 100644 index 000000000..7840b83b1 --- /dev/null +++ b/domain/camera/build.gradle.kts @@ -0,0 +1,69 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") + id("kotlin-kapt") + id("com.google.dagger.hilt.android") +} + +android { + namespace = "com.google.jetpackcamera.data.camera" + compileSdk = 34 + + defaultConfig { + minSdk = 21 + targetSdk = 34 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlin { + jvmToolchain(17) + } +} + +dependencies { + // Testing + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.3") + androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") + + // Futures + implementation("androidx.concurrent:concurrent-futures-ktx:1.1.0") + + // CameraX + val camerax_version = "1.3.0-SNAPSHOT" + implementation("androidx.camera:camera-core:${camerax_version}") + implementation("androidx.camera:camera-camera2:${camerax_version}") + implementation("androidx.camera:camera-lifecycle:${camerax_version}") + implementation("androidx.camera:camera-video:${camerax_version}") + + implementation("androidx.camera:camera-view:${camerax_version}") + implementation("androidx.camera:camera-extensions:${camerax_version}") + + // Hilt + implementation("com.google.dagger:hilt-android:2.44") + kapt("com.google.dagger:hilt-compiler:2.44") + + // Project dependencies + implementation(project(":data:settings")) + implementation(project(":core:common")) +} + +// Allow references to generated code +kapt { + correctErrorTypes = true +} diff --git a/domain/camera/proguard-rules.pro b/domain/camera/proguard-rules.pro index 481bb4348..ff59496d8 100644 --- a/domain/camera/proguard-rules.pro +++ b/domain/camera/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/CameraUseCase.kt b/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/CameraUseCase.kt index df95b91c1..0cf636a0e 100644 --- a/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/CameraUseCase.kt +++ b/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/CameraUseCase.kt @@ -60,6 +60,8 @@ interface CameraUseCase { fun tapToFocus(display: Display, surfaceWidth: Int, surfaceHeight: Int, x: Float, y: Float) + suspend fun setSingleStreamCapture(singleStreamCapture: Boolean) + companion object { const val INVALID_ZOOM_SCALE = -1f } diff --git a/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/CameraXCameraUseCase.kt b/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/CameraXCameraUseCase.kt index 2fe55817c..a7ec42da6 100644 --- a/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/CameraXCameraUseCase.kt +++ b/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/CameraXCameraUseCase.kt @@ -69,26 +69,28 @@ class CameraXCameraUseCase @Inject constructor( private val defaultDispatcher: CoroutineDispatcher, private val settingsRepository: SettingsRepository ) : CameraUseCase { + + private var camera: Camera? = null private lateinit var cameraProvider: ProcessCameraProvider //TODO apply flash from settings - private val imageCaptureUseCase = ImageCapture.Builder() - .build() - - private val previewUseCase = Preview.Builder() - .build() + private val imageCaptureUseCase = ImageCapture.Builder().build() + private val previewUseCase = Preview.Builder().build() private val recorder = Recorder.Builder().setExecutor(defaultDispatcher.asExecutor()).build() private val videoCaptureUseCase = VideoCapture.withOutput(recorder) + private var recording: Recording? = null - private var useCaseGroup: UseCaseGroup? = null + private lateinit var useCaseGroup: UseCaseGroup - private var recording: Recording? = null + private lateinit var aspectRatio : AspectRatio + private var singleStreamCaptureEnabled = false + private var isFrontFacing = true - private var camera: Camera? = null override suspend fun initialize(currentCameraSettings: CameraAppSettings): List { - updateUseCaseGroup(currentCameraSettings.aspect_ratio) + this.aspectRatio = currentCameraSettings.aspect_ratio setFlashMode(currentCameraSettings.flash_mode_status) + updateUseCaseGroup() cameraProvider = ProcessCameraProvider.getInstance(application).await() val availableCameraLens = @@ -121,7 +123,7 @@ class CameraXCameraUseCase @Inject constructor( previewUseCase.setSurfaceProvider(surfaceProvider) - cameraProvider.runWith(cameraSelector, useCaseGroup!!) { + cameraProvider.runWith(cameraSelector, useCaseGroup) { camera = it awaitCancellation() } @@ -147,7 +149,8 @@ class CameraXCameraUseCase @Inject constructor( override fun startVideoRecording(scope: CoroutineScope): Job { Log.d(TAG, "recordVideo") - val name = "JCA-recording-${Date()}.mp4" + val captureTypeString = if(singleStreamCaptureEnabled) "SingleStream" else "MultiStream" + val name = "JCA-recording-${Date()}-$captureTypeString.mp4" val contentValues = ContentValues().apply { put(MediaStore.Video.Media.DISPLAY_NAME, name) } @@ -190,11 +193,9 @@ class CameraXCameraUseCase @Inject constructor( // flips the camera to the designated lensFacing direction override suspend fun flipCamera(isFrontFacing: Boolean) { - cameraProvider.unbindAll() + this.isFrontFacing = isFrontFacing rebindUseCases( - cameraLensToSelector( - getLensFacing(isFrontFacing) - ) + ) } @@ -231,22 +232,30 @@ class CameraXCameraUseCase @Inject constructor( } override suspend fun setAspectRatio(aspectRatio: AspectRatio, isFrontFacing: Boolean) { - updateUseCaseGroup(aspectRatio) - cameraProvider.unbindAll() - rebindUseCases( - cameraLensToSelector( - getLensFacing(isFrontFacing) - ) - ) + this.aspectRatio = aspectRatio + updateUseCaseGroup() + rebindUseCases() } - private fun updateUseCaseGroup(aspectRatio: AspectRatio) { - useCaseGroup = UseCaseGroup.Builder() + override suspend fun setSingleStreamCapture(singleStreamCapture: Boolean) { + singleStreamCaptureEnabled = singleStreamCapture + Log.d(TAG, "Changing CaptureMode: singleStreamCaptureEnabled: $singleStreamCaptureEnabled") + updateUseCaseGroup() + rebindUseCases() + } + + private fun updateUseCaseGroup() { + val useCaseGroupBuilder = UseCaseGroup.Builder() .setViewPort(ViewPort.Builder(aspectRatio.ratio, previewUseCase.targetRotation).build()) .addUseCase(previewUseCase) .addUseCase(imageCaptureUseCase) .addUseCase(videoCaptureUseCase) - .build() + + if (singleStreamCaptureEnabled) { + useCaseGroupBuilder.addEffect(SingleSurfaceForcingEffect()) + } + + useCaseGroup = useCaseGroupBuilder.build() } // converts LensFacing from datastore to @LensFacing Int value @@ -256,8 +265,12 @@ class CameraXCameraUseCase @Inject constructor( false -> CameraSelector.LENS_FACING_BACK } - private suspend fun rebindUseCases(cameraSelector: CameraSelector) { - cameraProvider.runWith(cameraSelector, useCaseGroup!!) { + private suspend fun rebindUseCases() { + val cameraSelector = cameraLensToSelector( + getLensFacing(isFrontFacing) + ) + cameraProvider.unbindAll() + cameraProvider.runWith(cameraSelector, useCaseGroup) { camera = it awaitCancellation() } diff --git a/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/EmptySurfaceProcessor.kt b/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/EmptySurfaceProcessor.kt new file mode 100644 index 000000000..cba3be06a --- /dev/null +++ b/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/EmptySurfaceProcessor.kt @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2023 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 + * + * http://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.google.jetpackcamera.domain.camera + +import android.annotation.SuppressLint +import android.graphics.SurfaceTexture +import android.os.Handler +import android.os.HandlerThread +import android.view.Surface +import androidx.camera.core.DynamicRange +import androidx.camera.core.SurfaceOutput +import androidx.camera.core.SurfaceProcessor +import androidx.camera.core.SurfaceRequest +import androidx.camera.core.impl.utils.executor.CameraXExecutors.newHandlerExecutor +import androidx.camera.core.processing.OpenGlRenderer +import androidx.camera.core.processing.ShaderProvider +import java.util.concurrent.Executor + +private const val GL_THREAD_NAME = "EmptySurfaceProcessor" + +/** + * This is a [SurfaceProcessor] that passes on the same content from the input + * surface to the output surface. Used to make a copies of surfaces. + */ +@SuppressLint("RestrictedApi") +class EmptySurfaceProcessor : SurfaceProcessor { + + private val glThread : HandlerThread = HandlerThread(GL_THREAD_NAME) + private var glHandler: Handler + var glExecutor: Executor + private set + + // Members below are only accessed on GL thread. + private val glRenderer: OpenGlRenderer = OpenGlRenderer() + private val outputSurfaces: MutableMap = mutableMapOf() + private val textureTransform: FloatArray = FloatArray(16) + private val surfaceTransform: FloatArray = FloatArray(16) + private var isReleased = false + + init { + glThread.start() + glHandler = Handler(glThread.looper) + glExecutor = newHandlerExecutor(glHandler) + glExecutor.execute { + glRenderer.init( + DynamicRange.SDR, + ShaderProvider.DEFAULT + ) + } + } + override fun onInputSurface(surfaceRequest: SurfaceRequest) { + checkGlThread() + if (isReleased) { + surfaceRequest.willNotProvideSurface() + return + } + val surfaceTexture = SurfaceTexture(glRenderer.textureName) + surfaceTexture.setDefaultBufferSize( + surfaceRequest.resolution.width, surfaceRequest.resolution.height + ) + val surface = Surface(surfaceTexture) + surfaceRequest.provideSurface(surface, glExecutor) { + surfaceTexture.setOnFrameAvailableListener(null) + surfaceTexture.release() + surface.release() + } + surfaceTexture.setOnFrameAvailableListener({ + checkGlThread() + if (!isReleased) { + surfaceTexture.updateTexImage() + surfaceTexture.getTransformMatrix(textureTransform) + outputSurfaces.forEach {(surfaceOutput, surface) -> + run { + surfaceOutput.updateTransformMatrix(surfaceTransform, textureTransform) + glRenderer.render(surfaceTexture.timestamp, surfaceTransform, surface) + } + } + } + }, glHandler) + } + + override fun onOutputSurface(surfaceOutput: SurfaceOutput) { + checkGlThread() + if (isReleased) { + surfaceOutput.close() + return + } + val surface = surfaceOutput.getSurface(glExecutor) { + surfaceOutput.close() + outputSurfaces.remove(surfaceOutput)?.let { removedSurface -> + glRenderer.unregisterOutputSurface(removedSurface) + } + } + glRenderer.registerOutputSurface(surface) + outputSurfaces[surfaceOutput] = surface + } + + /** + * Releases associated resources. + * + * Closes output surfaces. + * Releases the [OpenGlRenderer]. + * Quits the GL HandlerThread. + */ + fun release() { + glExecutor.execute { + releaseInternal() + } + } + + private fun releaseInternal() { + checkGlThread() + if (!isReleased) { + // Once release is called, we can stop sending frame to output surfaces. + for (surfaceOutput in outputSurfaces.keys) { + surfaceOutput.close() + } + outputSurfaces.clear() + glRenderer.release() + glThread.quitSafely() + isReleased = true + } + } + + private fun checkGlThread() { + check(GL_THREAD_NAME == Thread.currentThread().name) + } +} \ No newline at end of file diff --git a/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/SingleSurfaceForcingEffect.kt b/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/SingleSurfaceForcingEffect.kt new file mode 100644 index 000000000..17d7a3e7b --- /dev/null +++ b/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/SingleSurfaceForcingEffect.kt @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2023 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 + * + * http://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.google.jetpackcamera.domain.camera + +import androidx.camera.core.CameraEffect + +private const val TARGETS = + CameraEffect.PREVIEW or CameraEffect.VIDEO_CAPTURE or CameraEffect.IMAGE_CAPTURE + +private val emptySurfaceProcessor = EmptySurfaceProcessor() + +/** + * [CameraEffect] that applies a no-op effect. + * + * Essentially copying the camera input to the targets, + * Preview, VideoCapture and ImageCapture. + * + * Used as a workaround to force the above 3 use cases to use a single camera stream. + */ +class SingleSurfaceForcingEffect : CameraEffect( + TARGETS, + emptySurfaceProcessor.glExecutor, + emptySurfaceProcessor, + {} +) { + fun release() { + emptySurfaceProcessor.release() + } +} diff --git a/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/test/FakeCameraUseCase.kt b/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/test/FakeCameraUseCase.kt index 9b8c00299..8566ce0ff 100644 --- a/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/test/FakeCameraUseCase.kt +++ b/domain/camera/src/main/java/com/google/jetpackcamera/domain/camera/test/FakeCameraUseCase.kt @@ -116,4 +116,8 @@ class FakeCameraUseCase : CameraUseCase { ) { TODO("Not yet implemented") } + + override suspend fun setSingleStreamCapture(singleStreamCapture: Boolean) { + TODO("Not yet implemented") + } } \ No newline at end of file diff --git a/feature/preview/build.gradle b/feature/preview/build.gradle deleted file mode 100644 index c3aa86663..000000000 --- a/feature/preview/build.gradle +++ /dev/null @@ -1,95 +0,0 @@ -plugins { - id 'com.android.library' - id 'org.jetbrains.kotlin.android' - id 'kotlin-kapt' - id 'com.google.dagger.hilt.android' -} - -android { - namespace 'com.google.jetpackcamera.feature.preview' - compileSdk 33 - - defaultConfig { - minSdk 21 - targetSdk 33 - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles "consumer-rules.pro" - } - - buildTypes { - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - kotlin { - jvmToolchain(17) - } - buildFeatures { - compose true - } - composeOptions { - kotlinCompilerExtensionVersion '1.4.0' - } - testOptions { - unitTests.returnDefaultValues = true - } -} - -dependencies { - // Compose - def composeBom = platform('androidx.compose:compose-bom:2022.12.00') - implementation composeBom - androidTestImplementation composeBom - - // Compose - Material Design 3 - implementation 'androidx.compose.material3:material3' - - // Compose - Android Studio Preview support - implementation 'androidx.compose.ui:ui-tooling-preview' - debugImplementation 'androidx.compose.ui:ui-tooling' - - // Compose - Integration with ViewModels with Navigation and Hilt - implementation("androidx.hilt:hilt-navigation-compose:1.0.0") - - // Compose - Testing - androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" - - // Testing - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - testImplementation "org.mockito:mockito-core:5.2.0" - testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6" - - // Guava - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.4.1' - - // CameraX - def camerax_version = "1.3.0-alpha05" - implementation "androidx.camera:camera-core:${camerax_version}" - implementation "androidx.camera:camera-view:${camerax_version}" - - // Hilt - implementation "com.google.dagger:hilt-android:2.44" - kapt "com.google.dagger:hilt-compiler:2.44" - - // access settings data - implementation project(path: ':data:settings') - - implementation(project(":domain:camera")) - implementation(project(':camera-viewfinder-compose')) - - // Quick Settings - implementation(project(":feature:quicksettings")) -} - -// Allow references to generated code -kapt { - correctErrorTypes true -} \ No newline at end of file diff --git a/feature/preview/build.gradle.kts b/feature/preview/build.gradle.kts new file mode 100644 index 000000000..7e3f081c6 --- /dev/null +++ b/feature/preview/build.gradle.kts @@ -0,0 +1,97 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") + id("kotlin-kapt") + id("com.google.dagger.hilt.android") +} + +android { + namespace = "com.google.jetpackcamera.feature.preview" + compileSdk = 34 + + defaultConfig { + minSdk = 21 + targetSdk = 34 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlin { + jvmToolchain(17) + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.4.0" + } + testOptions { + unitTests { + isReturnDefaultValues = true + } + } +} + +dependencies { + // Compose + val composeBom = platform("androidx.compose:compose-bom:2023.08.00") + implementation(composeBom) + androidTestImplementation(composeBom) + + // Compose - Material Design 3 + implementation("androidx.compose.material3:material3") + + // Compose - Android Studio Preview support + implementation("androidx.compose.ui:ui-tooling-preview") + debugImplementation("androidx.compose.ui:ui-tooling") + + // Compose - Integration with ViewModels with Navigation and Hilt + implementation("androidx.hilt:hilt-navigation-compose:1.0.0") + + // Compose - Testing + androidTestImplementation("androidx.compose.ui:ui-test-junit4") + + // Testing + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.3") + androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") + testImplementation("org.mockito:mockito-core:5.2.0") + testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6") + + // Guava + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.4.1") + + // CameraX + val camerax_version = "1.3.0-SNAPSHOT" + implementation("androidx.camera:camera-core:${camerax_version}") + implementation("androidx.camera:camera-view:${camerax_version}") + + // Hilt + implementation("com.google.dagger:hilt-android:2.44") + kapt("com.google.dagger:hilt-compiler:2.44") + + // Project dependencies + implementation(project(":data:settings")) + implementation(project(":domain:camera")) + implementation(project(":camera-viewfinder-compose")) + implementation(project(":feature:quicksettings")) +} + +// Allow references to generated code +kapt { + correctErrorTypes = true +} \ No newline at end of file diff --git a/feature/preview/proguard-rules.pro b/feature/preview/proguard-rules.pro index 481bb4348..ff59496d8 100644 --- a/feature/preview/proguard-rules.pro +++ b/feature/preview/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt index e278e3443..087395595 100644 --- a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt +++ b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt @@ -42,8 +42,12 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Settings +import androidx.compose.material3.Button +import androidx.compose.material3.ChipColors +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.SuggestionChip import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -76,6 +80,7 @@ private const val TAG = "PreviewScreen" * Screen used for the Preview feature. */ @OptIn(ExperimentalComposeUiApi::class) +@ExperimentalMaterial3Api @Composable fun PreviewScreen( onNavigateToSettings: () -> Unit, @@ -118,31 +123,31 @@ fun PreviewScreen( Text(text = stringResource(R.string.camera_not_ready)) } else if (previewUiState.cameraState == CameraState.READY) { BoxWithConstraints( - Modifier.background(Color.Black) + Modifier + .background(Color.Black) .pointerInput(Unit) { - detectTapGestures( - onDoubleTap = { offset -> - // double tap to flip camera - Log.d(TAG, "onDoubleTap $offset") - viewModel.flipCamera() - }, - onTap = { offset -> - // tap to focus - try { - viewModel.tapToFocus( - viewInfo.display, - viewInfo.width, - viewInfo.height, - offset.x, offset.y - ) - Log.d(TAG, "onTap $offset") - } catch (e: UninitializedPropertyAccessException) { - Log.d(TAG, "onTap $offset") - e.printStackTrace() + detectTapGestures( + onDoubleTap = { offset -> + Log.d(TAG, "onDoubleTap $offset") + viewModel.flipCamera() + }, + onTap = { offset -> + // tap to focus + try { + viewModel.tapToFocus( + viewInfo.display, + viewInfo.width, + viewInfo.height, + offset.x, offset.y + ) + Log.d(TAG, "onTap $offset") + } catch (e: UninitializedPropertyAccessException) { + Log.d(TAG, "onTap $offset") + e.printStackTrace() + } } - } - ) - }, + ) + }, contentAlignment = Alignment.Center ) { @@ -202,6 +207,24 @@ fun PreviewScreen( ) } + SuggestionChip( + onClick = { viewModel.toggleCaptureMode() }, + modifier = Modifier + .align(Alignment.TopEnd) + .padding(12.dp), + label = { + Text( + stringResource( + if (previewUiState.singleStreamCapture) { + R.string.capture_mode_single_stream + } else { + R.string.capture_mode_multi_stream + } + ) + ) + } + ) + Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.align(Alignment.BottomCenter) diff --git a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewUiState.kt b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewUiState.kt index cd6a4b863..f7f61af19 100644 --- a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewUiState.kt +++ b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewUiState.kt @@ -28,7 +28,8 @@ data class PreviewUiState( val currentCameraSettings: CameraAppSettings, // "quick" settings val lensFacing: Int = CameraSelector.LENS_FACING_BACK, val videoRecordingState: VideoRecordingState = VideoRecordingState.INACTIVE, - val quickSettingsIsOpen: Boolean = false + val quickSettingsIsOpen: Boolean = false, + val singleStreamCapture: Boolean = false, ) /** diff --git a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt index 2e7e6c66f..24717f012 100644 --- a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt +++ b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt @@ -140,6 +140,18 @@ class PreviewViewModel @Inject constructor( ) } + fun toggleCaptureMode() { + val singleStreamCapture = previewUiState.value.singleStreamCapture + viewModelScope.launch { + _previewUiState.emit( + previewUiState.value.copy( + singleStreamCapture = !singleStreamCapture + ) + ) + cameraUseCase.setSingleStreamCapture(!singleStreamCapture) + } + } + // sets the camera to a designated direction fun flipCamera(isFacingFront: Boolean) { // only flip if 2 directions are available diff --git a/feature/preview/src/main/res/values/strings.xml b/feature/preview/src/main/res/values/strings.xml index 1bf9d001a..233b865e4 100644 --- a/feature/preview/src/main/res/values/strings.xml +++ b/feature/preview/src/main/res/values/strings.xml @@ -17,4 +17,6 @@ Camera Not Ready Settings + Single Stream + Multi Stream \ No newline at end of file diff --git a/feature/quicksettings/build.gradle b/feature/quicksettings/build.gradle deleted file mode 100644 index f6edb633e..000000000 --- a/feature/quicksettings/build.gradle +++ /dev/null @@ -1,69 +0,0 @@ -plugins { - id 'com.android.library' - id 'org.jetbrains.kotlin.android' - id 'kotlin-kapt' -} - -android { - namespace 'com.google.jetpackcamera.quicksettings' - compileSdk 33 - - defaultConfig { - minSdk 21 - targetSdk 33 - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles "consumer-rules.pro" - } - - buildTypes { - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - kotlin { - jvmToolchain(17) - } - buildFeatures { - compose true - } - composeOptions { - kotlinCompilerExtensionVersion '1.4.0' - } -} - -dependencies { - implementation project(path: ':data:settings') - // Compose - def composeBom = platform('androidx.compose:compose-bom:2022.12.00') - implementation composeBom - androidTestImplementation composeBom - - // Compose - Material Design 3 - implementation 'androidx.compose.material3:material3' - - // Compose - Android Studio Preview support - implementation 'androidx.compose.ui:ui-tooling-preview' - debugImplementation 'androidx.compose.ui:ui-tooling' - - // Compose - Testing - androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" - - // Testing - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - - // Guava - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.4.1' -} - -// Allow references to generated code -kapt { - correctErrorTypes true -} \ No newline at end of file diff --git a/feature/quicksettings/build.gradle.kts b/feature/quicksettings/build.gradle.kts new file mode 100644 index 000000000..0df9aa565 --- /dev/null +++ b/feature/quicksettings/build.gradle.kts @@ -0,0 +1,73 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") + id("kotlin-kapt") +} + +android { + namespace = "com.google.jetpackcamera.quicksettings" + compileSdk = 34 + + defaultConfig { + minSdk = 21 + targetSdk = 34 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlin { + jvmToolchain(17) + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.4.0" + } +} + +dependencies { + // Compose + val composeBom = platform("androidx.compose:compose-bom:2023.08.00") + implementation(composeBom) + androidTestImplementation(composeBom) + + // Compose - Material Design 3 + implementation("androidx.compose.material3:material3") + + // Compose - Android Studio Preview support + implementation("androidx.compose.ui:ui-tooling-preview") + debugImplementation("androidx.compose.ui:ui-tooling") + + // Compose - Testing + androidTestImplementation("androidx.compose.ui:ui-test-junit4") + + // Testing + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.3") + androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") + + // Guava + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.4.1") + + implementation(project(":data:settings")) +} + +// Allow references to generated code +kapt { + correctErrorTypes = true +} \ No newline at end of file diff --git a/feature/quicksettings/proguard-rules.pro b/feature/quicksettings/proguard-rules.pro index 481bb4348..ff59496d8 100644 --- a/feature/quicksettings/proguard-rules.pro +++ b/feature/quicksettings/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/feature/settings/build.gradle b/feature/settings/build.gradle deleted file mode 100644 index 30274f5eb..000000000 --- a/feature/settings/build.gradle +++ /dev/null @@ -1,86 +0,0 @@ -plugins { - id 'com.android.library' - id 'org.jetbrains.kotlin.android' - id 'kotlin-kapt' - id 'com.google.dagger.hilt.android' -} - -android { - namespace 'com.google.jetpackcamera.settings' - compileSdk 33 - - defaultConfig { - minSdk 21 - targetSdk 33 - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles "consumer-rules.pro" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - kotlin { - jvmToolchain(17) - } - buildFeatures { - compose true - } - composeOptions { - kotlinCompilerExtensionVersion '1.4.0' - } -} - -dependencies { - // Compose - def composeBom = platform('androidx.compose:compose-bom:2022.12.00') - implementation composeBom - androidTestImplementation composeBom - - // Compose - Material Design 3 - implementation 'androidx.compose.material3:material3' - - // Compose - Android Studio Preview support - implementation 'androidx.compose.ui:ui-tooling-preview' - debugImplementation 'androidx.compose.ui:ui-tooling' - - // Compose - Integration with ViewModels with Navigation and Hilt - implementation("androidx.hilt:hilt-navigation-compose:1.0.0") - - // Compose - Testing - androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" - - // Testing - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - testImplementation "org.mockito:mockito-core:5.2.0" - testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6" - implementation 'androidx.test:core-ktx:1.5.0' - - - // Guava - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.4.1' - - // Hilt - implementation "com.google.dagger:hilt-android:2.44" - kapt "com.google.dagger:hilt-compiler:2.44" - - // proto datastore - implementation "androidx.datastore:datastore:1.0.0" - implementation "com.google.protobuf:protobuf-kotlin-lite:3.21.12" - - implementation(project(":data:settings")) -} - -// Allow references to generated code -kapt { - correctErrorTypes true -} \ No newline at end of file diff --git a/feature/settings/build.gradle.kts b/feature/settings/build.gradle.kts new file mode 100644 index 000000000..9a3894f28 --- /dev/null +++ b/feature/settings/build.gradle.kts @@ -0,0 +1,88 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") + id("kotlin-kapt") + id("com.google.dagger.hilt.android") +} + +android { + namespace = "com.google.jetpackcamera.settings" + compileSdk = 34 + + defaultConfig { + minSdk = 21 + targetSdk = 34 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlin { + jvmToolchain(17) + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.4.0" + } +} + +dependencies { + // Compose + val composeBom = platform("androidx.compose:compose-bom:2022.12.00") + implementation(composeBom) + androidTestImplementation(composeBom) + + // Compose - Material Design 3 + implementation("androidx.compose.material3:material3") + + // Compose - Android Studio Preview support + implementation("androidx.compose.ui:ui-tooling-preview") + debugImplementation("androidx.compose.ui:ui-tooling") + + // Compose - Integration with ViewModels with Navigation and Hilt + implementation("androidx.hilt:hilt-navigation-compose:1.0.0") + + // Compose - Testing + androidTestImplementation("androidx.compose.ui:ui-test-junit4") + + // Testing + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.3") + androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") + testImplementation("org.mockito:mockito-core:5.2.0") + testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6") + implementation("androidx.test:core-ktx:1.5.0") + + // Guava + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.4.1") + + // Hilt + implementation("com.google.dagger:hilt-android:2.44") + kapt("com.google.dagger:hilt-compiler:2.44") + + // Proto Datastore + implementation("androidx.datastore:datastore:1.0.0") + implementation("com.google.protobuf:protobuf-kotlin-lite:3.21.12") + + implementation(project(":data:settings")) +} + +// Allow references to generated code +kapt { + correctErrorTypes = true +} \ No newline at end of file diff --git a/feature/settings/proguard-rules.pro b/feature/settings/proguard-rules.pro index 481bb4348..ff59496d8 100644 --- a/feature/settings/proguard-rules.pro +++ b/feature/settings/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 6509c497f..000000000 --- a/settings.gradle +++ /dev/null @@ -1,23 +0,0 @@ -pluginManagement { - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} -dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) - repositories { - google() - mavenCentral() - } -} -rootProject.name = "Jetpack Camera" -include ':app' -include ':feature:preview' -include ':domain:camera' -include ':camera-viewfinder-compose' -include ':feature:settings' -include ':data:settings' -include ':core:common' -include ':feature:quicksettings' diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 000000000..a66bfecba --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + maven { + setUrl("https://androidx.dev/snapshots/builds/10707469/artifacts/repository") + } + google() + mavenCentral() + } +} +rootProject.name = "Jetpack Camera" +include(":app") +include(":feature:preview") +include(":domain:camera") +include(":camera-viewfinder-compose") +include(":feature:settings") +include(":data:settings") +include(":core:common") +include(":feature:quicksettings")