Upload images according to position no firebase - android

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.

Related

Add more field in a document without overwrite in Firebase Cloud Firestore

I wish to add fields in my firebase without overwriting it.
As you can see below, the user for my app will screen their emotions and the emotion will be uploaded to firebase.
Actually, user will be screened many times and each time they will get different emotions or same emotions.
Lets say the user screened their face and get Happiness, Sadness, Happiness respectively.
I wish to have my fields in the firebase console like this:
FaceEmotion: Happiness
FaceEmotion: Sadness
FaceEmotion: Happiness
Using my code below, at this moment I only get to overwrite the (FaceEmotion:) with same emotion values but not adding values as I wish like above. I've tried using array but I guess the problem is because the fieldname "FaceEmotion" is the same.
Is there a way for me to let Firestore generate autoID for the fieldname "FaceEmotion"? like maybe to have something like this:
FaceEmotion1: Happiness
FaceEmotion2: Sadness
FaceEmotion3: Happiness
String Emotion = EmotionType.toString();
userID = fAuth.getCurrentUser().getUid();
FaceEmotion = "FaceEmotion";
Map<String,Object> user = new HashMap<>();
user.put("FaceEmotion",Emotion);
DocumentReference documentReference = fStore.collection("users").document(userID).collection("FaceEmotion").document(FaceEmotion);
documentReference.update("FaceEmotion",FieldValue.arrayUnion(user)).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "onSuccess: Data has been saved "+ userID);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "onFailure: " + e.toString());
}
});
The issue is on how you are writing to the document, the solution is to create a new document for every new emoton, this way you will be able to add emotions to that collection.
The code to write the emotions with this modification would be something like:
String emotion = EmotionType.toString();
userID = fAuth.getCurrentUser().getUid();
faceEmotion = "FaceEmotion";
Map<String,Object> val = new HashMap<>();
val.put("FaceEmotion",emotion);
DocumentReference documentReference = fStore.collection("users").document(userID).collection("FaceEmotion").document();
documentReference.set(val).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "onSuccess: Data has been saved "+ userID);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "onFailure: " + e.toString());
}
});

How to add a new Sub- Collection in a Firestore document Android

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.

Upload Multiple images and wait for completion before returning, android and firebase

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());
}
}
});

How to set persistence in Firebase Storage on Android?

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

Firebase custom application setup

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();
}
});

Categories

Resources