terça-feira, 7 de junho de 2016

Carregando imagens da galeria do Android

Olá povo,

Nesse post rápido vou mostrar como carregar imagens da galeria de mídia do Android. O único detalhe a observar nesse post é que estamos carregando imagens tanto locais quando as que estão em algum serviço da nuvem como DropBox e Google Photos. Por isso, para começar coloque as permissões necessárias no AndroidManifest.xml.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
Lembrando que para o Android 6 (API Level 23) você deve checar essas permissões em tempo de execução.

Em seguida, inicie uma nova activity utilizando a ação ACTION_GET_CONTENT.
private static final int IMAGE_GALLERY_REQUEST = 1;
...
public void selectImageClick(View view) {
    if (ActivityCompat.checkSelfPermission(this, 
            Manifest.permission.READ_EXTERNAL_STORAGE) ==
            PackageManager.PERMISSION_GRANTED) {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(
                Intent.createChooser(
                        intent,
                        getString(R.string.select_picture_title)),
                IMAGE_GALLERY_REQUEST);
    } else {
        ActivityCompat.requestPermissions(this,
                new String[]{ Manifest.permission.READ_EXTERNAL_STORAGE },
                IMAGE_GALLERY_REQUEST);
    }
}
Ao selecionarmos uma imagem, o método onActivityResult será chamado.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == IMAGE_GALLERY_REQUEST && resultCode == RESULT_OK){
        new LoadImageTask(this).execute(data.getData());
    }
}

Como falamos anteriormente, carregaremos as imagens do sistema de arquivos ou da web. Por isso, devemos realizar essa operação fora da UI thread, então definimos a classe LoadImageTask.
class LoadImageTask extends AsyncTask<Uri, Void, Bitmap> {

    WeakReference<PickImageActivity> mActivity;

    public LoadImageTask(PickImageActivity activity) {
        this.mActivity = new WeakReference<>(activity);
    }

    public PickImageActivity getActivity() {
        return mActivity.get();
    }

    @Override
    protected Bitmap doInBackground(Uri... params) {
        if (getActivity() != null) {
            try {
                return BitmapFactory.decodeStream(
                        getActivity().getContentResolver().openInputStream(params[0]));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        super.onPostExecute(bitmap);
        if (getActivity() != null){
            getActivity().showImage(bitmap);
        }
    }
}
Temos algumas coisas interessantes aqui. A primeira é essa classe não deve ser uma inner class da Activity/Fragment, pois uma inner class sempre contém uma referência para sua outer class. Uma vez que ela não é uma inner class, devemos passar a referência da activity/fragment para essa classe. Estamos utilizando uma WeakReference para armazenar a instância da activity, o motivo disso é evitar o leak de memória, já que se o usuário sair da tela antes da imagem ser baixada aquela memória ficará alocada desnecessariamente durante algum tempo.
Outra coisa interessante é que estamos utilizando o método openInputStream() da classe ContentResolver para obter a imagem propriamente dita.
A imagem retornada terá o seu tamanho original, se você preferir, pode utilizar a técnica de redimensionamento de imagem que eu mostrei nesse post.
Por fim, no onPostExecute, invocamos o método showImage da Activity.
public void showImage(Bitmap bitmap) {
    ImageView imageView = (ImageView)findViewById(R.id.imageView);
    if (imageView != null){
        imageView.setImageBitmap(bitmap);
    }
}
Qualquer dúvida, deixe seu comentário ;)

 4br4ç05,
nglauber

2 comentários:

Blog do ueder disse...

Nelson, suas dicas são demais.
Já virei fã seu desde a primeira edição do seu livro.

Nelson Glauber disse...

Valeu Ueder,!

4br4ç05,
nglauber