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

Uso do Bitmap no ImageView

Olá, pessoal.

No meu formulário, é possível tirar uma foto pela câmera e depois atribuir a uma ImageView. Ela aparece na miniatura do formulário utilizando o set visita.setFoto(fotoDaCamera);. Dessa forma, o set está funcionando normalmente ao meu ver.

Contudo, o erro acontece quando tento alterar esse cadastro (dá crash ao abrir o formulário) e parece que o erro é neste comando: campoFoto.setImageBitmap(visita.getFoto());, pois quando tenho um cadastro sem foto, a edição ocorre naturalmente.

No log, não entendi o erro, pois aparece "Parcelable encountered IOException writing serializable object"

Observação: estou utilizando o serializable.

Alguém teria uma luz? Obrigado.

21 respostas

Thiago, tudo bem ?

Qual é o formato que você está salvando essa foto ?

Se for string você vai precisar fazer a conversão dela.

Além disso, se tiver salvando o bitmap, bitmap é uma classe que implementa parcelable e o comportamento entre serializable e parcelable não é muito bom.

Recomendo que você salve o caminho da foto e quando necessário abre o arquivo.

Semelhante com o que é feito no curso

Ah tá. Estou usando bitmap com serializable. Vou mudar e te falo. Obrigado

Fala, Matheus. Parcelable implementado e inicialmente funcionando rsrsrs.

Tiro a foto, salvo o formulário e ela aparece quando eu abro o formulário para edição. Contudo, ao salvar a edição e abrir novamente, a foto fica vazia.

Código se achar melhor: https://github.com/thiagornela/visita

Um método está assim:

protected Visita(Parcel in) {
        foto_familia = (Bitmap) in.readValue(Bitmap.class.getClassLoader());
//restante.....

O outro:

@Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeValue(foto_familia);
//restante.....

Coloquei o Bitmap usando o comando "Value", pois, em um tutorial, vi o cara fazendo essa recomendação.

Já o get e o set estão assim:

public Bitmap getFoto_familia() {
        return foto_familia;
    }

    public void setFoto_familia(Bitmap foto_familia) {
        this.foto_familia = foto_familia;
    }

Acho que tu pode usar writeParcelable no lugar do writeValue e na hora de recuperar readParcelable invés do readValue

Ficou assim: dest.writeParcelable(foto_familia, flags); e foto_familia = in.readParcelable(Bitmap.class.getClassLoader());, mas na segunda edição o ImageView continuou "em branco". aff

Rapaz, fui ler umas coisas agora e me toquei em algo.

O bitmap geralmente ultrapassa os 1MB máximo que o Bundle, que fica dentro da Intent consegue trafegar, por isso deve estar ficando em branco.

Olhando aqui a galera recomenda que você passe apenas uma referencia para ter acesso a esse bitmap do outro lado, como o caminho da foto por exemplo se for local, caso seja web, passar a url.

Rapaz, já estava difícil antes... kkkk.

Não sei o caminho da foto não kkkkk

O código está assim:

public void tirarFoto(View view) {
        Intent intentTirarFoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(intentTirarFoto, RESULT_TIRAR_FOTO);
    }

    private void pegaFotoGaleria() {
        Intent intentPegaFoto = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI);
        startActivityForResult(intentPegaFoto, RESULT_PEGA_FOTO_GALERIA);
    }

    @Override
    protected void onActivityResult(int requestCode, int resulteCode, Intent data) {
        super.onActivityResult(requestCode, resulteCode, data);
        if (requestCode == RESULT_TIRAR_FOTO) {
            if (data != null) {
                Bundle bundle = data.getExtras();
                if (bundle != null) {
                    fotoDaFamilia = (Bitmap) bundle.get("data");
                    campoFotoFamilia.setImageBitmap(fotoDaFamilia);
                }
            }
        } else if (requestCode == RESULT_PEGA_FOTO_GALERIA && resulteCode == RESULT_OK) {
            carregarImagemGaleria(data);
        }
    }

Provavelmente estaria salvando em uma pasta temporária? Ainda estou usando o savedInstanceState. Como está quase finalizado, no decorrer da semana mudarei isso.

               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 imgDecodableString = cursor.getString(columnIndex);
                cursor.close();

                imgView.setImageBitmap(BitmapFactory.decodeFile(imgDecodableString));

senão estiver enganado esse código te dá o caminho da foto :)

Vamos lá, Matheus. Força. Preciso de vc para não desistir, cara kkkkkk

