Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Problema no Exercício 2 da aula 2

Boa noite pessoal.

Estou com problemas para salvar a imagem no meu celular. Não estou utilizando um emulador e sim meu celular direto (S4). Eu fiz o código todo e só mudei o diretório que vai salvar para não salvar num cartão de memória e sim na memória interna. Mas sempre que eu tiro a foto no meu onActivityResult a Intent data retorna como null.

Segue abaixo o código utilizado.



package br.com.caelum.cadastro;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import java.io.File;

import br.com.caelum.cadastro.dao.AlunoDAO;
import br.com.caelum.cadastro.modelo.Aluno;

public class FormularioActivity extends AppCompatActivity {
    private FormularioHelper helper;
    private String localArquivoFoto;
    private static final int TIRA_FOTO = 123;

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

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        this.helper = new FormularioHelper(this);

        final Aluno alunoParaSerAlterado = (Aluno) getIntent().getSerializableExtra("alunoSelecionado");

        Button botao = (Button) findViewById(R.id.botao);

        if (alunoParaSerAlterado != null) {
            botao.setText("Alterar");
            this.helper.colocaNoFormulario(alunoParaSerAlterado);
        }

        botao.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                Aluno aluno = helper.pegaAlunoDoFormulario();

                AlunoDAO dao = new AlunoDAO(FormularioActivity.this);

                if (aluno.getId() == null) {
                    dao.insere(aluno);
                } else {
                    dao.altera(aluno);
                }

                dao.close();

                finish();
            }
        });

        ImageView foto = helper.getBotaoImagem();
        foto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                localArquivoFoto = Environment.DIRECTORY_PICTURES +  /*getFilesDir() +*/
                        "/" + System.currentTimeMillis() + "claudio.jpg";

                File arquivo = new File(localArquivoFoto);
                Uri localFoto = Uri.fromFile(arquivo);

                Intent irParaCamera =
                        new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                irParaCamera.putExtra(MediaStore.EXTRA_OUTPUT, localFoto);
                startActivityForResult(irParaCamera, TIRA_FOTO);
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode,
                                    int resultCode, Intent data) {

        if (requestCode == TIRA_FOTO && resultCode == RESULT_OK && data != null) {
            helper.carregaImagem(this.localArquivoFoto);
        } else {
            this.localArquivoFoto = null;
        }
    }

}
4 respostas

Olá Claudio!

Por padrão, quando especificamos o extra MediaStore.EXTRA_OUPUT para a intent da câmera, a foto estará disponível no caminho que você especificou e portanto a intent data será sempre null pois não há necessidade do método onActivityResult(...) passar de volta o caminho para a imagem.

Abraço!

Boa noite Jeferson.

Não entendi como fazer. Se eu utilizo o extra e ele vai salvar automaticamente na pasta como eu faço pra aguardar o retorno da activity e como vou saber se foi executada com sucesso sem usar o onactivityresult?

Mas de qualquer maneira ainda tenho outro problema. Minhas fotos não são armazenadas no dispositivo. Eu starto a activity, tiro a foto, aceito a foto e ela não é salva em lugar nenhum. Não dá erro só não salva.

Só o que eu fiz de diferente do exemplo da aula é que ao invés de selecionar o cartão sd (getExternalFilesDir(null) +"/"+ System.currentTimeMillis()+".jpg";) eu estou mandando salvar na memória interna (getFilesDir() + "/" + System.currentTimeMillis() + ".jpg";)

Consegui fazer funcionar mas da pior maneira. Sem entender direito como resolvi. Fiz diversas buscas no google e mudei a forma de gravar a imagem da câmera.

Tive que incluir no meu androidmanifest a linha android:configChanges="orientation|keyboardHidden|screenSize"> dentro da activy formulario.

Sem essa linha dá erro ao tentar salvar a foto.

O código da minha activity ficou assim: ```package br.com.caelum.cadastro;

import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast;

import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream;

import br.com.caelum.cadastro.dao.AlunoDAO; import br.com.caelum.cadastro.modelo.Aluno;

public class FormularioActivity extends AppCompatActivity { private FormularioHelper helper; private String localArquivoFoto; private static final int TIRA_FOTO = 123;

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

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar);

this.helper = new FormularioHelper(this);

final Aluno alunoParaSerAlterado = (Aluno) getIntent().getSerializableExtra("alunoSelecionado");

Button botao = (Button) findViewById(R.id.botao);

if (alunoParaSerAlterado != null) { botao.setText("Alterar"); this.helper.colocaNoFormulario(alunoParaSerAlterado); }

botao.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) { Aluno aluno = helper.pegaAlunoDoFormulario();

AlunoDAO dao = new AlunoDAO(FormularioActivity.this);

if (aluno.getId() == null) { dao.insere(aluno); } else { dao.altera(aluno); }

dao.close();

finish(); } });

ImageView foto = helper.getBotaoImagem(); foto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { localArquivoFoto = getFilesDir() + "/" + System.currentTimeMillis() + ".jpg";

/*localArquivoFoto = getApplicationContext().getFilesDir().getPath() + "/" + System.currentTimeMillis() + "claudio.jpg";

File arquivo = new File(localArquivoFoto);

Log.d("LocalFoto", localArquivoFoto);

Uri localFoto = Uri.fromFile(arquivo);*/

Intent irParaCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

//irParaCamera.putExtra(MediaStore.EXTRA_OUTPUT, localFoto); startActivityForResult(irParaCamera, TIRA_FOTO);

} }); }

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

InputStream stream = null; if (requestCode == TIRA_FOTO && resultCode == RESULT_OK) { try { stream = getContentResolver().openInputStream(data.getData()); Bitmap bitmap = BitmapFactory.decodeStream(stream);

helper.carregaImagem2(bitmap, localArquivoFoto); } catch (FileNotFoundException e) { e.printStackTrace(); } }

/if (requestCode == TIRA_FOTO && resultCode == RESULT_OK) { helper.carregaImagem(this.localArquivoFoto); } else { this.localArquivoFoto = null; }/ }

}


e do meu formulariohelper assim:

```package br.com.caelum.cadastro;

