写真を撮影する
画像を撮影して保存します。
「写真を撮影する」はCoddyKit上の無料Android Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAndroid Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Android Academyコースには全4レッスンが含まれています。
写真の撮影
画面にプレビューを表示できたら、次は写真を撮影します。CameRXでは、ImageCaptureユースケースを使ってこれを処理します。
ImageCaptureをプレビューと一緒にバインドし、ユーザーがシャッターボタンをタップしたときにtakePicture()を呼び出して、結果をデバイスのギャラリーに保存します。
ImageCaptureユースケースの構築
ImageCaptureはビルダーで設定します。便利なオプションに撮影モードがあります。これは、遅延と画質のバランスを調整するものです。
CAPTURE_MODE_MINIMIZE_LATENCY— シャッターを高速化します。CAPTURE_MODE_MAXIMIZE_QUALITY— 少し遅くなりますが、最高画質で撮影します。
val imageCapture = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build()PreviewとImageCaptureのバインド
複数のユースケースを一度にバインドできます。previewとimageCaptureの両方をbindToLifecycleに渡すと、カメラでライブ映像を表示しながら、写真を撮影できる状態にできます。
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
lifecycleOwner,
CameraSelector.DEFAULT_BACK_CAMERA,
preview,
imageCapture
)保存先:MediaStore
写真を保存する現代的でScoped Storageに対応した方法は、MediaStoreを使うことです。ContentValuesでファイル(名前、MIMEタイプ、フォルダー)を指定すると、システムが共有Picturesコレクションに配置します。
Android 10以降では、従来の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")
}出力オプション
JPEGの書き込み先をCameraXに伝えるには、コンテンツリゾルバー、対象のコレクションURI、ContentValuesからOutputFileOptionsを構築します。
val outputOptions = ImageCapture.OutputFileOptions
.Builder(
context.contentResolver,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
)
.build()takePicture()の呼び出し
ここで撮影を開始します。takePicture()には、出力オプション、Executor、コールバックを渡します。CameRXは成功またはエラーを非同期で通知します。
ContextCompat.getMainExecutor(context)を使うと、コールバックがメインスレッドで実行されます。
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.
}
}
)結果の処理
成功すると、OutputFileResults.savedUriから保存した画像のURIを取得できます。これを(Coilで)表示したり、共有したり、保存が完了したことを知らせるSnackbarを表示したりできます。
エラーが発生した場合は、ImageCaptureExceptionから問題の内容を確認できます。ログに記録し、ユーザーに知らせてください。
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val uri = output.savedUri ?: return
Toast.makeText(context, "Saved: $uri", Toast.LENGTH_SHORT).show()
}シャッターボタンの接続
Composeでは、Boxを使ってプレビューの上にシャッターボタンを重ねます。ImageCaptureの参照をホイスティングして、ボタンのonClickから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")
}
}takePhoto()の切り出し
キャプチャ処理をヘルパーに移動して、コンポーザブルをすっきり保ちます。ヘルパーはコンテキストとImageCaptureユースケースを受け取り、出力オプションを作成して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) {}
}
)
}フラッシュと回転
仕上げとして、次の2点を設定します。
- フラッシュ:
imageCapture.flashModeにFLASH_MODE_ON、OFF、またはAUTOを設定します。 - 回転:CameRXはターゲットの回転を使って、保存するJPEGを正しい向きにします。正確な向きを保つため、常に最新の値に更新してください。
imageCapture.flashMode = ImageCapture.FLASH_MODE_AUTO
// Update target rotation when the device rotates:
imageCapture.targetRotation = display.rotationすべてを組み合わせる
写真撮影の一連の流れは次のとおりです。ImageCaptureを作成する → プレビューとバインドする → シャッターをタップしたらOutputFileOptionsを作成してtakePictureを呼び出す → onImageSaved / onErrorを処理する。
これだけの数行で、ギャラリーに保存できるカメラが完成します。
確認テスト
写真撮影の流れを理解できているか確認しましょう。
まとめ
CameRXで写真を撮影して保存できるようになりました。
ImageCaptureユースケースを作成し、プレビューとバインドします。ContentValuesとMediaStoreを使い、スコープ付きストレージ向けの出力を指定します。OutputFileOptions、エグゼキュータ、OnImageSavedCallbackを指定してtakePicture()を呼び出します。- 成功時は
savedUriを読み取り、エラー時はImageCaptureExceptionを処理します。
次は、VideoCaptureユースケースを使って動画を録画します。
よくある質問
「写真を撮影する」レッスンは無料ですか?
はい。「写真を撮影する」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Android Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Android Academyコースには全4レッスンが含まれています。
「写真を撮影する」で何を学びますか?
画像を撮影して保存します。 ブラウザで直接実行するハンズオンコードでAndroid Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Android Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAndroid Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「写真を撮影する」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAndroid Academyレッスンでコードを書いて実行できますか?
はい。すべてのAndroid Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。