How do I upload multiple images automatically to Firebase Storage - Android Studio

I am developing an app, this app the user can already choose multiple images, but I am not able to upload the chosen images automatically to Firebase Storage. The user can log in. Can someone help me, how to do this upload process and create together folder that will store the images through each id already authenticated?

public class TelaverGaleriaActivity extends AppCompatActivity {
    private static final int SELECAO_GALERIA = 1;
    Button botaoGaleria;
    private StorageReference storageReference;
    private String identificadorUsuario;
    private List<String> listaFotosRecuperadas = new ArrayList<>();



    //solicitacao de permissao
    private String[] permissoesNecessarias = new String[]{
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE

    };


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

        //configurações iniciais
        storageReference = ConfiguracaoFireBase.getReferenciaStorage();
        identificadorUsuario = UsuarioFirebase.getIdentificadorUsuario();

        //validar as permissoes
        Permissao.validarPermissoes(permissoesNecessarias, this, 1);

        botaoGaleria = findViewById(R.id.botaoParaGaleria);

        //criar evento onclick para que o usuario tenha acesso a galeria clicando no botao
        botaoGaleria.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Intent intent = new Intent();
                intent.setType("image/*");
                intent.putExtra(EXTRA_ALLOW_MULTIPLE, true);
                intent.setAction(ACTION_GET_CONTENT);
                startActivityForResult(Intent.createChooser(intent, "Selecione Imagem"), SELECAO_GALERIA);

            }
        });


    }

    //pegar as  varias foto que o usuario selecionou ok ok ok
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == SELECAO_GALERIA) {
            if (resultCode == TelaverGaleriaActivity.RESULT_OK) {

                if (data.getClipData() != null) {
                    int count = data.getClipData().getItemCount();
                    Log.i("count", String.valueOf(count));
                    int currentItem = 0;
                    while (currentItem < count) {
                        Uri imagemUri = data.getClipData().getItemAt(currentItem).getUri();

                        Log.i("uri", imagemUri.toString());
                        listaFotosRecuperadas.add(String.valueOf(imagemUri));
                        currentItem = currentItem + 1;
                    }
                    Log.i("listsize", String.valueOf(listaFotosRecuperadas.size()));
                } else if (data.getData() != null) {
                    String imagePath = data.getData().getPath();



                } else if (listaFotosRecuperadas.size() != 5){
                    exibirMensagemErro("Selecione pelo menos cinco fotos");

                }
                Uri imagemUri = Uri.fromFile(new File("imagens.jpg"));

                StorageReference firebaseRef = storageReference.child( storageReference +imagemUri.getLastPathSegment());
                StorageTask<UploadTask.TaskSnapshot> uploadTask = firebaseRef.putFile(imagemUri);

                uploadTask.addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception exception) {
                        Toast.makeText(TelaverGaleriaActivity.this, "Erro ao enviar imagens", Toast.LENGTH_SHORT).show();
                        // Handle unsuccessful uploads
                    }
                }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        // taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc.
                        // ...
                        Toast.makeText(TelaverGaleriaActivity.this, "Upload com sucesso", Toast.LENGTH_SHORT).show();

                    }
                });
            }


        }

    }

    private void exibirMensagemErro(String mensagem) {
        Toast.makeText(this, mensagem, Toast.LENGTH_SHORT).show();
    }

   /* private void salvarImagensFirebase() {
        Uri file = Uri.fromFile(new File("path/to/images/rivers.jpg"));
        StorageReference riversRef = storageReference.child(identificadorUsuario+file.getLastPathSegment());
        StorageTask<UploadTask.TaskSnapshot> uploadTask = riversRef.putFile(file);

        uploadTask.addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception exception) {
                // Handle unsuccessful uploads
            }
        }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                // taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc.
                // ...
            }
        });

    }*/

    //caso permissao foi negada
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        for(int permissaoResultado : grantResults){
            if(permissaoResultado == PackageManager.PERMISSION_DENIED){
                alertaValidacaoPermissao();

            }

        }

    }
     private void alertaValidacaoPermissao(){
         AlertDialog.Builder builder = new AlertDialog.Builder(this );
         builder.setTitle("Permissoes Negadas");
         builder.setMessage("Para utilizar o app é necessario aceitar as permissoes");
         builder.setPositiveButton("Confirmar", new DialogInterface.OnClickListener() {
             @Override
             public void onClick(DialogInterface dialog, int which) {
                 finish();

             }
         });
         AlertDialog dialog = builder.create();
         dialog.show();
     }



    }