import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.SeekBar;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import br.com.caelum.cadastro.modelo.Aluno;

/**
 * Created by suporte on 10/01/2016.
 */
public class FormularioHelper {
    private Aluno aluno;
    private EditText nome;
    private EditText telefone;
    private EditText site;
    private SeekBar nota;
    private EditText endereco;
    private ImageView botaoImagem;

    public FormularioHelper(FormularioActivity activity) {

        nome = (EditText) activity.findViewById(R.id.nome);
        telefone = (EditText) activity.findViewById(R.id.telefone);
        site = (EditText) activity.findViewById(R.id.site);
        nota = (SeekBar) activity.findViewById(R.id.nota);
        endereco = (EditText) activity.findViewById(R.id.endereco);
        botaoImagem = (ImageView) activity.findViewById(R.id.foto);
        aluno = new Aluno();
    }

    public Aluno pegaAlunoDoFormulario() {
        aluno.setNome(nome.getEditableText().toString());
        aluno.setEndereco(endereco.getEditableText().toString());
        aluno.setSite(site.getEditableText().toString());
        aluno.setTelefone(telefone.getEditableText().toString());
        aluno.setNota(Double.valueOf(nota.getProgress()));

        return aluno;
    }

    public void colocaNoFormulario(Aluno aluno) {
        nome.setText(aluno.getNome());
        telefone.setText(aluno.getTelefone());
        site.setText(aluno.getSite());
        nota.setProgress(aluno.getNota().intValue());
        endereco.setText(aluno.getEndereco());

        carregaImagem(aluno.getCaminhoFoto());

        //botaoImagem.setImageBitmap(BitmapFactory.decodeFile(aluno.getCaminhoFoto()));
        this.aluno = aluno;
    }

    public ImageView getBotaoImagem() {
        return botaoImagem;
    }

    public void carregaImagem(String localArquivoFoto) {
        Bitmap imagemFoto = BitmapFactory.decodeFile(localArquivoFoto);
        Bitmap imagemFotoReduzida = Bitmap.createScaledBitmap(imagemFoto, 300, 200, true);
        botaoImagem.setRotation(-90);

        botaoImagem.setImageBitmap(imagemFotoReduzida);
    }

    public void carregaImagem2(Bitmap bitmap, String localArquivoFoto) {
        Bitmap imagemFotoReduzida = Bitmap.createScaledBitmap(bitmap, 300, 200, true);

        botaoImagem.setImageBitmap(imagemFotoReduzida);
        botaoImagem.setRotation(-90);

        aluno.setCaminhoFoto(localArquivoFoto);

        gravaImagem(bitmap);
    }

    public void gravaImagem(Bitmap bmp){
        try {
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream);

            byte[] bytes = stream.toByteArray();

            FileOutputStream fos = new FileOutputStream(aluno.getCaminhoFoto());
            fos.write(bytes);
            fos.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

A meu ver isso ficou um tremendo dum pog/colcha de retalhos. Estou errando em algum lugar no código básico da aula mas não sei onde.

Mais uma dúvida. Eu salvo minhas fotos e quando peço o path ele me retorna "/data/data/br.com.caelum.cadastro/files/1452567052175.jpg" e copia essa foto na pasta dcim/camera. Mesmo que eu exclua a foto da pasta dcim*camera a imagem continua aparecendo mas eu não enxergo essa pasta que está salva. Como posso acessá-la?

solução!

Olá Cláudio!

Para realizar a leitura da foto gravada pela câmera, geralmente não utilizamos a intent que é passada como parâmetro no método onActivityResult(...). O motivo disso é que quando essa intent é disponibilizada pelo Android, ela contém apenas o caminho para um thumbnail da foto tirada. Isso significa que ela não vai ter uma resolução muito alta e isso pode não ser o suficiente para a tarefa que queremos realizar.

A solução é continuar usando o método onActivityResult(...) mas apenas ignorar a intent e abrir a imagem utilizando uma BitmapFactory. Para sabermos se deu tudo certo, se o usuário tirou a foto ou cancelou podemos utilizar o parâmetro resultCode como no código abaixo:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Verificamos primeiro se é a intent da câmera que está retornando
    if (requestCode == TIRA_FOTO) {
        // Agora verificamos se deu tudo certo
        if (resultCode == Activity.RESULT_OK) {
            // Então abrimos a imagem a partir do caminho que construímos antes
            Bitmap bitmap = BitmapFactory.decodeFile(caminhoFoto);
            Bitmap bitmapReduzido = Bitmap.createScaledBitmap(bitmap, 300, 300, true);
            imageView.setImageBitmap(bitmapReduzido);
        }
    }
}

Os arquivos salvos nos caminhos devolvidos pelos métodos getExternalFilesDir(...) e getFilesDir(...) sempre serão salvos em pastas que são inacessíveis ao usuário. A diferença é que o primeiro tem a opção de salvar os arquivos em um SDCard externo e o segundo irá salvá-los na memória interna do dispositivo.

Para obter o caminho para uma pasta pública você pode utilizar o método abaixo:

String pastaDeFotos = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);

Ao salvar nessa pasta fica fácil de encontrar as imagens salvas pela câmera.

Abraço!