domingo, 21 de agosto de 2011

Galeria de mídia do Android

Olá povo,

Neste post vou mostrar como tirar uma foto com a aplicação de câmera, salvar a imagem em um diretório temporário e em seguida adiciona-la à galeria de mídia do aparelho. E por último, vou mostrar como carregar uma imagem da galeria.
Vamos iniciar mostrando como chamar a aplicação de câmera.
public void tirarFotoClick(View v) {
  String nomeFoto = DateFormat.format(
    "yyyy-MM-dd_hhmmss", new Date()).toString();

  caminhoFoto = new File(
    Environment.getExternalStoragePublicDirectory(
      Environment.DIRECTORY_PICTURES),
    nomeFoto);

  Intent it = new Intent(
    MediaStore.ACTION_IMAGE_CAPTURE);  
  it.putExtra(MediaStore.EXTRA_OUTPUT, 
    Uri.fromFile(caminhoFoto));
  startActivityForResult(it, 0);
}
A aplicação de câmera é chamada através da ação ACTION_IMAGE_CAPTURE passado no construtor da Intent. Um detalhe interessante aqui é o parâmetro EXTRA_OUTPUT, ele serve para indicar um caminho para a foto ser salva. Sem ele, a imagem será salva com tamanho e qualidade inferior a que a câmera realmente tirou.

caminhoFoto é um atributo do tipo File.
A chamada do método startActivityForResult indica que queremos tratar o resultado da activity que estamos chamando. Esse tratamento é feito no método onActivityResult.
protected void onActivityResult(
  int requestCode, int resultCode, Intent data) {
  super.onActivityResult(
    requestCode, resultCode, data);

  if (resultCode == RESULT_OK && requestCode == 0) {
    ImageView img = (ImageView)
      findViewById(R.id.imageView1);
   
    // Obtém o tamanho da ImageView
    int targetW = img.getWidth();
    int targetH = img.getHeight();
    
    // Obtém a largura e altura da foto
    BitmapFactory.Options bmOptions =
      new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(
      caminhoFoto.getAbsolutePath(), bmOptions);

    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;
    
    // Determina o fator de redimensionamento
    int scaleFactor = Math.min(
      photoW/targetW, photoH/targetH);
    
    // Decodifica o arquivo de imagem em 
    // um Bitmap que preencherá a ImageView
    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;
    
    Bitmap bitmap = BitmapFactory.decodeFile(
      caminhoFoto.getAbsolutePath(), bmOptions);
    img.setImageBitmap(bitmap);
  }
}
Quando chamamos a câmera, no startActivityForResult, passamos o valor 1 como segundo parâmetro, esse valor representa o código da requisição (requestCode). Esse valor é retornado no método onActivityResult para saber se o resultado que estamos tratando é daquela requisição. No if que fizemos, além do requestCode, checamos o resultCode. O resultCode descreve o resultado da operação, que neste caso é tirar a foto. Se o resultado for RESULT_OK, é porque uma foto foi tirada.
[EDITADO em 12/05/2013] 
A foto que é tirada com as câmeras atuais requer muita memória para ser alocada. Sendo assim, verificamos o tamanho da ImageView para carregar a imagem deste tamanho.
O atributo caminhoFoto que foi atribuído no método tirarFotoClick é utilizado para carregar a imagem e atribuir em um ImageView. Agora vamos ver como salvar essa imagem na galeria de mídia.
public void salvarFotoClick(View v) {
  if (caminhoFoto != null && caminhoFoto.exists()) {
    MediaStore.Images.Media.insertImage(
      getContentResolver(), 
      caminhoFoto.getAbsolutePath(), 
      caminhoFoto.getName(), "");

    Toast.makeText(this, 
      "Imagem adicionada a galeria.",
      Toast.LENGTH_SHORT).show();
  }
}
A classe MediaStore.Images.Media tem um "método mágico" que permite que possamos inserir um Bitmap na galeria. Essa operação é feita graças a um ContentProvider disponibilizado pela aplicação de galeria. O próximo passo será como abrir a galeria de mídia para selecionarmos uma imagem.
public void galleryButtonClick(View v) {

  Intent intent = new Intent(
    Intent.ACTION_GET_CONTENT);
  intent.setType("image/*");
  startActivityForResult(intent, 2);
}
O código acima abrirá a aplicação de galeria. Notem que agora passamos o valor 2 para o startActivityForResult. Da mesma forma que fizemos para tirar foto, usaremos o método onActivityResult para tratar a imagem selecionada.
// adicione esse código no onActivityResult
if (resultCode == RESULT_OK && requestCode == 2) {
  Uri selectedImage = data.getData();
  String[] filePathColumn = { 
    MediaStore.Images.Media.DATA };

  Cursor cursor = getContentResolver().query(
    selectedImage, filePathColumn, null, null, null);
  cursor.moveToFirst();

  int columnIndex = cursor.getColumnIndex(
    filePathColumn[0]);
  String filePath = cursor.getString(columnIndex); 
  cursor.close();

  Bitmap yourSelectedImage = 
    BitmapFactory.decodeFile(filePath);

  imageView1.setImageBitmap(yourSelectedImage);
}
A galeria retorna o endereço da imagem selecionada através de um objeto Uri que é obtido em data.getData(). Com essa informação podemos acessar o ContentProvider da galeria para obter o caminho da imagem. Com esse caminho passamos para a classe BitmapFactory que retornará um objeto Bitmap para preencher a imageView.

