242 lines
8.1 KiB
Markdown
242 lines
8.1 KiB
Markdown
|
|
---
|
|
|
|
## 🛠️ Bước 1: Khởi tạo các file build cấu hình Gradle cho Android
|
|
|
|
Để Android Studio có thể nhận diện và compile dự án, bạn cần tạo các file cấu hình bằng Kotlin DSL (`.gradle.kts`) tại thư mục `android-project`.
|
|
|
|
### 1. Tạo file `android-project/settings.gradle.kts`
|
|
|
|
File này dùng để khai báo tên dự án và quản lý kho chứa thư viện (Repositories).
|
|
|
|
```kotlin
|
|
pluginManagement {
|
|
repositories {
|
|
google()
|
|
mavenCentral()
|
|
gradlePluginPortal()
|
|
}
|
|
}
|
|
dependencyResolutionManagement {
|
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
|
repositories {
|
|
google()
|
|
mavenCentral()
|
|
}
|
|
}
|
|
|
|
rootProject.name = "RetroPhotobooth"
|
|
include(":app")
|
|
|
|
```
|
|
|
|
### 2. Tạo file `android-project/build.gradle.kts` (Của thư mục gốc Android)
|
|
|
|
```kotlin
|
|
plugins {
|
|
id("com.android.application") version "8.2.2" apply false
|
|
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
|
|
}
|
|
|
|
```
|
|
|
|
### 3. Tạo file `android-project/app/build.gradle.kts` (Của module app)
|
|
|
|
Đây là nơi chúng ta khai báo SDK và các thư viện cần dùng (CameraX, Jetpack Compose hoặc XML Views). Ở đây mình cấu hình sẵn các dependency cho **CameraX**.
|
|
|
|
```kotlin
|
|
plugins {
|
|
id("com.android.application")
|
|
id("org.jetbrains.kotlin.android")
|
|
}
|
|
|
|
android {
|
|
namespace = "com.photobooth.app"
|
|
compileSdk = 34
|
|
|
|
defaultConfig {
|
|
applicationId = "com.photobooth.app"
|
|
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"
|
|
}
|
|
|
|
buildTypes {
|
|
release {
|
|
isMinifyEnabled = false
|
|
proguardFiles(
|
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
"proguard-rules.pro"
|
|
)
|
|
}
|
|
}
|
|
compileOptions {
|
|
sourceCompatibility = JavaVersion.VERSION_17
|
|
targetCompatibility = JavaVersion.VERSION_17
|
|
}
|
|
kotlinOptions {
|
|
jvmTarget = "17"
|
|
}
|
|
buildFeatures {
|
|
viewBinding = true // Bật ViewBinding để thao tác với giao diện dễ dàng
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
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")
|
|
|
|
// --- 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")
|
|
}
|
|
|
|
```
|
|
|
|
---
|
|
|
|
## 📸 Bước 2: Thiết lập Giao diện Chụp ảnh (XML Layout)
|
|
|
|
Tạo file giao diện hiển thị Camera preview và nút chụp ảnh tại đường dẫn:
|
|
`android-project/app/src/main/res/layout/activity_main.xml` *(Bạn cần tạo thêm các thư mục `res/layout` nếu chưa có)*.
|
|
|
|
```xml
|
|
<?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>
|
|
|
|
```
|
|
|
|
---
|
|
|
|
## 💻 Bước 3: Viết Code Logic Khởi Tạo CameraX (Kotlin)
|
|
|
|
Tạo file `MainActivity.kt` tại đường dẫn `android-project/app/src/main/java/com/photobooth/app/MainActivity.kt`. Đoạn code này thực hiện xin quyền Camera và kích hoạt kính ngắm.
|
|
|
|
```kotlin
|
|
package com.photobooth.app
|
|
|
|
import android.Manifest
|
|
import android.content.pm.PackageManager
|
|
import android.os.Bundle
|
|
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
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
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
|
|
}
|
|
|
|
override fun onDestroy() {
|
|
super.onDestroy()
|
|
cameraExecutor.shutdown()
|
|
}
|
|
|
|
companion object {
|
|
private const val REQUEST_CODE_PERMISSIONS = 10
|
|
private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
---
|
|
|
|
## 🏃♂️ Việc cần làm ngay lúc này của bạn:
|
|
|
|
1. **Mở Android Studio** trên Debian và thực hiện `Import Project`, trỏ tới thư mục `android-project`.
|
|
2. Hệ thống sẽ tự động đồng bộ hóa (Gradle Sync).
|
|
3. **Chạy thử nghiệm:** Bật Android Emulator (hoặc cắm điện thoại Android của bạn qua cổng USB bật gỡ lỗi ADB) để xem ứng dụng đã hiển thị được Camera lên màn hình chưa.
|
|
|
|
Khi luồng hiển thị Camera này chạy thành công, chúng ta sẽ chuyển sang code tính năng **Đếm ngược tự động chụp liên tiếp 4 tấm** và lưu file ảnh thô. |