Android : download files list from Firebase storage - android

I uploaded a file list to Firebase that I want to download using my app.
List<String> childsRef = new ArrayList<>();
childsRef.add("xxxx/img1");
childsRef.add("xxxx/img2");
... etc
Then, through this list, I try to download files using my Firebase storageReference :
for (String child : childsRef) {
islandRef = storageRef.child(child);
File localFile = File.createTempFile("images", "jpg");
islandRef.getFile(localFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
// Local temp file has been created
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle any errors
}
});
}
The download process is async, so I can't show pop-ups to visualize downloading progression... I want to navigate to next Activity only if all of pending downloads are done..
Do you have any ideas/help?
--EDIT
Solution :
FirebaseStorage instance = FirebaseStorage.getInstance();
StorageReference referenceFromUrl = instance.getReferenceFromUrl("gs://xxxxxxx.appspot.com/");
for (final String aur : aurl) {
final File localFile = new File(PATH + aur.substring(aur.lastIndexOf("/") + 1, aur.lastIndexOf(".")) + ".dat");
StorageReference f = referenceFromUrl.child(aur);
FileDownloadTask task = f.getFile(localFile);
task.addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
size += localFile.length();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Log.e("firebase ", ";local tem file not created created " + exception.toString());
}
});
while (!task.isComplete()) {
}
publishProgress("" + (int) ((float) i++ * 100 / aurl.length));
}

getFile returns a FileDownloadTask object, which is a subclass of Task. As you probably know, this Task tracks the progress of the download. You have the option of kicking off all the downloads at once, collecting all the Tasks in a list, then using Tasks.whenAll() to get a new Task that completes when all the downloads are complete.
I have a four part blog series about using Tasks that might help you better understand how they work.

make childsRef hashmap and add a boolean to see if download is completed.
set value true when onSuccess and make a handler to send message when a download completed to check if all boolean values true. than start your activity from handler.

Related

Can't get actual download Url of an image uploaded in firebase storage [duplicate]

This question already has answers here:
How to get URL from Firebase Storage getDownloadURL
(13 answers)
Closed 2 years ago.
I'm trying to get the download url of the image uploaded to firebase database. But Task Uri imageURL = storageReference.getDownloadUrl(); doesn't gives the actual download URL of an image stored in the firebase storage i.e it gives this - com.google.android.gms.tasks.zzu#27da5837
getdownloadUrl() doesn't work in case of as it is deprecated:
Uri imageUrl = storagereference.getdownloadUrl(); //Gives error
please see the code here:
final StorageReference storageReference = FirebaseStorage.getInstance().getReference().child("images").child(imageName);
final UploadTask uploadTask = storageReference.putBytes(data);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle unsuccessful uploads
Toast.makeText(CreateSnapActivity.this, "Upload Failed", Toast.LENGTH_SHORT).show();
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(final UploadTask.TaskSnapshot taskSnapshot) {
// taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc.
//Task<Uri> imageURL = storageReference.getDownloadUrl();
//Log.i("URL", imageURL.toString()); // gives this url - com.google.android.gms.tasks.zzu#27da5837 which is not correct
Task<Uri> urlTask = storageReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Log.i("Url", String.valueOf(uri));
imageUrl = uri.toString(); //Gives the correct url but it cannot store this uri value outside this function i.e for Intent shown below outside this func.
}
});
Toast.makeText(CreateSnapActivity.this, "Uploaded", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(CreateSnapActivity.this, ChooseUserActivity.class);
intent.putExtra("imageName", imageName);
intent.putExtra("imageURL", imageUrl);
intent.putExtra("message", captionEditText.getText().toString());
startActivity(intent);
}
});
Calling getDownloadUrl() starts an asynchronous operation, which may take some time to complete. Because of this, your main code continues to run while the download URL is being retrieved to prevent blocking the user. Then when the download URL is available, your onSuccess gets called. Because of this, by the time your intent.putExtra("imageURL", imageUrl) now runs, the imageUrl = uri.toString() hasn't run yet.
To see that this indeed true, I recommend putting some logging in the code to just show the flow, or running it in a debugger and setting breakpoints on the lines I indicated above.
To fix it, any code that needs the download URL, needs to be inside the onSuccess, or be called from there. This applies not just here, but to all code that runs asynchronously, which includes most modern cloud APIs. So I recommend spending some time now studying this behavior, so that you're more comfortable with it going forward.
In your code:
final StorageReference storageReference = FirebaseStorage.getInstance().getReference().child("images").child(imageName);
final UploadTask uploadTask = storageReference.putBytes(data);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Toast.makeText(CreateSnapActivity.this, "Upload Failed", Toast.LENGTH_SHORT).show();
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(final UploadTask.TaskSnapshot taskSnapshot) {
Task<Uri> urlTask = storageReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
imageUrl = uri.toString();
Toast.makeText(CreateSnapActivity.this, "Uploaded", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(CreateSnapActivity.this, ChooseUserActivity.class);
intent.putExtra("imageName", imageName);
intent.putExtra("imageURL", imageUrl);
intent.putExtra("message", captionEditText.getText().toString());
startActivity(intent);
}
});
}
});
Also see:
URL generated by Firebase Storage does not allow access to the file
How to get download url for firebase storage and update firestore document?
imageURL is a task.You are trying to print a task. not task's result. please try this code:
Task<Uri> imageURL = storageReference.getDownloadUrl();
Log.i("URL", imageURL.toString());
Log.i("URL", imageURL.result.toString());

