Robienie zdjęć
Przechwytuj i zapisuj obrazy
Robienie zdjęć to bezpłatna lekcja Android Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Android Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Android Academy zawiera 4 lekcji w sumie.
Robienie zdjęcia
Po wyświetleniu podglądu kolejnym krokiem jest zrobienie zdjęcia. CameRX obsługuje to za pomocą przypadku użycia ImageCapture.
Powiążesz ImageCapture razem z podglądem, a następnie wywołasz takePicture() po dotknięciu przez użytkownika przycisku migawki i zapiszesz wynik w galerii urządzenia.
Budowanie przypadku użycia ImageCapture
ImageCapture konfiguruje się za pomocą buildera. Przydatną opcją jest tryb przechwytywania, który stanowi kompromis między opóźnieniem a jakością:
CAPTURE_MODE_MINIMIZE_LATENCY— szybka migawka.CAPTURE_MODE_MAXIMIZE_QUALITY— najlepsza jakość obrazu, ale nieco wolniejsze działanie.
val imageCapture = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build()Powiązywanie Preview + ImageCapture
Możesz powiązać wiele przypadków użycia jednocześnie. Przekaż zarówno preview, jak i imageCapture do bindToLifecycle, aby aparat obsługiwał podgląd na żywo i był gotowy do zrobienia zdjęcia.
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
lifecycleOwner,
CameraSelector.DEFAULT_BACK_CAMERA,
preview,
imageCapture
)Gdzie zapisywać: MediaStore
Nowoczesnym sposobem zapisu zdjęcia, zgodnym z mechanizmem ograniczonego dostępu do pamięci, jest użycie MediaStore. Opisujesz plik (nazwę, typ MIME i folder) za pomocą ContentValues, a następnie pozwalasz systemowi umieścić go we wspólnej kolekcji Pictures.
Na Androidzie 10 i nowszych działa to bez starszego uprawnienia WRITE_EXTERNAL_STORAGE.
val name = "photo_${System.currentTimeMillis()}"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, name)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/MyApp")
}Opcje wyjściowe
Aby wskazać CameraX miejsce zapisu pliku JPEG, utwórz OutputFileOptions na podstawie resolvera treści, identyfikatora URI docelowej kolekcji oraz obiektu ContentValues.
val outputOptions = ImageCapture.OutputFileOptions
.Builder(
context.contentResolver,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
)
.build()Wywoływanie takePicture()
Teraz uruchom przechwytywanie. takePicture() przyjmuje opcje wyjściowe, obiekt Executor oraz callback. CameRX asynchronicznie zgłasza powodzenie lub błąd.
Użyj ContextCompat.getMainExecutor(context), aby callback był wykonywany w wątku głównym.
imageCapture.takePicture(
outputOptions,
ContextCompat.getMainExecutor(context),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val savedUri = output.savedUri
// Photo saved! Show a confirmation.
}
override fun onError(exc: ImageCaptureException) {
// Handle the failure.
}
}
)Obsługa wyniku
W przypadku powodzenia OutputFileResults.savedUri zawiera URI zapisanego obrazu. Można go wyświetlić (za pomocą Coil), udostępnić lub pokazać Snackbar z potwierdzeniem zapisu.
W przypadku błędu ImageCaptureException informuje, co poszło nie tak — należy zapisać błąd w logach i poinformować użytkownika.
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val uri = output.savedUri ?: return
Toast.makeText(context, "Saved: $uri", Toast.LENGTH_SHORT).show()
}Podłączanie przycisku migawki
W Compose należy umieścić przycisk migawki nad podglądem, używając Box. Należy wynieść referencję do ImageCapture, aby funkcja onClick przycisku mogła wywołać takePhoto.
Box(modifier = Modifier.fillMaxSize()) {
CameraPreview(imageCapture = imageCapture)
IconButton(
onClick = { takePhoto(context, imageCapture) },
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(32.dp)
) {
Icon(Icons.Default.PhotoCamera, contentDescription = "Take photo")
}
}Wydzielanie takePhoto()
Aby zachować przejrzystość composable, należy przenieść logikę przechwytywania do funkcji pomocniczej. Przyjmuje ona kontekst i przypadek użycia ImageCapture, tworzy opcje wyjściowe i wywołuje takePicture.
fun takePhoto(context: Context, imageCapture: ImageCapture) {
val values = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "IMG_${System.currentTimeMillis()}")
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
}
val options = ImageCapture.OutputFileOptions.Builder(
context.contentResolver,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values
).build()
imageCapture.takePicture(
options,
ContextCompat.getMainExecutor(context),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(o: ImageCapture.OutputFileResults) {}
override fun onError(e: ImageCaptureException) {}
}
)
}Lampa błyskowa i obrót
Dwa ostatnie elementy:
- Lampa błyskowa: ustaw
imageCapture.flashModenaFLASH_MODE_ON,OFFlubAUTO. - Obrót: CameRX używa docelowego obrotu, aby poprawnie ustawić zapisany plik JPEG; należy go aktualizować, aby orientacja była prawidłowa.
imageCapture.flashMode = ImageCapture.FLASH_MODE_AUTO
// Update target rotation when the device rotates:
imageCapture.targetRotation = display.rotationPołączenie wszystkich elementów
Pełny przebieg robienia zdjęcia wygląda następująco: utworzenie ImageCapture → powiązanie go z podglądem → dotknięcie migawki, utworzenie OutputFileOptions i wywołanie takePicture → obsługa onImageSaved / onError.
To kompletna obsługa aparatu zapisującego zdjęcia w galerii, wymagająca zaledwie kilku wierszy kodu.
Szybkie sprawdzenie
Upewnij się, że rozumiesz przebieg przechwytywania zdjęcia.
Podsumowanie
Potrafisz już robić i zapisywać zdjęcia za pomocą CameRX:
- Utwórz przypadek użycia
ImageCapturei powiąż go z podglądem. - Opisz dane wyjściowe za pomocą
ContentValuesiMediaStoredla magazynu zakresowego. - Wywołaj
takePicture(), przekazującOutputFileOptions, executor iOnImageSavedCallback. - Po pomyślnym zapisie odczytaj
savedUri, a w przypadku błędu obsłużImageCaptureException.
W następnym kroku nagrasz film za pomocą przypadku użycia VideoCapture.
Często zadawane pytania
Czy lekcja „Robienie zdjęć” jest bezpłatna?
Tak — pełny tekst „Robienie zdjęć” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Android Academy, przejdź na CoddyKit PRO. Kurs Android Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Robienie zdjęć”?
Przechwytuj i zapisuj obrazy Ćwiczysz Android Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Android Academy?
Nie wymagamy żadnego doświadczenia. Android Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Robienie zdjęć”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Android Academy?
Tak. Każda lekcja Android Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.