Author: neves, 2019-10-16

1 answers

Hello, Luana!

This may not be the best method, but I think it will solve your problem.

First we must realize that to date, the SDK of the Firebase Storage does not support uploading multiple files at once. The solution would be to call multiple times the code responsible for a single upload. The second point that we must pay attention to is to know when all uploads have been finalized. Explained this, we can proceed.

1 - create a class to package some information about the upload itself such as: Uri and a boolean flag indicating the state (up or not).

UploadWrapper.java

public class UploadWrapper {
    private Uri uri;
    private boolean uploaded;

    public UploadWrapper(Uri uri) {
        this.uri = uri;
    }

    /* Getters e setters desnecessários omitidos */

    public Uri getUri() {
        return uri;
    }

    public void setUploaded(boolean uploaded) {
        this.uploaded = uploaded;
    }

    public boolean isUploaded() {
        return uploaded;
    }
}

2 - now we have to encapsulate the code responsible for the upload in a method so that we can work in a more modular way, since we will use a loop for the multiple uploads. Make the method receive as parameter the class we created in the step 1.

    public void upload(UploadWrapper wrapper) {
      StorageTask<UploadTask.TaskSnapshot> uploadTask 
= firebaseRef.putFile(wrapper.getUri()); // Isso retorna a Uri da imagem

          uploadTask.addOnFailureListener(new OnFailureListener() {
              @Override
              public void onFailure(@NonNull Exception exception) {
                   // Setar false aqui é irrelevante, pois o valor padrão já é false,
                   // mas server como ilustração de que o upload dessa imagem falhou
                   wrapper.setUploaded(false); 

                   // Agora adicione o wrapper à lista e cheque se o tamanho dela
                   // é igual ao tamanho da lista de uris: se sim, sabemos que
                   //  não há mais nada para upar e já podemos avisar ao 
                   // usuário
                   if (!mFinished.contains(wrapper)) mFinished.add(wrapper);
                   checkUploadFinished();   // Esse método vai checar se tudo já acabou
              })
              .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
              @Override
              public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                   // Repetindo tudo só que dessa vez setando a flag (uploaded)
                   // como true!
                   wrapper.setUploaded(true); 

                   // Verifica se já não foi adicionado à lista
                   if (!mFinished.contains(wrapper)) mFinished.add(wrapper);
                   checkUploadFinished();   // Esse método vai checar se tudo já acabou       
              }
           });
    }

3 - we need to now create a method that checks which images have been uploaded or not.

public void checkUploadFinished() {
   if (listaFotosRecuperadas.size() == mFinished.size()) {
        // Pronto! Todos os uploads foram concluídos e você
        // pode verificar quem teve sucesso ou falha na lista mFinished
        for(UploadWrapper wrapper : mFinished) {         
           if (wrapper.isUploaded) {               // Mas isso é opcional, você pode só mostrar um Toast
               // Foi upado com sucesso!
           }
        }

       // E não esqueça de esvaziar as listas depois que tudo acabar
       listaFotosRecuperadas.clear();
       mFinished.clear();  
    }
}

4 - finally, create a loop to mount the wrappers and call the upload method multiple times.

for (String s : listaFotosRecuperadas) {
    upload(new Wrapper(Uri.parse(s)));
}

Oh, I was simmering, about the location of the images: do as follows

StorageReference firebaseRef = storageReference.child("galleries/" + mUserKey);

Thus Firebase Storage will generate a directory schema in this way

   galleries/{id_do_usuario}/imagem_1.jpg
    .
    .
    .
    galleries/{id_do_usuario}/imagem_n.jpg   // n imagens

And if the directory does not exist, it will be created automatically. Don't worry about it.

Warning that I have not tested this code so I do not know if in practice everything will occur as expected. Anyway, that's the way. I hope this helps!

 2
Author: Ivan Silva, 2019-10-16 19:36:44