how do I upload multiple files to firebase databse in order as in arraylist?

I'm trying to add multiple images to firebase, but it seems like it doesn't upload in order. I believe myUrlList gets added depending on the order of getting uploaded to the server. Is there any way I can sort myUrlsList same as imageUrlList?
for(int i=0; i< imageUriList.size(); i++){
final StorageReference filereference = storageReference.child(System.currentTimeMillis()
+ "." + getFileExtension(imageUriList.get(i)));
uploadTask = filereference.putFile(imageUriList.get(i));
uploadTask.continueWithTask(new Continuation() {
#Override
public Object then(#NonNull Task task) throws Exception {
if(!task.isSuccessful()){
throw task.getException();
}
return filereference.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if(task.isSuccessful()){
Uri downloadUri = task.getResult();
myUrl = downloadUri.toString();
myUrlList.add(myUrl);
Even if you are using a loop and theoretically, the upload of the images should be in the order of the iteration, you cannot know how much it will take to actually upload each image to the Firebase Storage separately. As #DougStevenson mentioned in his comment, you are uploading everything in "parallel". So an image of a smaller size can be uploaded much faster than an image of a bigger size, even if the smaller image is positioned right after the larger image, as it will take a smaller amount of time to be uploaded.
The solution to solve this issue is to wait until an image is uploaded and start the next upload, right after the upload of the previous image completes. This is typically done with recursion, with a method that invokes itself.
private void uploadImageToFirebaseStorage() {
if (imageUriList.size() > 0) {
Uri imageUri = imageUriList.get(0);
StorageReference filereference = storageReference.child(System.currentTimeMillis()
+ "." + getFileExtension(imageUri));
imageUriList.remove(0);
uploadTask = filereference.putFile(imageUri);
uploadTask.continueWithTask(new Continuation() {
#Override
public Object then(#NonNull Task task) throws Exception {
if(!task.isSuccessful()){
throw task.getException();
}
return filereference.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if (task.isSuccessful()) {
Uri downloadUri = task.getResult();
myUrl = downloadUri.toString();
myUrlList.add(myUrl);
uploadBeerImageToFirebaseStorage(); //Call when completes
}
}
});
}
}
First, kick it off with uploadImageToFirebaseStorage(). Once an image is uploaded, the method will check if there's more work that should be done, and reinvokes itself if that's the case.
get the name from arraylist create new handler and execute runnable, Now every time when upload execute it create new runnable for different file and then upload file as your requirement.

How can we auto-generate a new folder for every new user of our android app on Firebase Storage?

Currently, data of all the users who are using my Android app is going to a single folder on Firebase Storage. But I want to auto-create a new folder for every new device. Means, the data of "harry's device" will be uploaded to "Harry Folder" on storage of Firebase. And the data of "Jane's device" will be auto uploaded to "Jane Folder".
Note: I want the auto-creation of folders on Firebase Storage.
Don't use names, use UID of users as it is unique.
Whenever uploading data to firebase use this:
private void uploadMethod() {
progressDialog();
StorageReference storageReferenceProfilePic = firebaseStorage.getReference();
StorageReference imageRef = storageReferenceProfilePic.child(firebaseUser.getUid() + "/" + "image" + ".jpg");
imageRef.putFile(profilePicUri)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
//if the upload is successful
//hiding the progress dialog
//and displaying a success toast
dismissDialog();
profilePicUrl = taskSnapshot.getDownloadUrl().toString();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
//if the upload is not successful
//hiding the progress dialog
dismissDialog();
//and displaying error message
Toast.makeText(getActivity(), exception.getCause().getLocalizedMessage(), Toast.LENGTH_LONG).show();
}
})
.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
#Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
//calculating progress percentage
// double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount();
// //displaying percentage in progress dialog
// progressDialog.setMessage("Uploaded " + ((int) progress) + "%...");
}
});
}
there are no auto create of specific firebase cloud storage location when
a new user registers to your app. but you can achieve this manually by naming your folder base on user id.

