Alura > Cursos de Mobile > Cursos de Flutter > Conteúdos de Flutter > Primeiras aulas do curso Flutter: integrações com a câmera

Flutter: integrações com a câmera

Abrindo a câmera - Apresentação

Olá! Sou o Ricarth Lima e serei seu instrutor em mais um curso no fascinante mundo do Flutter.

Audiodescrição: Ricarth é um homem com cabelo Black Power e barba castanho-escuro. Usa óculos de grau com armação transparente e uma camiseta preta. Ao fundo, uma parede lisa com iluminação degradê do rosa ao roxo. Ao lado esquerdo, duas prateleiras suspensas com livros e itens de decoração. Ao lado direito uma prateleira com livros e uma cafeteira.

Boas-vindas ao curso de Flutter Integrações com a Câmera!

O que aprenderemos

Vamos explorar o projeto que desenvolveremos. Estamos não com o emulador, mas sim a reprodução de um dispositivo físico que está em nossas mãos. Afinal, utilizaremos uma câmera real.

Ao clicar no botão "Entrar" para fazer um registro no Banco D'Ouro, desenvolvido na formação Dart, a pessoas usuárias vai inserir seus dados, como nome, data de nascimento e endereço. No entanto, o que importa para nós neste curso é desenvolver o comportamento necessário para a pessoa conseguir fotografar o documento e o rosto, elementos essenciais para o banco confirmar que a pessoa que está abrindo a conta é, de fato, quem afirma ser no cadastro.

Ao clicar em fotografar o rosto, a câmera será ativada. Vamos aprender a controlá-la, inicializá-la, e a colocar todo o guia ao redor ou sobre a câmera. Além disso, capturaremos uma imagem que, mesmo que inicialmente não fique perfeita, poderá ser confirmada e utilizada como informação no cadastro.

Não é necessário muito esforço para perceber a importância de aprender a usar a câmera no Flutter. Muitos aplicativos que utilizamos diariamente, seja em redes sociais ou para segurança, como no caso de um banco, fazem uso da câmera. Portanto, é fundamental incluir esse conhecimento em nosso repertório no Flutter.

Pré-requisitos

Outro ponto importante são os pré-requisitos. É necessário ter concluído a formação de Dart e a formação de Flutter. Com esses conhecimentos, será possível acompanhar adequadamente nosso curso de integrações com a câmera.

Estamos bastante animados para começar, então vamos colocar a mão na massa!

Abrindo a câmera - Lendo câmera do dispositivo

Agora que conhecemos nosso projeto e entendemos nossos objetivos, vamos pôr a mão na massa. A primeira pergunta que precisamos responder é: quais são as câmeras às quais nosso dispositivo tem acesso? Precisamos de uma lista das câmeras com as quais poderemos trabalhar, sejam elas frontais ou traseiras.

Falando sobre o dispositivo, é importante esclarecer que, neste curso, e em todos os outros que lidam com hardware físico, como é o caso da câmera, recomendamos fortemente o uso de um dispositivo físico. O que está sendo espelhado na tela é apenas um espelhamento do dispositivo físico, não um emulador.

Isso é excelente por duas razões. Primeiro, porque nos aproxima da experiência que a pessoa usuária final terá. Segundo, evita diversos problemas e bugs, já que um dispositivo emulado também emula características físicas, como a câmera, que não será real. Portanto, recomendamos o uso de um dispositivo físico. Haverá um "Para Saber Mais" que relembrará como conectar um dispositivo físico ao VS Code.

Instalando o plugin Camera

Sabendo disso, vamos instalar o plugin Camera, que será responsável por todas as ações relacionadas à câmera neste curso. Para isso, vamos ao VS Code, parar a execução do código, abrir o console de depuração com "Ctrl + J", e rodar o comando flutter pub add camera.

flutter pub add camera

Esse comando instalará o pacote do pub.dev, que possui integração com a parte nativa do Android, por isso é chamado de plugin. Após isso, fechamos o terminal com "Ctrl + J".

Configurando o Build.Gradle

Um detalhe importante é que precisamos fazer uma configuração fora da parte de Flutter, entrando na parte nativa do projeto Flutter. No explorador, vamos à pasta "Android", procuramos por "app" e clicamos no arquivo build.gradle. Dentro desse arquivo, procuramos pela linha onde está escrito minSdk, apagamos o flutter.minSdkVersion e passamos 21, conforme recomendado pelo plugin.

minSdkVersion = 21

Salvamos o build.gradle, fechamos tudo, exceto o arquivo main, e rodamos o projeto para verificar se tudo está funcionando corretamente. Se a aplicação rodar sem problemas, significa que a instalação do plugin e a configuração no build.gradle foram bem-sucedidas. Deu certo.

Clicamos no botão "Sem conta? Registrar-se agora!" e somos encaminhados para a página de formulário. Trabalharemos agora nessa tela de cadastro, mais especificamento nos campos em que solicitam uma foto do documento e rosto.

