De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.
Colaboração: Carlos Tosin
Data de Publicação: 02 de abril de 2012
Grande parte dos dispositivos Android possui uma ou mais câmeras, que permitem tirar fotos e gravar vídeos. O objetivo deste artigo é mostrar como aplicações Android podem tirar proveito da presença destas câmeras.
A integração de uma aplicação com a câmera de um dispositivo pode ser feita de duas formas. A primeira, mais simples, utiliza a aplicação de câmera nativa que já existe no Android. E a segunda permite que o desenvolvedor tenha controle total do hardware da câmera. As duas formas serão abordadas na sequência.
Este artigo tem foco na utilização da câmera apenas, portanto é esperado que o leitor tenha conhecimento prévio a respeito de conceitos fundamentais do Android, como intents, activities, views e permissões de acesso.
A forma mais simples de integrar uma aplicação com a câmera é chamar a aplicação nativa de câmera do dispositivo. A chamada de outras aplicações no Android é feita através do disparo de uma intent para a plataforma, que fica responsável por carregar a aplicação. O código que solicita a abertura da aplicação nativa da câmera pode ser visto a seguir:
File picsDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES); File imageFile = new File(picsDir, "foto.jpg"); Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imageFile)); startActivity(i);
A intent deve ser criada com a action MediaStore.ACTION_IMAGE_CAPTURE
,
que identifica a aplicação nativa de câmera. Dentro de intent,
é fornecido também o caminho para o arquivo onde a foto tirada será
armazenada. Neste caso, o armazenamento está sendo feito na memória externa
do dispositivo, dentro da pasta onde normalmente as fotos ficam guardadas
(mas poderia ser em outro local). Lembrando que, se você deseja gravar
dados na área de memória externa, é preciso que sua aplicação declare
a permissão android.permission.WRITE_EXTERNAL_STORAGE
no arquivo
AndroidManifest.xml
.
Depois de criada a intent, o método startActivity()
é chamado. É ele quem
envia a intent para a plataforma, a qual vai abrir a aplicação da câmera. A
foto tirada por esta aplicação será armazenada no caminho especificado pela
propriedade MediaStore.EXTRA_OUTPUT
adicionada à intent.
Como você pode perceber, este primeiro tipo de integração é bastante simples. É preciso apenas chamar a aplicação nativa de câmera e indicar onde a foto será armazenada. Se você precisa de um controle maior ou deseja realizar uma programação mais avançada nesta área, será necessário controlar diretamente a câmera via programação. Este é o assunto que será abordado a partir de agora.
Existem situações onde o programador não quer utilizar a aplicação nativa da câmera ou quer ter um controle maior sofre ela. Nesses casos o trabalho de programação é um pouco maior, pois é preciso seguir alguns passos.
Um dispositivo pode ter várias câmeras, uma câmera ou nenhuma. Para identificar o número exato é possível fazer a seguinte chamada (disponível a partir do Android 2.3):
int qtde = Camera.getNumberOfCameras();
O primeiro passo para trabalhar com uma câmera é obter uma instância de um
objeto Camera
(classe presente no pacote android.hardware.Camera
). Isto
pode ser feito desta forma:
Camera camera = Camera.open();
Esta chamada retorna a referência à câmera traseira do dispositivo (retorna
null caso ela não exista). Para referenciar outras câmeras, é preciso utilizar
o método open()
sobrecarregado, que recebe um int
como parâmetro. Este
parâmetro indica qual o ID da câmera, que pode variar de 0 até o número de
câmeras subtraído de 1.
Um detalhe importante com relação à câmera é que ela deve ser liberada após o uso. Isto é feito através da seguinte chamada:
camera.release();
Além disso, quando você acessa diretamente a câmera, o Android solicita que você declare uma permissão específica na sua aplicação, como pode ser visto abaixo:
<uses-permission android:name="android.permission.CAMERA" />
Para que você possa tirar uma foto é necessário que você esteja vendo um
preview da imagem, isto é, esteja vendo o que a câmera está enquadrando. Para
trabalhar com preview, a classe SurfaceView
é utilizada. Esta classe
representa uma view, o que permite a sua utilização em um arquivo XML de
definição de layout. Veja um exemplo:
public class CameraActivity extends Activity implements SurfaceHolder.Callback { private Camera camera; private SurfaceView surfaceView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); camera = Camera.open(); surfaceView = (SurfaceView) findViewById(R.id.preview); surfaceView.getHolder().addCallback(this); } @Override protected void onDestroy() { super.onDestroy(); if (camera != null) { camera.release(); } } @Override protected void onPause() { super.onPause(); if (camera != null) { camera.stopPreview(); } } @Override public void surfaceCreated(SurfaceHolder holder) { try { camera.setPreviewDisplay(holder); camera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (holder.getSurface() != null) { try { camera.stopPreview(); } catch (Exception e) { } try { camera.setPreviewDisplay(holder); camera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } } @Override public void surfaceDestroyed(SurfaceHolder holder) { } }
Para trabalhar com um SurfaceView
, é preciso registrar um callback. Isto
é feito através do método surfaceView.getHolder().addCallback()
. Este
callback é um objeto de uma classe que implementa SurfaceHolder.Callback
(neste caso, a própria activity).
A interface SurfaceHolder.Callback
declara três métodos:
surfaceCreated()
: Chamado quando a superfície, que é gerenciada
pelo SurfaceView
, é criada. O preview da imagem da câmera só pode ser
iniciado quando a superfície é criada.
surfaceChanged()
: Chamado quando a superfície é tem suas
características alteradas. Se um preview está em andamento quando este método
é chamado, ele deve ser reinicializado.
surfaceDestroyed()
: Chamado quando a superfície é destruída.
O preview é iniciado ou parado, respectivamente, através dos
métodos camera.startPreview()
e camera.stopPreview()
. O método
camera.setPreviewDisplay()
atrela a SurfaceView
(onde o preview será
mostrado) à câmera (que gera as imagens que serão exibidas).
Depois que a câmera foi inicializada e o preview está sendo exibido, é possível tirar fotos. Isto é feito através da seguinte chamada:
camera.takePicture(shutter, raw, jpeg);
O método takePicture()
é assíncrono. Conforme a imagem vai sendo
processada, o Android invoca os callbacks passados como parâmetro. Os
callbacks que não interessam para a aplicação não precisam ser fornecidos
(neste caso null
deve ser passado como parâmetro). O parâmetros deste
método são os seguintes:
shutter
: Objeto cuja classe implementa a interface
ShutterCallback
. Invocado assim que o obturador da câmera entra em ação
e captura a imagem.
raw
: Objeto cuja classe implementa a interface
PictureCallback
. Invocado quando a imagem "crua" tirada pela câmera
está disponível.
jpeg
: Objeto cuja classe implementa a interface
PictureCallback
. Invocado assim que a imagem comprimida, no formato JPEG,
está disponível.
Veja um exemplo de implementação de um callback que grava a imagem no formato JPEG em algum local do dispositivo, assim que a imagem esteja disponível:
PictureCallback jpeg = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { FileOutputStream fos = null; try { try { fos = new FileOutputStream(imageFile); fos.write(data); } finally { if (fos != null) { fos.close(); } } } catch (IOException e) { e.printStackTrace(); } camera.startPreview(); }
O método onPictureTaken()
recebe como parâmetro um array de bytes,
que representa o conteúdo da imagem. Este array deve ser usado para gerar
o arquivo de imagem, por exemplo.
Outro detalhe importante é a chamada do método camera.startPreview()
depois que a foto é gerada. Isto é necessário caso você deseje continuar
exibindo o preview para tirar outras fotos.
Para tirar a foto utilizando o callback criado, a chamada pode ser feita assim:
camera.takePicture(null, null, jpeg);
Seguindo estes passos você conseguirá ter controle total sobre a câmera e poderá utilizá-la de acordo com a sua necessidade.
Este artigo apresentou as duas formas de integrar aplicações Android com as câmeras presentes no dispositivo. A primeira através do uso da própria aplicação de câmera nativa do Android, e a segunda através do controle direto da câmera pela aplicação.
Carlos Tosin é instrutor oficial dos cursos de Java e Android da SoftBlue. É formado em Ciência da Computação pela PUC-PR, pós-graduado em Desenvolvimento de Jogos para Computador pela Universidade Positivo e Mestre em Informática na área de Sistemas Distribuídos, também pela PUC-PR. Trabalha profissionalmente com Java há 10 anos e possui 6 anos de experiência no desenvolvimento de sistemas para a IBM dos Estados Unidos, utilizados a nível mundial. Atua há mais de 3 anos com cursos e treinamentos de profissionais em grandes empresas. Possui as certificações da Oracle SCJP, SCJD, SCWCD, SCBCD, SCEA; além das certificações IBM SOA, IBM OOAD (Object-Oriented Analysis and Design e ITIL Foundation.
This policy contains information about your privacy. By posting, you are declaring that you understand this policy:
This policy is subject to change at any time and without notice.
These terms and conditions contain rules about posting comments. By submitting a comment, you are declaring that you agree with these rules:
Failure to comply with these rules may result in being banned from submitting further comments.
These terms and conditions are subject to change at any time and without notice.
Comentários