0Pricing
Android Academy · Aula

Tirando fotos

Capture e salve uma imagem.

Tirando fotos é uma aula grátis de Android Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Android Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Android Academy inclui 4 aulas no total.

Capturando uma foto

Com uma visualização na tela, o próximo passo é tirar uma foto. A CameRX cuida disso com o caso de uso ImageCapture.

Você associará ImageCapture junto com a visualização, chamará takePicture() quando o usuário tocar no botão do obturador e salvará o resultado na galeria do dispositivo.

Criando o caso de uso ImageCapture

ImageCapture é configurado com um builder. Uma opção útil é o modo de captura, que estabelece um equilíbrio entre latência e qualidade:

  • CAPTURE_MODE_MINIMIZE_LATENCY — obturador rápido.
  • CAPTURE_MODE_MAXIMIZE_QUALITY — melhor imagem, um pouco mais lento.
val imageCapture = ImageCapture.Builder()
    .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
    .build()

Associando Preview e ImageCapture

Você pode associar vários casos de uso ao mesmo tempo. Passe preview e imageCapture para bindToLifecycle para que a câmera forneça a transmissão ao vivo e esteja pronta para tirar uma foto.

cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
    lifecycleOwner,
    CameraSelector.DEFAULT_BACK_CAMERA,
    preview,
    imageCapture
)

Onde salvar: MediaStore

A maneira moderna e compatível com o armazenamento com escopo para salvar uma foto é usar o MediaStore. Você descreve o arquivo (nome, tipo MIME e pasta) com ContentValues e deixa o sistema colocá-lo na coleção compartilhada Pictures.

Isso funciona sem a permissão antiga WRITE_EXTERNAL_STORAGE no Android 10 ou superior.

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")
}

Opções de saída

Para informar à CameraX onde gravar o JPEG, crie um OutputFileOptions a partir do resolvedor de conteúdo, do URI da coleção de destino e dos seus ContentValues.

val outputOptions = ImageCapture.OutputFileOptions
    .Builder(
        context.contentResolver,
        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
        contentValues
    )
    .build()

Chamando takePicture()

Agora inicie a captura. takePicture() recebe as opções de saída, um Executor e um callback. A CameRX informa o sucesso ou o erro de forma assíncrona.

Use ContextCompat.getMainExecutor(context) para que o callback seja executado na thread principal.

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.
        }
    }
)

Como lidar com o resultado

Em caso de sucesso, OutputFileResults.savedUri fornece o URI da imagem salva. Você pode exibi-la (com Coil), compartilhá-la ou mostrar uma Snackbar confirmando o salvamento.

Em caso de erro, ImageCaptureException informa o que deu errado — registre o erro e informe o usuário.

override fun onImageSaved(output: ImageCapture.OutputFileResults) {
    val uri = output.savedUri ?: return
    Toast.makeText(context, "Saved: $uri", Toast.LENGTH_SHORT).show()
}

Conectando um botão do obturador

No Compose, sobreponha um botão do obturador à visualização usando uma Box. Eleve a referência de ImageCapture para que o onClick do botão possa chamar 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")
    }
}

Extraindo takePhoto()

Mantenha seu componente composable organizado, transferindo a lógica de captura para uma função auxiliar. Ela recebe o contexto e o caso de uso ImageCapture, cria as opções de saída e chama 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) {}
        }
    )
}

Flash e rotação

Dois toques finais:

  • Flash: defina imageCapture.flashMode como FLASH_MODE_ON, OFF ou AUTO.
  • Rotação: CameRX usa a rotação de destino para orientar corretamente o JPEG salvo; mantenha esse valor atualizado para garantir a orientação correta.
imageCapture.flashMode = ImageCapture.FLASH_MODE_AUTO
// Update target rotation when the device rotates:
imageCapture.targetRotation = display.rotation

Juntando tudo

O fluxo completo de captura de fotos é: criar ImageCapture → vinculá-lo à visualização → ao tocar no obturador, criar OutputFileOptions e chamar takePicture → lidar com onImageSaved / onError.

Assim, você tem uma câmera completa que salva na galeria usando apenas algumas linhas.

Verificação rápida

Confirme que você entende o fluxo de captura de fotos.

Recapitulação

Agora você pode tirar e salvar fotos com CameRX:

  • Crie um caso de uso ImageCapture e vincule-o à visualização.
  • Descreva a saída com ContentValues e MediaStore para usar o armazenamento com escopo.
  • Chame takePicture() com OutputFileOptions, um executor e um OnImageSavedCallback.
  • Leia savedUri em caso de sucesso; lide com ImageCaptureException em caso de erro.

Em seguida, você gravará vídeos com o caso de uso VideoCapture.

Perguntas Frequentes

A aula “Tirando fotos” é grátis?

Sim — o texto completo de “Tirando fotos” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Android Academy, atualize para CoddyKit PRO. O curso de Android Academy inclui 4 aulas no total.

O que vou aprender em “Tirando fotos”?

Capture e salve uma imagem. Você pratica Android Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Android Academy?

Nenhuma experiência prévia é necessária. Android Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Tirando fotos”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Android Academy?

Sim. Cada aula de Android Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Visão geral do CameraX
  2. Exibindo uma prévia da câmera
  3. Tirando fotos
  4. Gravando vídeo
← Voltar para Android Academy