No VS Code, pressionamos "Ctrl + B" e acessamos "ui > registration" e abrimos o arquivo registration_screen.dart. No fim do código, há um método pré-pronto chamado _handleCameraClicked(), que lida com o clique no botão de abrir a câmera.

Obtendo a lista de câmeras disponíveis

Nesse caso, vamos usar o método availableCameras() do plugin Camera. Se o analisador do Dart demorar para fazer a importação automática, podemos fazê-la manualmente. No início do arquivo, escrevemos:

import 'package:camera/camera.dart';

Com o método availableCameras(), que é assíncrono e retorna uma lista de CameraDescription, podemos prosseguir. Na linha 173, criamos uma lista de CameraDescription chamada cameras e a inicializamos com await availableCameras().

Com essa lista, vamos primeiro imprimir a List Cameras. Sabemos que isso é uma lista e que o CameraDescription se assemelha a um map. Para facilitar a visualização, vamos utilizar o método toString na List Cameras e aplicar um replaceAll("),","), \n") , permitindo que a saída seja exibida em múltiplas linhas.

void _handleCameraClicked(
    BuildContext context,
    RegistrationViewModel viewModel, {
    bool isDocument = true,
  }) async {
    List<CameraDescription> listCameras = await availableCameras();
    print(listCameras);
    print(listCameras.toString().replaceAll(",", ",\n"));

    if (isDocument) {
      // TODO: Abrir câmera para fotografar documento
    } else {
      // TODO: Abrir câmera para fotografar selfie
    }
}

Vamos salvar, reiniciar a aplicação, abrir o console de depuração e o visualizador. No entanto, não utilizaremos tanto o visualizador, pois ele gera warnings que não são bem-vindos no momento. Vamos usar o dispositivo físico. Após clicar em "Sem Conta? Registre-se agora!", arrastamos para cima e clicamos em "Fotografar rosto", nisso algumas ações ocorrem.

Inicialmente, o primeiro print é difícil de visualizar, mas os subsequentes, com a quebra de linha, são mais claros. Identificamos quatro câmeras: duas frontais e duas traseiras, com as direções de lente "Back" e "Front". Os valores 90 e 270 indicam a rotação, o que será útil no futuro. O CameraDescription contém o ID da câmera, a seleção entre traseira ou frontal e o número, resolvendo nosso problema de identificar as câmeras disponíveis no dispositivo.

Entendendo o Build.Gradle

OBuild Gradle faz parte dos arquivos nativos que normalmente não exploramos no Flutter. Primeiro, precisamos entender o que é código nativo. O Flutter é multiplataforma e híbrido, criando aplicativos para iOS e Android, além de suportar Linux, Chrome OS, Windows, Mac OS, entre outros. Isso requer códigos nativos em seu interior.

Explorando os arquivos nativos do Flutter

No VS Code, ao explorar o projeto Flutter, percebemos que não existe apenas a pasta "lib". Há várias outras pastas, como "Android", "iOS", "Linux", "Mac OS" e "Web", relacionadas ao caráter multiplataforma e híbrido do Flutter. Por exemplo, na pasta "Web", encontramos partes de um site, como HTML, JavaScript e CSS. Na pasta "Windows", há códigos como make. Na pasta "Android", encontramos códigos Java, Kotlin e XML, essenciais para cada tecnologia, utilizados pelo Flutter durante o build.

O Build Gradle é parte do código nativo do Android, responsável pela configuração do Gradle, uma ferramenta de automação usada para compilar, testar e empacotar aplicativos. Quem já programou para Android nativo conhece o Gradle. No Flutter, precisamos conhecê-lo para situações que exigem código nativo.

O Build Gradle é responsável por plugins e configurações iniciais do Android, como o minSDK e as dependências do projeto, semelhante ao pubspec.yml. No VS Code, ao acessar "app > build.gradle", observamos que o código começa com os plugins usados no build do aplicativo. Entre as linhas 8 e 40, há configurações do Android, incluindo versões de SDK, versão de compilação, versão mínima e namespace, úteis para publicação na Play Store. Também definimos dependências, como pacotes do Firebase, que precisam estar presentes no código nativo além do ProSpec.yml.

O MinSDK define a versão mínima do Android que o aplicativo suportará. Com a evolução do Android, novas versões e SDKs são lançados. Definimos a versão mínima, neste caso, a 21, por recomendações do plugin. Ao instalar um plugin, é importante verificar no readme do pub.dev se há instruções específicas, como a necessidade de uma versão mínima do Android. A versão 21 foi recomendada devido a funcionalidades necessárias para o funcionamento do plugin.

Caso tenha ficado com alguma dúvida, consulte nosso fórum e o canal do Discord para discutir o assunto. Vamos continuar!

Abrindo a câmera - Inicializando câmera

Agora que conseguimos listar nossas câmeras, chegou a hora de usar alguma delas para inicializar, abrir, configurar e até mesmo tirar fotos. Para realizar essas ações, não utilizamos o CameraDescription, mas sim um objeto do plugin Camera chamado CameraController. Ele será o centro de tudo que faremos com nossa câmera.