Qualquer dúvida, deixem seus comentários.

4br4ç05,
nglauber

segunda-feira, 15 de agosto de 2011

Google compra Motorola Mobility


Olá povo,

Você chega na segunda de manhã e se depara com uma notícia que balança o mundo mobile: a compra da Motorola Mobility pela Google.
Não tô afim de escrever muito, mas vou colocar minha opinião pessoal. Achei essa aquisição bastante oportuna e ao meu ver até esperada. A Apple tem seu próprio SO (iOS) e fabrica seu hardware; a Nokia fecha parceria com a Microsoft para o Windows Phone; nada mais justo do que a Google se juntar com alguém, e com alguém que apostou muito no Android como a Motorola.

Aí pode vir a pergunta: e porque não a HTC ou a Samsung? Na minha opinião, pode ser porque esses dois fabricantes em especial "dão tiros pra todo lado". Digo isso porque podemos encontrar celulares Samsung com Bada, e da HTC com Windows, além do próprio sistema da Google. Então eu creio que eles continuarão assim, diversificando seus produtos.

Outro ponto importante é que o Google/Android/Fabricantes estavam sendo processados por diversos concorrentes por questões de patentes, e em muitos casos, perdendo essas disputas na justiça. Com a compra da Motorola, o Google amplia seu leque de patentes e protege a si e aos parceiros (fabricantes) que adotam o Android, uma vez que a Google reiterou sua posição de deixa-lo Open Source.

Sendo assim, acho que isso fortalecerá o Android e aquecerá ainda mais o mercado mobile. E nós, como desenvolvedores, devemos estar preparados para onde quer que o vento leve este barco.
E vocês, o que acham? Deixem seus comentários.

4br4ç05,
nglauber

*imagem Gizmodo Brasil

sábado, 6 de agosto de 2011

Artigo "Sensores no Android"

Olá povo,

A revista Java Magazine edição 94, trás uma matéria sobre utilização de sensores na plataforma Android. Ela foi escrita por mim e pelos meus colegas Edilson Mendes(Ronaldo!) e Artur Botelho (o doido :)

Este artigo demonstra como obter informações dos sensores dos aparelhos Android através da Sensor API. Com ela podemos capturar informações como aceleração e orientação do aparelho. Estes e outros sensores podem servir tanto como mecanismo de iteração com o usuário, quanto de canal de comunicação para obter informações sobre o dispositivo e o ambiente onde ele se encontra. O sensor de aceleração, também conhecido como acelerômetro, por exemplo, é amplamente utilizado em jogos disponíveis no Android Market.

Espero que vocês gostem.

4br4ç05,
nglauber

sexta-feira, 5 de agosto de 2011

Apple Fail

Olá povo,

Como vocês sabem, aqui no blog coloco coisas da minha vida profissional, então a maioria dos exemplos de código que eu coloco aqui, vem de necessidades minhas, ou de alunos/colegas durante o desenvolvimento de seus projetos. Entretanto, dessa vez não serão exemplos de código que colocarei aqui, e sim um registro, para que eu lembre e quem sabe até me retrate depois em relação a Apple.

Não estou nada satisfeito com os produtos da companhia do Steve Jobs. Comprei meu Macbook (branco) em Fevereiro deste ano, e em julho, após pagar os U$30 para atualizar o sistema operacional para a versão Lion, o computador já travou 3 vezes apresentando e tela de "kernel panic". Tudo bem que o Lion está na primeira versão, mas devemos combinar que isso é inadmissível.