Deu NEP. Veja se meu raciocínio está certo, por favor rs

Para utilizar a parte data.getData() do seu código (1ª linha), coloquei Uri selectedImage como atributo da classe. Por quê?

Para eu usá-lo no método que tira a foto ou pega na galeria. Assim:

protected void onActivityResult(int requestCode, int resulteCode, Intent data) {
        super.onActivityResult(requestCode, resulteCode, data);
        if (requestCode == RESULT_TIRAR_FOTO) {
            if (data != null) {
                Bundle bundle = data.getExtras();
                if (bundle != null) {
                    fotoDaFamilia = (Bitmap) bundle.get("data");
                    campoFotoFamilia.setImageBitmap(fotoDaFamilia);
                    this.selectedImage = data.getData(); ///////////////////////////////// USEI ELE AQUI
                }
            }
        } else if (requestCode == RESULT_PEGA_FOTO_GALERIA && resulteCode == RESULT_OK) {
            carregarImagemGaleria(data);
        }
    }

    public void carregarImagemGaleria(Intent data) {
        InputStream stream = null;
        try {
            if (fotoDaFamilia != null) {
                fotoDaFamilia.recycle();
            }
            stream = getContentResolver().openInputStream(data.getData());
            fotoDaFamilia = BitmapFactory.decodeStream(stream);
            this.selectedImage = data.getData();///////////////////////////////// USEI ELE AQUI
            campoFotoFamilia.setImageBitmap(fotoDaFamilia);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

Aí, no método preencheCamposEdicao() que eu coloquei o restante do código:

String[] filePathColumn = { MediaStore.Images.Media.DATA };

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

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

        campoFotoFamilia.setImageBitmap(BitmapFactory.decodeFile(imgDecodableString));

Muita coisa errada?

O que eu te mandei é pra ser utilizado no instante que você pega a foto da galeria, assim você consegue armazenar o caminho relativo da foto


                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 imgDecodableString = cursor.getString(columnIndex);
                cursor.close(); // aqui voce tem o caminho -> essa string voce precisa armazenar na sua aplicação para que consiga trabalhar com ela sem problemas maiores

                imgView.setImageBitmap(BitmapFactory.decodeFile(imgDecodableString));


Ahhhhh tá kkkk. Funciounou não rsrs. Qdo seleciono a foto na galeria, o ImageView fica em branco. Ficou assim:

public void carregarImagemGaleria(Intent data) {
        InputStream stream = null;
        try {
            if (fotoDaFamilia != null) {
                fotoDaFamilia.recycle();
            }
            stream = getContentResolver().openInputStream(data.getData());
            fotoDaFamilia = BitmapFactory.decodeStream(stream);
            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]);
            imgDecodableString = cursor.getString(columnIndex);
            cursor.close(); 

            campoFotoFamilia.setImageBitmap(BitmapFactory.decodeFile(imgDecodableString));

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
solução!

Se tentarmos fazer algo assim então?

   @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);

                if(requestCode == RESULT_PEGA_FOTO_GALERIA && resulteCode == RESULT_OK){
                    Uri selectedImage = intent.getData();

                     Bitmap   bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), selectedImage);
        String caminho =  selectedImage.toString(); // o caminho deve estar aqui
                    imageView.setImageBitmap(bitmap);

                }
        }
    }
}

Deu não. Quando seleciono a foto na galeria, ela aparece no ImageView, mas dá erro ao abrir para edição.

Mas já fiz tanta mudança nesse código que não sei mais nada... se é bagunça mesmo ou outra coisa . Desespero mode on rs

Bom dia, Matheus. Bom? Tem como dar uma olhada direto no código? Pq tá difícil entender essa parte kkkk

Cara, peguei seu código aqui e rodei, fiz um pequena alteração e acredito que esteja funcionando.

Fiz o seguinte:

  • no seu método preencheVisitaFinalizada adicionei o um if para validar se precisa ou não mudar a foto:

      if (fotoDaFamilia != null)
          visita.setFoto_familia(fotoDaFamilia);
  • no seu método preencheCamposEdicao apenas mudei a fonte de onde pegava a foto:

      campoFotoFamilia.setImageBitmap(visita.getFoto_familia());

Está tudo funcionando, testa ai e vê se esse era o resultado que você quer

Rapaz, tu é fera. Funcionou 98%. Qdo tirei uma foto pela câmera, salvou e editei (com a foto aparecendo) e salvei novamente. Perfeitamente.

