Máy ảnh trong ứng dụng di động là một mô-đun phần cứng của thiết bị mà nhà phát triển có thể truy cập thông qua API hệ thống để chụp ảnh và quay video. Theo Google Android Developers (2025), CameraX được sử dụng trong hơn 85% ứng dụng Android yêu cầu chức năng máy ảnh. AVFoundation trên iOS và CameraX trên Android cung cấp các giao diện cấp cao che giấu sự phức tạp của việc quản lý phần cứng.
Những điểm chính
Máy ảnh di động là một mô-đun quang học tích hợp bao gồm ống kính, cảm biến hình ảnh và bộ xử lý tín hiệu hình ảnh (ISP). Nhà phát triển truy cập máy ảnh thông qua hệ điều hành bằng các framework chuyên dụng. Trên Android, đó là Camera2 API (cấp thấp) và CameraX (cấp cao, dựa trên Camera2), còn trên iOS — AVFoundation và UIKit cho các tình huống đơn giản. Mỗi nền tảng cung cấp bộ công cụ riêng, nhưng khái niệm chung là giống nhau: ứng dụng khởi tạo phiên chụp, cấu hình tham số (độ phân giải, lấy nét, phơi sáng) và nhận luồng khung hình hoặc ảnh riêng lẻ.
Máy ảnh di động hiện đại hỗ trợ nhiều chế độ chụp: HDR, chế độ ban đêm, chân dung với làm mờ hậu cảnh, quay video chuyển động chậm và ghi ở định dạng RAW. Nhà phát triển có quyền truy cập vào các cài đặt phần mềm: ISO (độ nhạy cảm biến), tốc độ màn trập (phơi sáng), cân bằng trắng, lấy nét (tự động và thủ công) và ổn định hình ảnh. Các thiết bị cao cấp có thể có tới 4 máy ảnh với tiêu cự khác nhau và ứng dụng có thể chọn máy ảnh cụ thể theo ID.
Các nền tảng di động cung cấp một số API để làm việc với máy ảnh, khác nhau về mức độ trừu tượng và chức năng. Việc chọn API cụ thể phụ thuộc vào yêu cầu của dự án: để chụp ảnh đơn giản, CameraX hoặc UIImagePickerController là đủ; cho các ứng dụng chuyên nghiệp, cần Camera2 hoặc AVFoundation với điều khiển cảm biến trực tiếp. Dưới đây là so sánh các API chính.
| API | Nền tảng | Cấp độ | Tính năng |
|---|---|---|---|
| CameraX | Android | Cao | Nhận biết vòng đời, 95% thiết bị |
| Camera2 | Android | Thấp | Kiểm soát hoàn toàn, RAW, Burst |
| AVFoundation | iOS | Trung bình | Kiểm soát chụp hoàn toàn |
| UIKit (UIImagePickerController) | iOS | Cao | Giao diện có sẵn, không tùy chỉnh |
CameraX là lựa chọn tối ưu cho hầu hết các ứng dụng Android cần máy ảnh mà không cần tùy chỉnh sâu. Thư viện tự động xử lý vòng đời của Activity và Fragment, hỗ trợ quyền và đảm bảo tương thích giữa các phiên bản Android khác nhau. CameraX đảm bảo hành vi nhất quán trên 95% thiết bị Android nhờ lớp tương thích của nó. Nếu bạn cần xem trước máy ảnh (Preview), chụp ảnh (ImageCapture) hoặc phân tích khung hình (ImageAnalysis) — CameraX xử lý cả ba tình huống mà không cần viết mã phức tạp.
Camera2 là API cấp thấp cho các tình huống chuyên nghiệp: ghi RAW, điều chỉnh phơi sáng thủ công, chụp liên tiếp và điều khiển đồng thời nhiều máy ảnh. Camera2 yêu cầu nhà phát triển hiểu sâu về quy trình chụp ảnh, quản lý StateMachine và xử lý callback. Chỉ sử dụng Camera2 nếu CameraX không đáp ứng được yêu cầu: ví dụ, ứng dụng quét tài liệu với lấy nét thủ công hoặc máy ảnh tùy chỉnh với độ phân giải không chuẩn.
Quyền truy cập máy ảnh cần có sự cho phép rõ ràng từ người dùng trên cả hai nền tảng. Trên Android, quyền CAMERA được thêm vào tệp kê khai và từ Android 6.0, quyền cũng phải được yêu cầu trong thời gian chạy thông qua ActivityCompat.requestPermissions. Trên iOS, khóa NSCameraUsageDescription được thêm vào Info.plist với mô tả lý do sử dụng máy ảnh. Nếu không có mô tả này, ứng dụng sẽ bị treo khi cố gắng truy cập máy ảnh. Từ iOS 14, hộp thoại quyền hiển thị không chỉ tên ứng dụng mà còn cả lý do đã chỉ định — cách diễn đạt phải rõ ràng cho người dùng.
CameraX đơn giản hóa việc làm việc với máy ảnh chỉ trong vài dòng mã. Để bắt đầu xem trước, bạn cần tạo một phiên bản Preview, liên kết nó với LifecycleOwner và lấy SurfaceProvider để hiển thị. Để chụp ảnh, ImageCapture với đích lưu được sử dụng. Dưới đây là ví dụ hoàn chỉnh về khởi động máy ảnh và chụp ảnh bằng CameraX trong Kotlin.
val preview = Preview.Builder()
.build()
.also {
it.surfaceProvider = viewFinder.surfaceProvider
}
val imageCapture = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build()
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener(Runnable {
val cameraProvider = cameraProviderFuture.get()
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture
)
} catch (e: Exception) {
Log.e("CameraX", "Liên kết thất bại", e)
}
}, ContextCompact.getMainExecutor(this))
Phương thức bindToLifecycle liên kết máy ảnh với vòng đời của Activity — khi màn hình xoay hoặc ứng dụng chuyển xuống nền, máy ảnh tự động được giải phóng. CameraSelector.DEFAULT_BACK_CAMERA chọn máy ảnh sau; cho máy ảnh trước, sử dụng DEFAULT_FRONT_CAMERA. Sau khi liên kết, Preview bắt đầu hiển thị luồng máy ảnh trong PreviewView và người dùng thấy hình ảnh máy ảnh trên màn hình.
val photoFile = File(
externalMediaDirs.firstOrNull(),
"IMG_${System.currentTimeMillis()}.jpg"
)
val outputOptions = ImageCapture.OutputFileOptions
.Builder(photoFile)
.build()
imageCapture.takePicture(
outputOptions,
ContextCompact.getMainExecutor(this),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
Log.d("CameraX", "Photo saved: ${photoFile.absolutePath}")
}
override fun onError(exception: ImageCaptureException) {
Log.e("CameraX", "Lỗi chụp", exception)
}
}
)
Phương thức takePicture chụp một khung hình từ máy ảnh và lưu nó vào tệp. OutputFileOptions hỗ trợ ghi vào File, ContentResolver và MediaStore. Trong callback onImageSaved, ứng dụng nhận thông báo lưu thành công và có thể cập nhật giao diện. CAPTURE_MODE_MINIMIZE_LATENCY đảm bảo tốc độ màn trập tối đa bằng cách giảm xử lý hậu kỳ.
Trên iOS, quyền truy cập máy ảnh được cung cấp bởi framework AVFoundation thông qua lớp AVCaptureSession. Nhà phát triển tạo một phiên chụp, thêm các đầu vào cần thiết (AVCaptureDeviceInput) và đầu ra (AVCapturePhotoOutput, AVCaptureVideoDataOutput) rồi khởi động phiên. AVCaptureVideoPreviewLayer được sử dụng để hiển thị xem trước. Dưới đây là ví dụ về thiết lập phiên để chụp ảnh trong Swift.
import AVFoundation
let captureSession = AVCaptureSession()
captureSession.sessionPreset = .photo
guard let camera = AVCaptureDevice.default(
for: .video
) else { return }
guard let input = try? AVCaptureDeviceInput(device: camera)
else { return }
let output = AVCapturePhotoOutput()
captureSession.addInput(input)
captureSession.addOutput(output)
DispatchQueue.global(qos: .userInitiated).async {
captureSession.startRunning()
}
AVCaptureSessionPreset.photo đặt độ phân giải tối ưu cho ảnh (thường là 12 MP trên các thiết bị hiện đại). Đầu vào là AVCaptureDeviceInput được tạo cho máy ảnh của thiết bị. Sau khi thêm đầu vào và đầu ra, phiên được khởi động trên một luồng nền thông qua startRunning — việc khởi động phiên có thể mất tới 200 ms trên các thiết bị cũ. Để chụp ảnh, capturePhoto(with:delegate:) được gọi và kết quả được trả về thông qua AVCapturePhotoCaptureDelegate.
Khi làm việc với máy ảnh trên thiết bị di động, cần xem xét các hạn chế về phần cứng: thiết bị nóng lên khi quay lâu, tiêu hao pin khi làm việc ở độ phân giải cao và chất lượng máy ảnh khác nhau trên các thiết bị. Trên Android, sự phân mảnh hệ sinh thái có nghĩa là cùng một cấu hình CameraX có thể hoạt động khác nhau trên các mẫu máy khác nhau. Trên iOS, các hạn chế chủ yếu liên quan đến cấp phép: sử dụng máy ảnh trong nền cần có sự cho phép đặc biệt từ Apple. Cũng cần nhớ rằng trình mô phỏng không có quyền truy cập vào máy ảnh thực — chỉ có thể kiểm tra trên thiết bị vật lý.
CameraX giải quyết vấn đề phân mảnh Android thông qua lớp tương thích CameraXConfig — thư viện tự động áp dụng các giải pháp thay thế cho các lỗi nhà sản xuất đã biết. Trên iOS, AVFoundation hoạt động nhất quán trên tất cả các thiết bị từ iOS 6, nhưng một số tính năng (như Chế độ chân dung hoặc LiDAR) chỉ khả dụng trên iPhone 12 và các mẫu mới hơn. Khi phát triển ứng dụng đa nền tảng, nên sử dụng Flutter hoặc React Native với plugin máy ảnh — chúng trừu tượng hóa sự khác biệt giữa các nền tảng và cung cấp API thống nhất cho cả hai hệ điều hành.
Câu hỏi thường gặp
Đối với hầu hết ứng dụng, CameraX được khuyến nghị vì dễ sử dụng, quản lý vòng đời tích hợp và tương thích với 95% thiết bị. Camera2 chỉ nên chọn khi cần RAW, chụp liên tiếp hoặc điều khiển cảm biến thủ công.
Trên Android, thêm quyền CAMERA vào tệp kê khai và yêu cầu trong thời gian chạy qua ActivityCompat.requestPermissions. Trên iOS, thêm NSCameraUsageDescription vào Info.plist với giải thích rõ ràng về lý do sử dụng máy ảnh.
Trên iOS, việc sử dụng máy ảnh trong nền bị hạn chế nghiêm ngặt — cần có sự cho phép đặc biệt từ Apple. Trên Android, máy ảnh có thể hoạt động trong nền thông qua dịch vụ tiền cảnh, nhưng điều này ảnh hưởng tiêu cực đến tuổi thọ pin và làm nóng thiết bị.
Trình mô phỏng iOS và trình giả lập Android không có quyền truy cập vào máy ảnh phần cứng — chúng không mô phỏng cảm biến vật lý. Để kiểm tra chức năng máy ảnh, luôn sử dụng thiết bị vật lý hoặc máy ảnh ngoài kết nối với máy tính.
ImageAnalysis là bộ phân tích luồng khung hình từ CameraX, chuyển mỗi khung hình đến ImageAnalysis.Analyzer để xử lý. Nó được sử dụng để nhận dạng mã QR, phát hiện khuôn mặt, quét tài liệu và các tác vụ thị giác máy tính khác.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm