Implement 2_PROJECT_ANDROID: Gradle configuration, layout setup, and CameraX initial logic

This commit is contained in:
3dtours committed 2026-07-05 12:29:00 +07:00
1 parent a3b9c24936
commit df837a4c56
6 files changed
+357 -75

No files matched your search

+13 -36
View File
@@ -5,19 +5,16 @@ plugins {
android {
namespace = "com.photobooth.app"
compileSdk = 33
compileSdk = 34
defaultConfig {
applicationId = "com.photobooth.app"
minSdk = 24
targetSdk = 33
minSdk = 26 // Android 8.0 trở lên để hỗ trợ tốt các tính năng đồ họa
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
}
buildTypes {
@@ -30,48 +27,28 @@ android {
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "1.8"
jvmTarget = "17"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.1"
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
viewBinding = true // Bật ViewBinding để thao tác với giao diện dễ dàng
}
}
dependencies {
implementation("androidx.core:core-ktx:1.10.1")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")
implementation("androidx.activity:activity-compose:1.7.2")
implementation(platform("androidx.compose:compose-bom:2023.06.01"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.11.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
// CameraX dependencies for Sprint 1 Camera preview
val cameraVersion = "1.3.0-rc01"
// --- Thư viện CameraX Core ---
val cameraVersion = "1.3.1"
implementation("androidx.camera:camera-core:$cameraVersion")
implementation("androidx.camera:camera-camera2:$cameraVersion")
implementation("androidx.camera:camera-lifecycle:$cameraVersion")
implementation("androidx.camera:camera-view:$cameraVersion")
implementation("androidx.camera:camera-extensions:$cameraVersion")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation(platform("androidx.compose:compose-bom:2023.06.01"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
}
@@ -1,44 +1,72 @@
package com.photobooth.app
import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.CameraSelector
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.photobooth.app.databinding.ActivityMainBinding
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var cameraExecutor: ExecutorService
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState: Bundle?)
setContent {
MaterialTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Greeting("Retro Photobooth")
}
}
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// Xin quyền Camera
if (allPermissionsGranted()) {
startCamera()
} else {
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
}
cameraExecutor = Executors.newSingleThreadExecutor()
}
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// Cấu hình Kính ngắm (Preview)
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(binding.viewFinder.surfaceProvider)
}
// Chọn Camera Trước (Mặc định cho Photobooth)
val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA
try {
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(this, cameraSelector, preview)
} catch (xc: Exception) {
Toast.makeText(this, "Không thể khởi động Camera", Toast.LENGTH_SHORT).show()
}
}, ContextCompat.getMainExecutor(this))
}
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Welcome to $name!",
modifier = modifier
)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
MaterialTheme {
Greeting("Retro Photobooth")
override fun onDestroy() {
super.onDestroy()
cameraExecutor.shutdown()
}
companion object {
private const val REQUEST_CODE_PERMISSIONS = 10
private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
}
}
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#121212">
<!-- Màn hình xem trước Camera -->
<androidx.camera.view.PreviewView
android:id="@+id/viewFinder"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="3:4"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/controlPanel" />
<!-- Bảng điều khiển phía dưới -->
<RelativeLayout
android:id="@+id/controlPanel"
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="#000000"
app:layout_constraintBottom_toBottomOf="parent">
<!-- Nút chụp hình -->
<ImageButton
android:id="@+id/btnCapture"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_centerInParent="true"
android:background="@android:color/transparent"
android:src="@android:drawable/ic_menu_camera"
android:contentDescription="Capture Button" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
+2 -3
View File
@@ -1,5 +1,4 @@
// 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("org.jetbrains.kotlin.android") version "1.9.0" apply false
id("com.android.application") version "8.2.2" apply false
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
}
+1 -1
View File
@@ -13,5 +13,5 @@ dependencyResolutionManagement {
}
}
rootProject.name = "Retro Photobooth"
rootProject.name = "RetroPhotobooth"
include(":app")