Também não tive uma boa experiência com o tablet "da maçã". Em junho, comprei um iPad 2 (16GB + Wi-Fi + 3G) pois estava bastante motivado para desenvolver aplicações para iOS. Porém, após 32 dias de uso o mesmo apresentou um defeito: uma linha de pixels queimados de cima a baixo. Isso mesmo, uma linha de "dead pixels".

Acabei de solicitar a devolução do mesmo junto a empresa onde adquiri, e felizmente acho que vou conseguir meu dinheiro de volta. Se isso acontecer, comprarei um outro tablet, mas com certeza, não será um iPad, pois duas experiências ruins de uma vez não são lá muito motivadoras.

Por ser um professor, e ter uma pequena parcela de participação na formação de pessoas, acho legal ter um registro como esse para que elas não fiquem com a imagem de que a Apple é perfeita. Não é, e pelo que eu vi depois dessas experiências, está longe disso.

4br4ç05,
nglauber

quarta-feira, 27 de julho de 2011

Android: Instalação e configuração

Olá povo,

Em praticamente todas as minhas turmas de Android os alunos me pediam um tutorial de instalação e configuração do ambiente. Finalmente saiu!!! :) No documento abaixo, coloquei um passo-a-passo que apresenta como instalar e configurar todas as ferramentas necessárias para iniciar o desenvolvimento com essa fantástica plataforma.

Para baixar o tutorial, clique aqui no link abaixo.

Configuração do Ambiente de Desenvolvimento Android

Qualquer dúvida ou sugestão, deixem seus comentários.

4br4ç05,
nglauber

segunda-feira, 25 de julho de 2011

Formação em Google Android

Olá povo,

O CESAR.edu, unidade de educação do C.E.S.A.R. (Centro de Estudos e Sistemas Avançados do Recife) está lançando o curso de Formação em Google Android. A capacitação abordará o desenvolvimento de aplicativos para a plataforma de dispositivos móveis da Google, tendo como base a usabilidade e qualidade através de estratégias de testes.
A disciplina de Android (com duração de 50 horas), abordará desde a instalação do ambiente de desenvolvimento e conceitos básicos como Activities e Intents, até conceitos avançados como Sensores, Bluetooth e comunicação com Web Services.

Maiores informações, clique aqui.

4br4ç05,
nglauber

segunda-feira, 4 de julho de 2011

Google Cloud Print + Android

Olá povo,

O post de hoje tem todos os créditos do meu colega Felipe Vasconcelos, que precisou adicionar a funcionalidade de imprimir um documento através de um aparelho Android.
A solução utilizada por ele foi o Google Cloud Print (http://www.google.com/cloudprint), um serviço que permite com que você compartilhe a(s) impressora(s) conectadas à sua máquina através da sua conta do Google.


O serviço está disponível apenas para máquinas Windows, por enquanto. Para utiliza-lo, é necessário fazer o download do Chrome, em seguida, habilitar o serviço. Para tal, basta seguir esse tutorial (do próprio Google).

Após habilitar o serviço, basta entrar no site do cloud print e "automagicamente" as impressoras que estão conectadas à sua máquina estarão "nas núvens", prontas para receber impressões.

Para imprimir documentos a partir da sua aplicação Android, basta adicionar os arquivos print_dialog.xml e PrintDialog.Activity.java ao seu projeto Android (na pasta res/layout e src respectivamente). Não esqueça de declarar a Activity e adicionar a permissão android.permission.INTERNET ao AndroidManifest.xml. Esses arquivos são do próprio Google (veja aqui).

Agora, para imprimir um arquivo TXT que esteja no SDCard, por exemplo, basta utilizar o código abaixo:


Intent printIntent =
new Intent(this, PrintDialogActivity.class);

printIntent.setDataAndType(
Uri.parse("file:///mnt/sdcard/arquivo.txt"),
"text/plain");

// Job da impressora
printIntent.putExtra("title", "Meu arquivo");
startActivity(printIntent);
Como vc deve imaginar, se fosse imprimir outro tipo de arquivo, bastaria mudar o MIME type.
Será exibida a tela abaixo. Faça o login no aparelho Android, selecione uma impressora, clique em "Print" e pronto!





Parabéns Felipe! Grande dica. E qualquer dúvida, falem com ele :)

4br4ç05,
nglauber