Mas quando peguei a foto da galeria e salvei o cadastro, na edição deu NEP. Contigo aí funcionou?

Não consegui simular a galeria por estar usando emulador, em tese não devia ter problema algum nisso.

Tu consegue mostrar onde o erro ocorre ?

E em qual momento tem quebrado ?

Depois que faço o cadastro, ele aparece no adapter. O erro dá exatamente quando clico nele para abrir a edição.

2021-01-21 14:11:20.356 28128-28128/com.example.cadastrodevisita E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 48772264)
2021-01-21 14:11:20.358 28128-28128/com.example.cadastrodevisita E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.cadastrodevisita, PID: 28128
    java.lang.RuntimeException: Failure from system
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1722)
        at android.app.Activity.startActivityForResult(Activity.java:5258)
        at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:675)
        at android.app.Activity.startActivityForResult(Activity.java:5203)
        at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:662)
        at android.app.Activity.startActivity(Activity.java:5587)
        at android.app.Activity.startActivity(Activity.java:5555)
        at com.example.cadastrodevisita.ui.activities.MainActivity.vaiParaEditaVisita(MainActivity.java:75)
        at com.example.cadastrodevisita.ui.activities.MainActivity.access$100(MainActivity.java:23)
        at com.example.cadastrodevisita.ui.activities.MainActivity$2.onItemClick(MainActivity.java:64)
        at android.widget.AdapterView.performItemClick(AdapterView.java:374)
        at android.widget.AbsListView.performItemClick(AbsListView.java:1736)
        at android.widget.AbsListView$PerformClick.run(AbsListView.java:4207)
        at android.widget.AbsListView$7.run(AbsListView.java:6692)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:8167)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
     Caused by: android.os.TransactionTooLargeException: data parcel size 48772264 bytes
        at android.os.BinderProxy.transactNative(Native Method)
        at android.os.BinderProxy.transact(BinderProxy.java:575)
        at android.app.IActivityTaskManager$Stub$Proxy.startActivity(IActivityTaskManager.java:4450)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1716)
        at android.app.Activity.startActivityForResult(Activity.java:5258) 
        at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:675) 
        at android.app.Activity.startActivityForResult(Activity.java:5203) 
        at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:662) 
        at android.app.Activity.startActivity(Activity.java:5587) 
        at android.app.Activity.startActivity(Activity.java:5555) 
        at com.example.cadastrodevisita.ui.activities.MainActivity.vaiParaEditaVisita(MainActivity.java:75) 
        at com.example.cadastrodevisita.ui.activities.MainActivity.access$100(MainActivity.java:23) 
        at com.example.cadastrodevisita.ui.activities.MainActivity$2.onItemClick(MainActivity.java:64) 
        at android.widget.AdapterView.performItemClick(AdapterView.java:374) 
        at android.widget.AbsListView.performItemClick(AbsListView.java:1736) 
        at android.widget.AbsListView$PerformClick.run(AbsListView.java:4207) 
        at android.widget.AbsListView$7.run(AbsListView.java:6692) 
        at android.os.Handler.handleCallback(Handler.java:883) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:237) 
        at android.app.ActivityThread.main(ActivityThread.java:8167) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100) 
2021-01-21 14:11:20.387 2210-2210/? E/Zygote: isWhitelistProcess - Process is Whitelisted
2021-01-21 14:11:20.388 2210-2210/? E/Zygote: accessInfo : 1
2021-01-21 14:11:20.401 2210-2210/? E/ng.android.loo: Not starting debugger since process cannot load the jdwp agent.
2021-01-21 14:11:20.415 18299-18299/? E/DecorView: mWindow.mActivityCurrentConfig is null
2021-01-21 14:11:20.431 1953-1953/? E/libprocessgroup: set_timerslack_ns write failed: Operation not permitted
2021-01-21 14:11:20.464 1053-1308/? E/InputDispatcher: channel '90d23b0 com.example.cadastrodevisita/com.example.cadastrodevisita.ui.activities.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed!

Não é problema de null pointer cara, olha o erro: TransactionTooLargeException muito grande a foto.

Como te disse, o bundle não aguenta o valor, você vai precisar saber quando a foto é da galeria, pra poder buscar através do caminho da foto e tem mais, se a pessoa deletar a foto da galeria, seu app também tá passível de quebrar :(

Blz. Vou pesquisar esse tipo de tratamento. Muitíssimo obrigado mesmo, cara.