No arquivo registration_screen.dart, faremos algumas mudanças iniciais. Começamos apagando o print(listCameras), ele não é útil devido à sua má formatação. O print() que sobrou pode ser útil no futuro, caso precisemos verificar alguma parte da câmera ou algum detalhe, então vamos mantê-lo por enquanto.

As linhas de To Do estão verificando basicamente se o clique veio do documento ou da selfie no nosso aplicativo. Não vamos utilizá-las por enquanto, então vamos comentá-los.

Criando o controlador da câmera

Próximo à linha 176, podemos criar um CameraController. Vamos chamá-lo de cameraController e ele receberá um CameraController(). Vamos colocar uma vírgula no final da linha 177, antes do parêntese, para identificar melhor e discutir cada um dos atributos que passamos para o CameraController.

O primeiro é um CameraDescription, então precisamos decidir qual câmera queremos utilizar. Para isso, vamos verificar no console de depuração com um "Ctrl + J". As câmeras ainda aparecem listadas: a primeira é uma câmera traseira e a segunda é uma câmera frontal. Vamos começar pela frontal, pois será mais fácil visualizar os detalhes. Com um "Ctrl + J", verificamos que o print foi útil. Na Description, vamos passar listCameras[1] na posição 1, já que é a nossa segunda câmera.

Definindo a resolução

Na linha 178, vamos definir no ResolutionPreset qual é a resolução que queremos para abrir essa câmera. Isso é um Enum, ResolutionPreset, e ao verificar os valores desse Enum, percebemos que são resoluções semelhantes às que vemos no YouTube, relacionadas à qualidade. Normalmente, chamamos de qualidade porque uma resolução menor, ou seja, uma quantidade de pixels menor, resulta em uma qualidade inferior. A resolução está relacionada à quantidade de pixels. Assim, a High é 720, a Low é por volta de 240, a Max é o máximo que a câmera pode entregar, a Medium é 480, a Ultra High é 2160, e a Very High é 1080p.

A opção 1080p é uma resolução interessante, mas para evitar problemas de compatibilidade, e considerando que nosso aplicativo não precisa de gravações elaboradas, já que não é um aplicativo de vídeo, optamos por selecionar a qualidade High. Um atributo que podemos configurar, embora não seja obrigatório, é o enableAudio. Vamos defini-lo como false, pois, por padrão, ele vem como true.

Esse atributo permite que a câmera utilize o microfone do dispositivo, além da própria câmera. Isso é útil se estivermos gravando vídeos, pois é interessante ter o áudio junto com o vídeo. No entanto, como nosso objetivo é apenas tirar fotos, não faz sentido manter essa opção ativada, pois isso geraria uma solicitação de permissão desnecessária para o uso do microfone. Portanto, vamos definir como false. Se estivermos gravando vídeos, podemos deixá-lo como true.

Inicializando a câmera

Mas, essa configuração não inicializa a câmera. O que fizemos, da linha 176 até a 180, foi declarar o Camera Controller e inicializar o objeto Camera Controller. Para inicializar a câmera e informar ao Android que ela deve estar funcionando, precisamos executar o comando na linha 182: aameraController.initialize(). Como essa função é assíncrona, utilizamos await antes dela. Ao passar o mouse sobre a função, verificamos que é um Future, confirmando que é assíncrona.

    bool isDocument = true,
  }) async {
    List<CameraDescription> listCameras = await availableCameras();

    print(listCameras.toString().replaceAll("),", "),\n"));

    CameraController cameraController = CameraController(
      listCameras[1],
      ResolutionPreset.high,
      enableAudio: false,
    );

    await cameraController.initialize();

    // if (isDocument) {
    //   // TODO: Abrir câmera para fotografar documento
    // } else {
    //   // TODO: Abrir câmera para fotografar selfie
    // }
  }
}

Testando o funcionamento da câmera

Salvamos as alterações e pressionamos F5 para rodar o aplicativo. Como estamos rodando após ter parado para fazer configurações de build, o processo de abertura pode demorar um pouco. Após a abertura, com o aplicativo em execução, clicamos em "Sem Conta? Registre-se Agora!" e, em seguida, na opção para abrir a câmera, seja para fotografar documento ou rosto. Ao clicar, o aplicativo solicita permissão, informando que o "Flutter Banco D'Ouro deseja gravar vídeos e tirar fotos". Nesse caso, selecionamos a opção "Durando o uso do app".

Após a permissão, uma câmera aparece no canto superior direito, indicando que o Android está usando a câmera, mas nada mais acontece. Isso é esperado, pois o controlador apenas inicializou a câmera. Para visualizar a câmera e obter a resposta em tempo real, precisamos usar um widget na tela, o que faremos na sequência. Até lá!

Sobre o curso Flutter: integrações com a câmera

O curso Flutter: integrações com a câmera possui 157 minutos de vídeos, em um total de 50 atividades. Gostou? Conheça nossos outros cursos de Flutter em Mobile, ou leia nossos artigos de Mobile.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Flutter acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas