quinta-feira, 14 de maio de 2015

Como tirar fotos a partir de um app Android

A possibilidade de utilizar a câmera do dispositivo para tirar fotos a partir de nosso próprio app Android é muito atraente e certamente será de grande importância para dezenas de aplicações.

Geralmente no Android há duas formas de realizar determinadas operações. Como exemplo podemos citar o envio de mensagens SMS. É possível chamar o aplicativo nativo de envio de SMS já passando como parâmetros destinatário e o assunto, e então o próprio aplicativo nativo envia a mensagem. Ou, alternativamente, pode-se fazer com que nosso próprio app envie o SMS. É uma questão de escolha. Neste tutorial ensinaremos a primeira abordagem, ou seja, utilizaremos o aplicativo padrão de câmera do dispositivo.

Embora possa parecer algo complicado numa primeira análise, na verdade é extremamente simples. Chamamos o aplicativo de câmera nativo do aparelho (informando o diretório onde desejamos que a foto seja gravada) e então, concluída a operação de obtenção da fotografia, lemos o arquivo JPG e mostramos na tela do nosso app.

Então vamos lá...

Primeiro vamos criar um projeto novo e chamá-lo de "fotografo". Depois vamos abrir o arquivo "AndroidManifest.xml" e acrescentar (após o elemento "<uses-sdk>") a seguinte permissão:


<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />



Isto fará com que nosso app possa gravar no cartão de memória do dispositivo (SDCARD).

Agora vamos abrir o arquivo "strings.xml" da pasta "res/values" e acrescentar os dois parâmetros abaixo, marcados em azul, para que fique assim:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">fotografo</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
   
    <string name="resultado"></string>
    <string name="textoBotaoTirarFoto">Fotografar</string>

</resources>


O que estamos fazendo com isto é definir um campo de mensagens, para mostrar o resultado da operação e também o texto do botão que colocaremos na tela.

Em seguida vamos construir o layout da tela que apresentaremos ao usuário. Abramos portanto o arquivo "activity_main.xml", da pasta "res/layout" e substituamos pelo código abaixo:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textViewResultado"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/resultado" />

    <LinearLayout
        android:id="@+id/LayoutPrincipal"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_below="@+id/textViewResultado"
        android:gravity="bottom|center_horizontal"
        android:orientation="vertical" >

        <ImageView
            android:id="@+id/imageViewFoto"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal|center_vertical"
            android:layout_weight="0.67"
            android:scaleType="center"
            android:src="@drawable/preview" />

        <Button
            android:id="@+id/btnTirarFoto"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/imageViewFoto"
            android:text="@string/textoBotaoTirarFoto" />
    </LinearLayout>

</RelativeLayout>


Aqui estamos acrescentando um "TextView", que utilizaremos para mostrar o resultado da operação de tirar a foto (textViewResultado). Também um "ImageView" , onde mostraremos a imagem da foto tirada (imageViewFoto). Por último, estamos incluindo um botão que será utilizado pelo usuário para chamar a operação de tirar a foto ("btnTirarFoto").


Faça o download da figura abaixo. Crie uma pasta sob o diretório "res" chamada "drawable". Grave esta imagem (preview.png) nesta pasta.






Agora a parte final. Vamos abrir o arquivo "MainActivity.java" da pasta "src" e substituir integralmente o código por este:


package com.example.fotografo;

import java.io.File;
import java.util.Random;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.View.OnClickListener;

public class MainActivity extends Activity
{
   private static final int IMAGEM_VIA_CAMERA=0;
   private Button btnTirarFoto;
   private TextView textViewResultado;
   private Intent intent;
   private Bitmap mImageBitmap;
   private Bitmap mImageBitmapThumb;
   private ImageView imageViewFoto;
   private String nomeDoArquivo;

   @Override
   protected void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      // Obtém os elementos da tela.
      btnTirarFoto=(Button) findViewById(R.id.btnTirarFoto);
      textViewResultado=(TextView) findViewById(R.id.textViewResultado);
      imageViewFoto=(ImageView) findViewById(R.id.imageViewFoto);

