O documento apresenta um breve resumo sobre o sistema operacional Android: (1) É um sistema operacional baseado no núcleo Linux desenvolvido pela Google para dispositivos móveis com tela sensível ao toque; (2) É o sistema operacional móvel mais utilizado no mundo com mais de 1 bilhão de usuários ativos em 2014; (3) Além de smartphones e tablets, também é utilizado em outros dispositivos como TVs, carros e relógios.
Aprenda a usar os recursos “câmera” do android, criando um app de forma prática
1.
2. Um breve resumo sobre o Android
Android é um sistema operacional (SO) baseado no núcleo linux e atualmente desenvolvido
pela empresa de tecnologia Google. Com uma interface de usuário baseada na manipulação
direta, o Android é projetado principalmente para dispositivos móveis com tela sensível ao
toque como smartphones e tablets; com interface específica para TV (Android TV), carro
(Android Auto) e relógio de pulso (Android Wear). O sistema operacional utiliza-se da tela
sensível ao toque para que o usuário possa manipular objetos virtuais e também de um
teclado virtual. Apesar de ser principalmente utilizado em dispositivos com tela sensível ao
toque, também é utilizado em consoles de videogames, câmeras digitais, computadores e
outros dispositivos eletrônicos.
O Android é o sistema operacional móvel mais utilizado do mundo, e, em 2013, possuía a
maior porcentagem das vendas mundiais de SO móveis. Dispositivos com o sistema Android
vendem mais que eletrônicos com Windows, iOS e Mac OS X combinados, com vendas em
2012, 2013 e 2014 perto da base de computadores do mundo. Em julho de 2013, a loja de
aplicativos Google Play possuía mais de 1 milhão de aplicativos disponíveis, baixados mais de
50 bilhões de vezes.[15] Uma pesquisa com programadores entre abril e maio de 2013 revelou
que 71% dos programadores para sistemas móveis desenvolviam para o Android.Na
conferência anual Google I/O de 2014, a companhia revelou que existem mais de 1 bilhão de
usuários Android ativos. Em junho de 2013, este número era de 538 milhões.
Fonte: Wikipédia
I9mobi
A partir da necessidade de suprir a demanda por aplicativos mobile, os sócios, Arthur Litaiff;
que já possui muito conhecimento na área de gestão de projetos e análise de negócios,
juntamente com Josué Barbosa o qual, trabalha desde 2010 com desenvolvimento de
softwares e aplicativos inteligentes. Vendo as necessidades do mercado, resolveram criar a
i9mobi, que é uma empresa com foco em inovação e especializada em desenvolvimento
criativo de aplicativos mobile. Para saber mais sobre os nossos serviços acesse
http://i9mobi.com.
3. 3
Aprenda a usar os recursos “Câmera” do
android, criando um App de forma prática
Neste e-book, eu vou ensinar passo a passo como criar um aplicativo que vai utilizar os
recursos da Câmera do Android SDK. Entender como funciona esse recurso, é de bom uso
para o desenvolvedor Android. Mais sem muita enrolação, vamos ao que interessa.
Ferramentas
As ferramentas que irei utilizar neste tutorial serão o Android Studio e o Android SDK
Pré requisitos
Para poder acompanhar este tutorial, é imprescindível que você já possua conhecimentos em
Java, Programação Orientada a Objetos e, é claro, Android.
Agora, vamos dar início a parte prática, espero que gostem!
1 – Crie um novo projeto no Android Studio.
4. 4
2 - Em seguida, temos que escolher para qual plataforma vamos desenvolver o nosso App e a
versão minima do sistema operacional no qual o aplicativo será suportado. No meu caso,
escolhi a versão da API 11: Android 3.0
4 - Nesta tela, temos uma porção de modelos prontos para você ultilizar em seus projetos,
mas vamos criar um projeto em branco, escolha Add No Activity.
5. 5
5 - Pronto, a estrutura do nosso projeto já foi criada.
Para que nossa aplicação tenha uma interface de usuário, criaremos uma classe que herda de
Activtity. Também devemos criar o nosso layout. Veja o exemplo:
CameraActivity.java
package com.i9mobi.cameraapp;
import android.app.Activity;
import android.os.Bundle;
public class CameraActivity extends Activity {
protected void onCreate(Bundle saveInstance){
super.onCreate(saveInstance);
setContentView(R.layout.layout_camera);
}
}
camera_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/camera_preview"
android:layout_width="wrap_content"
6. 6
android:layout_height="wrap_content"></FrameLayout>
</LinearLayout>
Crie uma classe chamada CameraSurface.java, estenda a de SurfaceView e implemente a
interface SurfaceHolder.Callback2. Você precisará implementar os métodos Obrigatórios, se
você já estiver antenado sobre POO, então, já está familiarizado com o conceito de interfaces.
CameraSurface.java
package com.i9mobi.cameraapp;
import android.content.Context;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CameraSurface extends SurfaceView implements
SurfaceHolder.Callback2 {
public CameraSurface(Context context){
super(context);
}
@Override
public void surfaceRedrawNeeded(SurfaceHolder holder) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
Em suma, a classe SurfaceView fornece um poderoso recurso para você trabalhar com views,
animação, camadas, hierarquia de elementos e etc. Esta classe será a base principal para a
nossa Câmera.
Voltando ao layout_camera.xml, vamos fazer alguns ajustes e adicionar mais dois botões.
8. 8
Já este, servirá para iniciar a Acitivity que vamos mostrar a foto capturada.
<Button
android:text="Ver Foto"
android:id="@+id/btn_show_picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Inicialize as variáveis referentes aos botões, ultilizando o método findViewById(). Este método
é herdado quando e extendomos da classe Activity.
package com.i9mobi.cameraapp;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
public class CameraActivity extends Activity {
private Button btn_take_picture;
private Button btn_show_picture;
private FrameLayout camera_preview;
protected void onCreate(Bundle saveInstance){
super.onCreate(saveInstance);
setContentView(R.layout.layout_camera);
inicializeViews();
actions();
}
private void inicializeViews(){
btn_take_picture = (Button) findViewById(R.id.btn_take_picture);
btn_show_picture = (Button) findViewById(R.id.btn_show_picture);
camera_preview = (FrameLayout) findViewById(R.id.camera_preview);
}
}
private void actions(){
btn_show_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
btn_take_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
Feito isso, devemos fazer a parte mais importante do nosso aplicativo. Agora, declare uma
variável “mCamera” do tipo “Camera”, o qual será o centro de toda a funcionalidade, importe
o pacote android.hardware.Camera e em seguida adicione esta escreve o código abaixo:
9. 9
public Camera getCameraInstance(){
Camera camera = null;
try{
camera = Camera.open();
}catch (Exception ex){
Log.i("Camera", ex.getMessage());
}
return camera;
}
Instancie a variável mCamera com o método getCameraInstance(), veja:
private void inicializeViews(){
btn_take_picture = (Button) findViewById(R.id.btn_take_picture);
btn_show_picture = (Button) findViewById(R.id.btn_show_picture);
camera_preview = (FrameLayout) findViewById(R.id.camera_preview);
mCamera = getCameraInstance();
}
Código completo do que já fizemos na classe CameraActivity.java:
package com.i9mobi.cameraapp;
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
public class CameraActivity extends Activity {
private Button btn_take_picture;
private Button btn_show_picture;
private FrameLayout camera_preview;
private CameraSurface cameraSurface;
private Camera mCamera;
protected void onCreate(Bundle saveInstance){
super.onCreate(saveInstance);
setContentView(R.layout.layout_camera);
inicializeViews();
actions();
}
public Camera getCameraInstance(){
Camera camera = null;
try{
camera = Camera.open();
}catch (Exception ex){
Log.i("Camera", ex.getMessage());
}
return camera;
}
10. 10
private void inicializeViews(){
btn_take_picture = (Button) findViewById(R.id.btn_take_picture);
btn_show_picture = (Button) findViewById(R.id.btn_show_picture);
camera_preview = (FrameLayout) findViewById(R.id.camera_preview);
mCamera = getCameraInstance();
}
private void actions(){
btn_show_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
btn_take_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
}
Muito bem, tendo a classe CameraActivity.java meio caminho andado, agora, vamos trabalhar
na classe CameraSurface.java.
O primeiro passo, é declarar uma variável do tipo Camera, a mesma forma que declaramos na
classe CameraActivity, mas não a inicialize, apenas declare. Modifique o construtor,
adicionando mais um parâmetro do tipo Camera e atribua o valor na variável declarada no
escopo da classe.
private Camera camera;
public CameraSurface(Context context, Camera camera){
super(context);
this.camera = camera;
}
Feito isso, vamos analisar as seguintes funções:
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
11. 11
A função “surfaceCreated” é chamada quando a SurfaceCamera for criada, recebendo como
parâmetro o objeto SurfaceHolder.
Para mais informações sobre o SurfaceHolder, clique aqui.
A função “surfaceDestroyed” é chamada quando a SurfaceCamera for destruída.
Vamos usar apenas essas duas funções, não precisa se preocupar com as outras, deixe-as
como estão.
Quando a SurfaceView for criada, a Camera receberá o container no qual ela irá desenhar a
imagem. Esse container é o SurfaceHolder passado no parâmetro da função “surfaceCreated”,
veja:
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(holder);
camera.setDisplayOrientation(90);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
Código para quando a SurfaceView estiver sendo destruída
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
}
Por fim, terminamos de implementar a classe CameraSurface.java
package com.i9mobi.cameraapp;
import android.content.Context;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
public class CameraSurface extends SurfaceView implements
SurfaceHolder.Callback2 {
private Camera camera;
private SurfaceHolder surfaceHolder;
public CameraSurface(Context context, Camera camera){
super(context);
this.camera = camera;
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceRedrawNeeded(SurfaceHolder holder) {
12. 12
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(holder);
camera.setDisplayOrientation(90);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
}
}
De volta a classe CameraActivity.java, instancie a variável cameraSurface, passando a variável
mCamera e o contexto no parâmetro do construtor.
mCamera = getCameraInstance();
cameraSurface = new CameraSurface(this, mCamera);
this se refere ao contexto da classe atual.
Depois de ter feito isso, temos que adicionar a cameraSurface ao FrameLayout, que é a
variável “camera_preview”.
camera_preview.addView(cameraSurface)
Antes de compilar o código, temos que declara as permisões no AndroidManifest.xml. Não se
esqueça de adiciona a classe CameraActivity, como atividade principal do seu aplicativo.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.i9mobi.cameraapp">
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.CAMERA"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
14. 14
Crie outra Activity com o nome “ ImagePreview.java” e o layout “image_preview.xml”.
ImagePreview.java
package com.i9mobi.cameraapp;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;
public class ImagePreview extends Activity {
private ImageView imagePreview;
protected void onCreate(Bundle saveInstance){
super.onCreate(saveInstance);
setContentView(R.layout.image_preview);
inicialize();
}
private void inicialize(){
imagePreview = (ImageView) findViewById(R.id.image_preview);
}
}
image_preview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image_preview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
O objeto ImageView, receberá a imagem que será capturada pela Câmera.
Vamos dar um pulinho na classe CameraActivity.java para criar a funcionalidade de captura.
Escreva esse código na classe:
private static File getOutputMediaFile(int type){
File mediaStorageDir = new
File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new
Date());
15. 15
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
Este método servirá para recuperar a nossa imagem capturada, a qual será armazenada no
dispositivo. Não se esqueça de colocar as permissões de leitura e escrita no
AndroidManifest.xml.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Escreva este código:
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d("Camera", "Error creating media file, check storage
permissions: ");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d("Camera", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("Camera", "Error accessing file: " + e.getMessage());
}
}
};
Já este, será o objeto que vamos chamar ao clicar no botão para capturar a imagem. Ele será
passado como parâmetro na função
mCamera.takePicture(null, null, mPicture);
16. 16
Depois de ter capturado e gravado a imagem no armazenamento do dispositivo, vamos
converter o arquivo em Uri.
private static Uri getOutputMediaFileUri(int type){
return Uri.fromFile(getOutputMediaFile(type));
}
Está função, servirá para converter o nosso arquivo(imagem), criado previamente quando o
botão de captura for clicado, a qual será atribuída a ImagemView activity ImagePreview.java
com a função setImageURI().
btn_take_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isCaptured = true; //Esta variável servirá para verificar se a imagem
já foi capturada
mCamera.takePicture(null, null, mPicture);
Constants.IMAGE = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
}
});
Crie uma classe chamada Constants.java.
package com.i9mobi.cameraapp;
import android.net.Uri;
public class Constants {
public static Uri IMAGE = null;
}
Também, vamos precisar chamar a Intent que vai iniciar à activity ImagePreview.
btn_show_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(isCaptured){
Intent intent = new Intent(CameraActivity.this,
ImagePreview.class);
startActivity(intent);
}
}
});
Feito isso, vamos retornar na activity ImagePreview e chamar o método “setImageURI” da
nossa variável “imagePreview”.
imagePreview.setImageURI(Constants.IMAGE);
17. 17
Pronto, finalizamos o nosso aplicativo. Compile e confira.
Obrigado pela sua atenção e paciênte em dedicar o seu tempo ao ler esse conteúdo. Estamos a
disposição para tirar qualquer dúvida ou sugestões, basta entrar nos enviar um email
contato@i9mobi.com
Código completo das classes e layouts
CameraActivity.java
package com.i9mobi.cameraapp;
import android.app.Activity;
import android.content.Intent;
import android.hardware.Camera;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import java.io.File;
import java.io.FileNotFoundException;
18. 18
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CameraActivity extends Activity {
private Button btn_take_picture;
private Button btn_show_picture;
private FrameLayout camera_preview;
private CameraSurface cameraSurface;
private Camera mCamera;
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
public boolean isCaptured = false;
protected void onCreate(Bundle saveInstance){
super.onCreate(saveInstance);
setContentView(R.layout.layout_camera);
Intent intent = new Intent();
inicializeViews();
actions();
}
public Camera getCameraInstance(){
Camera camera = null;
try{
camera = Camera.open();
}catch (Exception ex){
Log.i("Camera", ex.getMessage());
}
return camera;
}
private void inicializeViews(){
btn_take_picture = (Button) findViewById(R.id.btn_take_picture);
btn_show_picture = (Button) findViewById(R.id.btn_show_picture);
camera_preview = (FrameLayout) findViewById(R.id.camera_preview);
mCamera = getCameraInstance();
cameraSurface = new CameraSurface(this, mCamera);
camera_preview.addView(cameraSurface);
}
private static Uri getOutputMediaFileUri(int type){
return Uri.fromFile(getOutputMediaFile(type));
}
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d("Camera", "Error creating media file, check storage
permissions: ");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
19. 19
Log.d("Camera", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("Camera", "Error accessing file: " + e.getMessage());
}
}
};
private static File getOutputMediaFile(int type){
File mediaStorageDir = new
File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new
Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
private void actions(){
btn_take_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isCaptured = true; //Esta variável servirá para verificar se a
imagem já foi capturada
mCamera.takePicture(null, null, mPicture);
Constants.IMAGE = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
}
});
btn_show_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(isCaptured){
Intent intent = new Intent(CameraActivity.this,
ImagePreview.class);
startActivity(intent);
}
}
});
}
}
CameraSurface.java
package com.i9mobi.cameraapp;
20. 20
import android.content.Context;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
public class CameraSurface extends SurfaceView implements
SurfaceHolder.Callback2 {
private Camera camera;
private SurfaceHolder surfaceHolder;
public CameraSurface(Context context, Camera camera){
super(context);
this.camera = camera;
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceRedrawNeeded(SurfaceHolder holder) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
camera.setPreviewDisplay(holder);
camera.setDisplayOrientation(90);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
}
}
Constants.java
package com.i9mobi.cameraapp;
import android.net.Uri;
public class Constants {
public static Uri IMAGE = null;
}
ImagePreview.java