I'am using Firebase Storage to get a list of images on Android, but every time when the App is started this list is downloaded, I want store persistence on Android the images and download only if is necessary. So I need to check if the images that will downloaded already are on the smartphone. I'am using the FirebaseDatabase to store the name of the files, for the Database I can check the persistence. I think need store images on the storage of device, but I don't know to check before download, so the best way is set persistence FirebaseStorage if possible.
My code looks like this:
FirebaseDatabase:
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference databaseReference = database.getReference().child("nomes_imagens");
final Map<String,Object> mapNomesImagens = new HashMap<>();
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.i(TAG,"onDataChanged()");
Iterator<DataSnapshot> iterator = dataSnapshot.getChildren().iterator();
while( iterator.hasNext() ) {
DataSnapshot snapshot = iterator.next();
mapNomesImagens.put(snapshot.getKey(),snapshot.getValue());
n1++;
}
makeList(mapNomesImagens);
Log.i(TAG,"Mapa: " + mapNomesImagens.toString());
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.i(TAG,"onCancelled");
}
});
FirebaseStorage:
public boolean makeList(Map<String,Object> map) {
final FirebaseStorage storage = FirebaseStorage.getInstance();
try {
Set<String> set = map.keySet();
for(final String nomeExercicio : set) {
String nomeArquivo = String.valueOf(map.get(nomeExercicio));
final File localFile = File.createTempFile("ImagensExercicios","bmp");
storage.getReference().child("ImagensExercicios").child(nomeArquivo).getFile(localFile).
addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
Log.i(TAG,"onSuccess()");
Bitmap bitmap;
bitmap = BitmapFactory.decodeFile(localFile.getAbsolutePath());
Exercicio exercicio = new Exercicio(nomeExercicio,bitmap);
exercicios.add(exercicio);
n++;
}
}).
addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.i(TAG,"onFailure() " + e.getMessage());
}
}).
addOnCompleteListener(new OnCompleteListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<FileDownloadTask.TaskSnapshot> task) {
Log.i(TAG,"onComplete()");
}
}
});
}
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
AFAIK setpersistence enabling is intended for offline data storage. So it will refresh when the internet is available.
You can use Glide library to handle caching. Official firebase usage with Glide given below must be sufficient.
Link: https://github.com/firebase/FirebaseUI-Android/tree/master/storage
To load an image from a StorageReference, simply use the
FirebaseImageLoader class:
// Reference to an image file in Cloud Storage
StorageReference storageReference = ...;
// ImageView in your Activity
ImageView imageView = ...;
// Load the image using Glide
Glide.with(this /* context */)
.using(new FirebaseImageLoader())
.load(storageReference)
.into(imageView);
Send the picture path or URI in the phone, create a room android database, or if you are good with persistence that's ok. Use regular expression or regex to help tally the URI path from firebase to that of the phone path.
If both URI match then the file exists no need to download but if the URI does not match then the file does not exist then a download process is trigger
Remember regular expression or regex
Related
I wanted to add new sub-Collection to a existing document. Should i create new POJO class to add Sub-Collection or any other way to do it. I wanted to add new Sub-Collection to existing document ID.I am new to android and Firestore. Thanks in advance.this is my Database
i tried this method but stuck couldn't succed
private void setNewCategory(String downloadUrl){
FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference newMainCatRef = db
.collection("HomeFeed")
.document("5HEkE0ac7sMa7Gjnvf3E")
.collection("MainCategory")
.document();
itemId = newMainCatRef.getId();
MainCategory category = new MainCategory();
category.setCategory_id(itemId);
category.setCategory_name(category_name.getText().toString());
category.setCategory_url(downloadUrl);
category.setPriority(priority.getValue());
newMainCatRef.set(category).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "onSuccess: Success on Updating the new Field to cat");
FirebaseFirestore NC = FirebaseFirestore.getInstance();
CollectionReference NewCategory = NC
.collection("Categories")
.document("tUdFCajDcQT995jX6G4k")
.collection(category_name.getText().toString());
NewCategory.add()
category_name.setText("");
priority.setValue(0);
category_image.setImageResource(R.drawable.ic_android);
category_progress.setVisibility(View.INVISIBLE);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(mContext, "Failed to add New Catgory Try again!", Toast.LENGTH_SHORT).show();
}
});
}
There is no need to make something special. As I see in your code, you're already using the right reference:
CollectionReference NewCategory = NC
.collection("Categories")
.document("tUdFCajDcQT995jX6G4k")
.collection(category_name.getText().toString());
category_name.getText().toString() being the name of the sub-collection but the problem rises in the following line of code:
NewCategory.add()
Where you aren't passing anything as an argument. You should pass a custom object or a Map in order to be able to write something in the database.
I'm creating a system for storing multiple image links in firestore, and it's been working, I select from the gallery and upload them as List it is in the order that it is going to the bank (firestore ), because it matters to me, I select for example the images 1,2,3, and when I save their link in the firestore it gets 2,1,3 or 3,1, 2 or 3,2,1 never in the order I loaded, it seems to be according to the lightest image, as saved according to the position I loaded? I've been breaking my head with this for a few days.
already to get each image from List.get(i) to save but to no avail.
I'm saving like this in firestore ->
list_img [
0 link_img
1 link_img
2 link_img]
firestore scheme
upload from gallery
GalleryConfig config = new GalleryConfig.Build()
.limitPickPhoto(50)
.singlePhoto(false)
.hintOfPick("this is pick hint")
.filterMimeTypes(new String[]{})
.build();
GalleryActivity.openActivity(Pag_producao_hq.this, reqCode, config);
upload
private void upload_Fotos_selecionadas(Uri uri, final int totalimg, int i) {
Log.i("sdsd77", String.valueOf(i));
final StorageReference ImageFolder = FirebaseStorage.getInstance().getReference().child("imagens");
String nomeImagem = UUID.randomUUID().toString();
final StorageReference imagename = ImageFolder
.child("HQ")
.child(identificadorUsuario)
.child(nomeImagem);
arrayListImageRef.add(ImageFolder); //arraylist of type StorageRef
arrayListImageRef.add(imagename);
imagename.putFile(uri)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
imagename.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
String urlConvertida = uri.toString();
lista_url.add(urlConvertida);
if(lista_url.size()==totalimg){
Map<String, Object> new_imagens = new HashMap<>();
new_imagens.put("list_img", lista_url);
db.collection("HQ")
.document(getId())
.collection("Imagens")
.add(new_imagens);
dialog.dismiss();
finish();
}
}
});
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
if (!isFinishing()) {
dialog.dismiss();
}
Toast.makeText(getApplicationContext(), exception.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
Cloud Firestore does not list document as the same order of insertion. Auto IDs are not time related. You will need to add a timestamp field and query your data using order by this field.
How can I retrieve an image that I uploaded on Firebase Storage to an ImageView? I already uploaded an ImageView from my pc to storage, now I need to retrieve it to an ImageView inside my app. How can I do that?
That's how I was trying to do.
db.collection("Ads").document("Ads1").addSnapshotListener(new EventListener<DocumentSnapshot>() {
#Override
public void onEvent(#Nullable DocumentSnapshot documentSnapshot, #Nullable FirebaseFirestoreException e) {
String titulo = documentSnapshot.getString("titulo");
String subtitulo = documentSnapshot.getString("subtitulo");
String imagem1 = documentSnapshot.getString("imagem1");
textViewAdsTitulo.setText(titulo);
textViewAdsSub.setText(subtitulo);
imageView1.setImageURI();//Can't get i as string;
Use picasso
First add implementation 'com.squareup.picasso:picasso:2.71828 in the build.gradle> dependencies
Then use Picasso.get().load(your_url).into(your_imageView)
Hello I am trying to upload multiple images, wait for them to return, compile the download uri's into an object and send it back to my activity. I am using this as reference for upload, firebase. So far i have this
private void saveStepWithImages(#NonNull Step step, Callback callback){
if(step.getStepId() == null){
Collection<Image> images = step.getImages().values();
List<Task<Uri>> taskArrayList= new ArrayList<>();
for (Image i: images) {
taskArrayList.add(uploadImageTask(new ImageUtils().StringToBitMap(i.getImageUrl()), i.getImageReference()));
}
Tasks.whenAll(taskArrayList).addOnCompleteListener(task -> {
Uri downloadUri = task.getResult(); // throws an error because task.getResult is void
});
}else{
updateStepInFirebase(step, callback);
}
}
and in my upload images
private Task<Uri> uploadImageTask(final Bitmap bitmap, String prepend){
final StorageReference ref = mStorageRef.child( prepend );
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] data = baos.toByteArray();
UploadTask uploadTask = ref.putBytes(data);
bitmap.recycle();
return uploadTask.continueWithTask(task -> {
bitmap.recycle();
return ref.getDownloadUrl();
});
}
Step is a custom object i created it contains a Map of images with a string as the key and the value being an image. My image class looks like this
public class Image implements Parcelable {
private String imageUrl;
private String imageReference;
public void Image(){
}
//Setters and getters here;
}
Any suggestions would be really appreciated. Thanks!
The key for solving this problem is to use Tasks's whenAllSuccess() method:
Returns a Task with a list of Task results that completes successfully when all of the specified Tasks complete successfully.
Insted of Tasks's whenAll() method:
Returns a Task that completes successfully when all of the specified Tasks complete successfully.
Please see more informations about Tasks class.
You can upload multiple files to firebase by nesting all the calls in one array, and adding each call to the Task API of firebase:
Define the reference and an array of tasks
StorageReference mStorageRef = FirebaseStorage.getInstance().getReference();
List<Task> myTasks = new ArrayList<>();
In this example im using a map that contains each file an its corresponding storage destination
for (Map.Entry<String, Attachment> entry : storageRouteMap.entrySet()) {
String path = entry.getKey();
final Attachment localAtt = entry.getValue();
Uri fileUri = localAtt.getMyUri();
I will put each task in the array of tasks, for a file i have three tasks, one for uploading the file, one for getting the url of the storage and one for writing the metadata in the real time database.
final StorageReference ref = mStorageRef.child(path);
ThreadPerTaskExecutor executor = new ThreadPerTaskExecutor();
UploadTask t1 = ref.putFile(fileUri);
myTasks.add(t1);
Task<Uri> t2 = t1.continueWithTask(executor,new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
#Override
public Task<Uri> then(#NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
if (!task.isSuccessful()) {
throw task.getException();
}
return ref.getDownloadUrl();
}
});
myTasks.add(t2);
Task<Void> t3 = t2.continueWithTask(executor,new Continuation<Uri, Task<Void>>() {
#Override
public Task<Void> then(#NonNull Task<Uri> task) throws Exception {
if (!task.isSuccessful()) {
throw task.getException();
}
Attachment uploadAtt = new Attachment();
uploadAtt.name = localAtt.name;
uploadAtt.url = task.getResult().toString();
uploadAtt.type = localAtt.type;
String idAtt = UtilFirebase.getAttachmentReference().push().getKey();
UtilLog.LogToConsole(TAG," => "+postId+" => "+uidAuthor+" =>"+idAtt);
return UtilFirebase.getAttachmentReference()
.child(postId)
.child(uidAuthor)
.child(idAtt)
.setValue(uploadAtt);
}
}).continueWith(executor,new VideoTransaction(communityId,localAtt.size,localAtt.type));
myTasks.add(t3);
}
Finally i will see if all the tasks where completed or if there was an error, either way this will communicate the result to the main thread.
Task finish = Tasks.whenAll((Collection) myTasks);
finish.addOnCompleteListener(new ThreadPerTaskExecutor(), new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
if (task.isSuccessful()) {
callback.onComplete();
} else {
callback.onError(task.getException().toString());
}
}
});
customApp= new FirebaseApp(getApplicationContext(),"My News",<to be filled>);
storage = FirebaseStorage.getInstance(customApp);
I'm new to firebase and what is the exact use of the custom App.
I want to create a custom app to upload large files to google cloud storage using firebase. is that custom app recommended for me?
No need to use customApp;
Simply we can use
storage = FirebaseStorage.getInstance("gs://<Google cloud storage bucket name>");
If we want storage references then
mStorageRef = storage.getReferenceFromUrl("gs://<Google cloud storage bucket name>");
#Override
public void onCreate() {
super.onCreate();
FirebaseOptions options = new FirebaseOptions.Builder()
.setApiKey("AI...3LnY")
.setStorageBucket("gs://f...t")
.setApplicationId("1:356....:android:f......232")
.build();
customApp = FirebaseApp.initializeApp(getApplicationContext(),options,"MyApp");
//storage
storage = FirebaseStorage.getInstance(customApp);`enter code here`
}
If you're new to Firebase, chances are you don't need a custom FirebaseApp. Instead, just use FirebaseStorage.getInstance().getReference() as shown in the Firebase Storage documentation.
Great answer Mr. Frank van Puffelen.
It's working for me (imported bucket from Google Cloud Storage.)
mStorageRef = FirebaseStorage.getInstance("gs://c......s").getReference();
Download the file from google cloud storage to a local device using firebase.
final StorageReference downloadRef;
downloadRef = mStorageRef.getRoot().child(downloadPath);
try {
File output = new File(Environment.getExternalStorageDirectory() + File.separator + Config.MY_VIDEOS_PATH);
if (!output.exists()) {
output.mkdir();
}
localFile = new File(output, downloadId);
} catch (Exception e) {
e.printStackTrace();
}
// Download and get total bytes
downloadRef.getFile(localFile)
.addOnProgressListener(new OnProgressListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onProgress(FileDownloadTask.TaskSnapshot taskSnapshot) {
showProgressNotification(title, "",
taskSnapshot.getBytesTransferred(),
taskSnapshot.getTotalByteCount());
}
})
.addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
Log.d(TAG, "download:SUCCESS");
// Send success broadcast with number of bytes downloaded
broadcastDownloadFinished(downloadPath, taskSnapshot.getTotalByteCount());
showDownloadFinishedNotification(downloadPath, (int) taskSnapshot.getTotalByteCount());
// Mark task completed
taskCompleted();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Log.w(TAG, "download:FAILURE", exception);
Log.w(TAG, "download:FAILURE", exception.getCause());
// Send failure broadcast
broadcastDownloadFinished(downloadPath, -1);
showDownloadFinishedNotification(downloadPath, -1);
// Mark task completed
taskCompleted();
}
});