Aparat w aplikacjach mobilnych — to moduł sprzętowy urządzenia, dostępny dla programisty przez systemowe API do przechwytywania obrazów i wideo. Według danych Google Android Developers (2025), CameraX jest używany w ponad 85% aplikacji na Androida wymagających pracy z aparatem. AVFoundation na iOS i CameraX na Androidzie zapewniają wysokopoziomowe interfejsy, ukrywające złożoność zarządzania sprzętem.
Najważniejsze
Mobilny aparat — to wbudowany moduł optyczny składający się z obiektywu, matrycy (czujnika) i procesora przetwarzania obrazu (ISP). Programista uzyskuje dostęp do aparatu przez system operacyjny za pomocą specjalnych frameworków. Na Androidzie są to Camera2 API (niskopoziomowy) i CameraX (wysokopoziomowy oparty na Camera2), na iOS — AVFoundation i UIKit dla prostych scenariuszy. Każda platforma zapewnia swój własny zestaw narzędzi, ale ogólna koncepcja jest taka sama: aplikacja inicjalizuje sesję przechwytywania, konfiguruje parametry (rozdzielczość, ostrość, ekspozycja) i otrzymuje strumień klatek lub pojedyncze obrazy.
Nowoczesne mobilne aparaty obsługują wiele trybów fotografowania: HDR, tryb nocny, portretowy z rozmyciem tła, zwolnione tempo i nagrywanie w formacie RAW. Dla programisty dostępne są ustawienia programowe: ISO (czułość matrycy), czas naświetlania (ekspozycja), balans bieli, ostrość (automatyczna i ręczna) oraz stabilizacja obrazu. Na flagowych urządzeniach dostępne są do 4 aparatów z różnymi ogniskowymi, a aplikacja może wybrać konkretny aparat po ID.
Na platformach mobilnych istnieje kilka API do pracy z aparatem, różniących się poziomem abstrakcji i funkcjonalnością. Wybór konkretnego API zależy od wymagań projektu: do prostego przechwytywania zdjęć wystarczy CameraX lub UIImagePickerController, do profesjonalnych aplikacji potrzebny jest Camera2 lub AVFoundation z bezpośrednim sterowaniem czujnikiem. Poniżej znajduje się porównanie głównych API.
| API | Platforma | Poziom | Cechy |
|---|---|---|---|
| CameraX | Android | Wysoki | Lifecycle-aware, 95% urządzeń |
| Camera2 | Android | Niski | Pełna kontrola, RAW, Burst |
| AVFoundation | iOS | Średni | Pełna kontrola przechwytywania |
| UIKit (UIImagePickerController) | iOS | Wysoki | Gotowy UI, bez dostosowywania |
CameraX — optymalny wybór dla większości aplikacji na Androida, które potrzebują aparatu bez zaawansowanego dostosowywania. Biblioteka automatycznie obsługuje cykl życia Activity i Fragment, wspiera uprawnienia i kompatybilność z różnymi wersjami Androida. CameraX gwarantuje takie samo działanie na 95% urządzeń Android dzięki warstwie kompatybilności. Jeśli potrzebny jest podgląd aparatu (Preview), przechwytywanie zdjęć (ImageCapture) lub analiza strumienia (ImageAnalysis) — CameraX radzi sobie ze wszystkimi trzema scenariuszami bez pisania złożonego kodu.
Camera2 — niskopoziomowe API do profesjonalnych scenariuszy: nagrywanie w RAW, ręczne ustawianie ekspozycji, zdjęcia seryjne (burst), sterowanie wieloma aparatami jednocześnie. Camera2 wymaga od programisty głębokiego zrozumienia potoku przechwytywania obrazów, zarządzania StateMachine i obsługi callbacków. Używaj Camera2 tylko jeśli CameraX nie pokrywa wymagań: na przykład do aplikacji skanowania dokumentów z ręcznym ustawianiem ostrości lub niestandardowych aparatów z nietypową rozdzielczością.
Dostęp do aparatu wymaga jawnej zgody użytkownika na obu platformach. Na Androidzie w manifeście dodaje się uprawnienie CAMERA, a począwszy od Androida 6.0 należy również żądać uprawnienia podczas działania przez ActivityCompat.requestPermissions. Na iOS w Info.plist dodaje się klucz NSCameraUsageDescription z opisem powodu użycia aparatu. Bez tego opisu aplikacja zostanie przymusowo zakończona przy próbie dostępu do aparatu. Od iOS 14 w oknie dialogowym uprawnień wyświetlana jest nie tylko nazwa aplikacji, ale także podany powód — sformułowanie powinno być zrozumiałe dla użytkownika.
CameraX upraszcza pracę z aparatem do kilku linii kodu. Aby uruchomić podgląd, należy utworzyć instancję Preview, powiązać ją z LifecycleOwner i uzyskać SurfaceProvider do wyświetlania. Do przechwytywania zdjęć używa się ImageCapture z celem zapisu. Poniżej znajduje się pełny przykład uruchomienia aparatu i robienia zdjęć za pomocą CameraX w Kotlinie.
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", "Niepowodzenie powiązania", e)
}
}, ContextCompact.getMainExecutor(this))
Metoda bindToLifecycle łączy aparat z cyklem życia Activity — przy obrocie ekranu lub przejściu w tło aparat jest automatycznie zwalniany. CameraSelector.DEFAULT_BACK_CAMERA wybiera tylny aparat, do przedniego używa się DEFAULT_FRONT_CAMERA. Po powiązaniu Preview zaczyna wyświetlać obraz z aparatu w PreviewView, a użytkownik widzi obraz z aparatu na ekranie.
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", "Błąd przechwytywania", exception)
}
}
)
Metoda takePicture wykonuje przechwycenie klatki z aparatu i zapisuje ją do pliku. OutputFileOptions obsługuje zapis do File, ContentResolver i MediaStore. W callback onImageSaved aplikacja otrzymuje powiadomienie o pomyślnym zapisie i może zaktualizować UI. CAPTURE_MODE_MINIMIZE_LATENCY zapewnia maksymalną szybkość działania migawki kosztem zmniejszenia post-processingu.
Na iOS dostęp do aparatu zapewnia framework AVFoundation przez klasę AVCaptureSession. Programista tworzy sesję przechwytywania, dodaje niezbędne wejścia (AVCaptureDeviceInput) i wyjścia (AVCapturePhotoOutput, AVCaptureVideoDataOutput) oraz uruchamia sesję. Do wyświetlania podglądu używa się AVCaptureVideoPreviewLayer. Poniżej znajduje się przykład konfiguracji sesji do przechwytywania zdjęć w 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 ustawia optymalną rozdzielczość zdjęcia (zwykle 12 MP na nowoczesnych urządzeniach). Wejściem jest AVCaptureDeviceInput utworzony dla aparatu urządzenia. Po dodaniu wejścia i wyjścia sesja uruchamiana jest w wątku tła przez startRunning — uruchomienie sesji może zająć do 200 ms na starszych urządzeniach. Do przechwytywania zdjęcia wywołuje się capturePhoto(with:delegate:), a wynik jest zwracany przez delegata AVCapturePhotoCaptureDelegate.
Podczas pracy z aparatem na urządzeniach mobilnych należy uwzględnić ograniczenia sprzętowe: nagrzewanie urządzenia przy długim fotografowaniu, rozładowanie baterii przy pracy z wysoką rozdzielczością i różną jakość aparatów na różnych urządzeniach. Na Androidzie fragmentacja ekosystemu prowadzi do tego, że ta sama konfiguracja CameraX może działać inaczej na różnych modelach. Na iOS ograniczenia dotyczą głównie licencjonowania: przy użyciu aparatu w tle wymagana jest osobna zgoda Apple. Należy również pamiętać, że symulatory nie mają dostępu do prawdziwego aparatu — testowanie jest możliwe tylko na fizycznym urządzeniu.
CameraX rozwiązuje problem fragmentacji Androida przez warstwę kompatybilności CameraXConfig — biblioteka automatycznie stosuje obejścia dla znanych błędów producentów. Na iOS AVFoundation działa jednolicie na wszystkich urządzeniach począwszy od iOS 6, ale niektóre funkcje (np. Portrait Mode lub LiDAR) są dostępne tylko na modelach iPhone 12 i nowszych. Przy tworzeniu aplikacji wieloplatformowej zaleca się używanie Flutter lub React Native z wtyczkami aparatu — abstrahują one różnice platformowe i zapewniają jednolite API dla obu systemów.
Często zadawane pytania
Dla większości aplikacji zaleca się CameraX ze względu na prostotę użycia, wbudowaną obsługę cyklu życia i kompatybilność z 95% urządzeń. Camera2 warto wybrać tylko w przypadku potrzeby RAW, zdjęć seryjnych lub ręcznego sterowania czujnikiem.
Na Androidzie dodaj uprawnienie CAMERA w manifeście i poproś o nie w trakcie działania przez ActivityCompat.requestPermissions. Na iOS dodaj NSCameraUsageDescription w Info.plist z jasnym opisem powodu użycia aparatu.
Na iOS używanie aparatu w tle jest ściśle ograniczone — wymagana jest specjalna zgoda Apple. Na Androidzie aparat może działać w tle przez foreground service, ale negatywnie wpływa to na poziom baterii i nagrzewanie urządzenia.
Symulatory iOS i emulatory Androida nie mają dostępu do sprzętowego aparatu — nie emulują fizycznego czujnika. Do testowania funkcjonalności aparatu zawsze używaj fizycznego urządzenia lub zewnętrznej kamery podłączonej do komputera.
ImageAnalysis — to analizator strumienia klatek z CameraX, który przekazuje każdą klatkę do ImageAnalysis.Analyzer w celu przetworzenia. Używany jest do rozpoznawania kodów QR, wykrywania twarzy, skanowania dokumentów i innych zadań wizji komputerowej.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również