How to get all files from firebase storage?

I have uploaded some files into Firebase directory and I want to list them and download one by one.There is no API/Documentation fo this.Could you help me ?
As of July 2019, version 18.1.0 of the Cloud Storage SDK now supports listing all objects from a bucket. You simply need to call listAll() in a StorageReference:
StorageReference storageRef = FirebaseStorage.getInstance().getReference();
// Now we get the references of these images
storageRef.listAll().addOnSuccessListener(new OnSuccessListener<ListResult>() {
#Override
public void onSuccess(ListResult result) {
for(StorageReference fileRef : result.getItems()) {
// TODO: Download the file using its reference (fileRef)
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception exception) {
// Handle any errors
}
});
If you want to download these files, you can use one of the options shown in the Docs.
Please note that in order to use this method, you must opt-in to version 2 of Security Rules, which can be done by making rules_version = '2'; the first line of your security rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
first , you should get the file download Url to retrieve it, the easiest way is to upload a file and generate the download Url in your database, so after that you just go and retrieve each file from the storage like this :
private void downloadFile() {
FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference storageRef = storage.getReferenceFromUrl("<your_bucket>");
StorageReference islandRef = storageRef.child("file.txt");
File rootPath = new File(Environment.getExternalStorageDirectory(), "file_name");
if(!rootPath.exists()) {
rootPath.mkdirs();
}
final File localFile = new File(rootPath,"imageName.txt");
islandRef.getFile(localFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
Log.e("firebase ",";local tem file created created " +localFile.toString());
// updateDb(timestamp,localFile.toString(),position);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Log.e("firebase ",";local tem file not created created " +exception.toString());
}
});
}
I personally use this method, whenever you upload a file, save its download URL in your Firebase Database, if you are uploading multiple files then save it in an array. There is no method for Firebase Storage android to download and upload multiple files in one go.
Whenever you want to download files access your firebase database for those URL's.

Download and parse XML file from Firebase

I am creating an Android app which downloads images and XML file from Firebase.
The code for downloading image works fine
FirebaseStorage storage = FirebaseStorage.getInstance();
gsReference = storage.getReferenceFromUrl("gs:...../sample.png");
Glide.with(this)
.using(new FirebaseImageLoader())
.load(gsReference)
.into((ImageView) questionImageSwitcher.getCurrentView());
But I can't retrieve the XML file and read it.
You can get a file from Firebase in that way:
StorageReference firebaseStorageRef = FirebaseStorage.getInstance().getReference(FILE_NAME);
File destinationFile = new File(getFilesDir() + "/" + FILE_NAME);
firebaseStorageRef.getFile(destinationFile)
.addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
// File downloaded successfully, do your stuff here using destinationFile variable
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Something went wrong
}
});
and do whatever you want with it.
FILE_NAME is the file's name hosted on Firebase

Categories

Resources