      // Adiciona listener ao botão.
      addListenerOnButtonFotografar();

   }

   public void addListenerOnButtonFotografar()
   {

      // A função de um listener no botão é verificar se houve intervenção do usuário sobre ele.
      // Aqui verificamos se o usuário clicou no botão e em caso afirmativo, tomamos uma ação.
      btnTirarFoto.setOnClickListener(new OnClickListener()
      {

         @Override
         public void onClick(View v)
         {

            // Configura e cria o diretório de gravação como "MinhasImagens" dentro do SDCARD.
            File diretorioDeImagens = new File(Environment.getExternalStorageDirectory(), "MinhasImagens");
            diretorioDeImagens.mkdirs();

            // Cria um prefixo para o nome do arquivo.
            Random r=new Random();
            int prefixo=r.nextInt(10000) + 1;
           
            // Constrói o nome do arquivo e informa onde o aplicativo de câmera deverá gravar a foto.
            nomeDoArquivo = "imagem_" + prefixo + ".jpg";
            File image = new File(diretorioDeImagens, nomeDoArquivo);
            Uri uriSavedImage = Uri.fromFile(image);
           
            // Chama o aplicativo de câmera do dispositivo e aguarda o resultado.           
            intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
            startActivityForResult(intent, IMAGEM_VIA_CAMERA);
            // Note que "IMAGEM_VIA_CAMERA" é o nosso identificador (requestCode).
           
         }

      });

   }

   // Este método será chamado quando houver um resultado originário
   // de uma atividade previamente requisitada.
   public void onActivityResult(int requestCode, int resultCode, Intent intent)
   {
      // requestCode é o identificador que permite identificar de onde veio a chamada.
      if (requestCode == IMAGEM_VIA_CAMERA)
      {
         // Caso o usuário tenha tido êxito em tirar uma foto.
         if (resultCode == RESULT_OK)
         {

            // Atualiza a caixa de mensagens.
            textViewResultado.setText("Imagem gravada com sucesso");

            // Lê a imagem gravada.
            File sdcard = Environment.getExternalStorageDirectory();
            mImageBitmap=BitmapFactory.decodeFile(sdcard+"/MinhasImagens/" + nomeDoArquivo);
           
            // Gera um thumbnail.
            Bitmap imagemRedimensionada=Bitmap.createScaledBitmap(mImageBitmap, 300, 200, false);
           
            // Rotaciona a imagem em 90 graus.
            Matrix matrix = new Matrix();
            matrix.postRotate(90);
    Bitmap imagemRotacionada = Bitmap.createBitmap(imagemRedimensionada , 0, 0, imagemRedimensionada.getWidth(), imagemRedimensionada.getHeight(), matrix, true);
                            
            // Mostra o thumbnail da foto na tela do app.
            mImageBitmapThumb = imagemRotacionada;
            imageViewFoto.setVisibility(View.VISIBLE);
            imageViewFoto.setImageBitmap(mImageBitmapThumb);

         }
         else
         {
            // Atualiza mensagem de erro.
            textViewResultado.setText("Operação cancelada pelo usuário");

            // Restaura imagem original (de preview).
            int id=getResources().getIdentifier("com.example.fotografo:drawable/preview", null, null);
            imageViewFoto.setImageResource(id);
         }
      }
   }
     
}



Pronto! Basta isso. Execute o projeto. O app vai abrir uma tela inicial com a imagem de preview, aguardando que o usuário pressione o botão "fotografar". Ao fazê-lo, ele será redirecionado para o aplicativo nativo de foto do dispositivo. Depois que a foto for tirada e o usuário clicar em "save" na imagem, o controle será retomado pelo nosso app, que mostrará a foto no lugar da imagem de preview:







Também, utilizando as classes "BitMap" e "Matrix", fizemos uma operação de rotação e outra de redimensionamento da imagem, para que aparecesse em pé na tela do celular e na forma de "thumbnail".

Para quem preferir fazer obter o código-fonte completo, eis aqui o link de download. Se quiser visualizar direto no celular, eis o APK.

Até a próxima e fiquem ligados!

Nenhum comentário:

Postar um comentário