0

My codes are to:

  • Select a local Mp3 Uri
  • Upload it to Firebase
  • then retrieve that mp3 metadata such as name, artist, album cover,...
  • Upload the album cover to Firebase
  • Create a new object in the Firebase Realtime Database including the mp3 and cover download links, the name, and artist.

I have a Create the String

Then inside the mp3 upload onSucess() I retrieve the metadatas and upload the mp3 album cover: Uploading the album cover and assign the downloadLink to the str created above.

Finally create a song object and push it to he Realtime db: push song object to db

but the str is = "". And the result on the db is like this db result

I have checked inside the onSucess() in the 2nd img, the str is = the downloadLink but when moved to the 3rd img it = "" again.

I have tried static, non-static, local variable, etc for the str but no use.

Here is the full code

private static String str = "";

private void uploadFile() {
    if (!filename.getText().toString().equals("") && imgView != null) {
        StorageReference mp3ref = mp3StorageRef.child(SongName.getText().toString().trim() + "_" + System.currentTimeMillis() + "." + getFileExtension(Mp3_uri));

        mp3ref.putFile(Mp3_uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        progressBar.setProgress(0);
                    }

                }, 500);

                MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
                mediaMetadataRetriever.setDataSource(getContext(), Mp3_uri);

                String name = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
                String artist = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
                byte[] art = mediaMetadataRetriever.getEmbeddedPicture();


                StorageReference cover = coverStorageRef.child("cover_" + name + "_" + System.currentTimeMillis() + ".jpg");
                cover.putBytes(art).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        Task<Uri> urlTask = taskSnapshot.getStorage().getDownloadUrl();
                        while (!urlTask.isSuccessful()) ;
                        Uri downloadUrl = urlTask.getResult();
                        str =  (downloadUrl.toString());
                    }
                });



                Task<Uri> urlTask = taskSnapshot.getStorage().getDownloadUrl();
                while (!urlTask.isSuccessful()) ;
                Uri downloadUrl = urlTask.getResult();
                Song song = new Song(name, artist, str, downloadUrl.toString());

                String uploadId = databaseReference.push().getKey();
                databaseReference.child(uploadId).setValue(song);
                Toast.makeText(getContext(), "Upload Success", Toast.LENGTH_SHORT).show();
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Toast.makeText(getContext(), "Upload Failed", Toast.LENGTH_SHORT).show();
            }
        }).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onProgress(@NonNull UploadTask.TaskSnapshot snapshot) {
                double Progress = (100.0 * snapshot.getBytesTransferred() / snapshot.getTotalByteCount());
                progressBar.setProgress((int) Progress);
            }
        });
    } else {
        Toast.makeText(getContext(), "No File Selected", Toast.LENGTH_SHORT).show();
    }
}

A way to upload 2 files (mp3 and jpg) and retrieve both files download Links.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Kaiser
  • 1
  • 1
  • I think what happen here. your str="" that called database and save into database, but str initialize after some millisecond of insert database. – Urvish Shiroya Apr 16 '23 at 06:45
  • [Please do not upload images of code/data/errors.](//meta.stackoverflow.com/q/285551/1772220) – ugexe Apr 16 '23 at 17:13
  • Aside from my answer, if you understand Kotlin, I think that this [resource](https://medium.com/firebase-tips-tricks/how-to-upload-an-image-to-cloud-storage-and-save-the-url-in-firestore-42711ca1df46) will help. Here is the corresponding [repo](https://github.com/alexmamo/CloudStorageJetpackCompose). – Alex Mamo Apr 18 '23 at 07:23

1 Answers1

0

All Firebase operations are asynchronous and the solution is always the same. Any code that needs to process data as a result of an asynchronous operation, should be placed inside the onSuccess method or be called from there. So in your case, you have to move all the code from the inner onSuccess right inside the outer onSuccess.

private static String str = "";

private void uploadFile() {
    if (!filename.getText().toString().equals("") && imgView != null) {
        StorageReference mp3ref = mp3StorageRef.child(SongName.getText().toString().trim() + "_" + System.currentTimeMillis() + "." + getFileExtension(Mp3_uri));

        mp3ref.putFile(Mp3_uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        progressBar.setProgress(0);
                    }

                }, 500);

                MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
                mediaMetadataRetriever.setDataSource(getContext(), Mp3_uri);

                String name = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
                String artist = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
                byte[] art = mediaMetadataRetriever.getEmbeddedPicture();


                StorageReference cover = coverStorageRef.child("cover_" + name + "_" + System.currentTimeMillis() + ".jpg");
                cover.putBytes(art).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        Task<Uri> urlTask = taskSnapshot.getStorage().getDownloadUrl();
                        while (!urlTask.isSuccessful()) ;
                        Uri downloadUrl = urlTask.getResult();
                        str =  (downloadUrl.toString());

                        //
                        Task<Uri> urlTask = taskSnapshot.getStorage().getDownloadUrl();
                        while (!urlTask.isSuccessful()) ;
                        Uri downloadUrl = urlTask.getResult();
                        Song song = new Song(name, artist, str, downloadUrl.toString());

                        String uploadId = databaseReference.push().getKey();
                        databaseReference.child(uploadId).setValue(song);
                        Toast.makeText(getContext(), "Upload Success", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Toast.makeText(getContext(), "Upload Failed", Toast.LENGTH_SHORT).show();
            }
        }).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onProgress(@NonNull UploadTask.TaskSnapshot snapshot) {
                double Progress = (100.0 * snapshot.getBytesTransferred() / snapshot.getTotalByteCount());
                progressBar.setProgress((int) Progress);
            }
        });
    } else {
        Toast.makeText(getContext(), "No File Selected", Toast.LENGTH_SHORT).show();
    }
}

If you need to use the result of an async operation outside the onComplete, then I recommend you check my answer from the following post:

It's true that the answer refers to a read operation, but the exact same rules apply in your case.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193