Android / Firebase , get timestamp to date - java

İ'm developing chat app with android studio / java and using firebase , i'm getting an error while getting server timestamps.
MY SEND FUNCTİON
public void send(View v) {
if (!status) {
String message = text.getText().toString();
String senderUID = firebaseAuth.getCurrentUser().getUid();
HashMap<String, Object> postData = new HashMap<>();
postData.put("senderID", senderUID);
postData.put("time",FieldValue.serverTimestamp());
postData.put("message", message);
firebaseFirestore.collection("chats").document(id).collection("messages").document()
.set(postData)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
text.setText("");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(chat.this, "Sunucu Hatası...", Toast.LENGTH_LONG).show();
finish();
}
});
}
}
MY GET FUNCTİON
public void dataRead(String id) {
CollectionReference docRef = firebaseFirestore.collection("chats").document(id).collection("messages");
docRef.orderBy("time", Query.Direction.DESCENDING)
.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot queryDocumentSnapshots, #Nullable FirebaseFirestoreException e) {
if (e != null) {
System.err.println("Listen failed: " + e);
return;
}
if (queryDocumentSnapshots != null) {
messageFb.clear();
dateFb.clear();
dateFb.clear();
for (DocumentSnapshot snapshot : queryDocumentSnapshots.getDocuments()) {
Map<String, Object> data = snapshot.getData();
String message = (String) data.get("message");
String sender = (String) data.get("senderID");
Timestamp timestamp = (Timestamp) data.get("time");
messageFb.add(message);
senderFb.add(sender);
dateFb.add(timestamp.toDate().toString().substring(11,16)); //ERROR İS HERE
chatRecycler.notifyDataSetChanged();
}
}
}
});
}
THERE İS THE SMAPLE ERROR java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.Date com.google.firebase.Timestamp.toDate()' on a null object reference
When i send a any message in my app , the app is crashing , but when i open again , everythings works fine , just crashing when i send and get new data. ANY İDEAS ?

Related

Disorganized Chat messages in my Chat App using Firebase

I recently added a feature to send images too along with the option to send text messages. Everything was working fine before that - messages popped as expected queried by descending time. But after I added this image sending feature whenever I scroll up or down the chat the messages get all jumbled up and I don't know why.
When I send only text:
Before Scrolling https://i.stack.imgur.com/2NMVHl.jpg
After Scrolling https://i.stack.imgur.com/2Nxpc.jpg (same)
When I send Image with text
Before Scrolling https://i.stack.imgur.com/rS6Mx.jpg
After Scrolling https://i.stack.imgur.com/OP5DK.jpg
In my code there are two places from where message(image or text) can be uploaded.
For sending Image message:
Briefings - Here I upload the image to the Storage and then retrieve its URL. Then I store the URL to firestore in form of string (which I later use to download the image using Picasso) along with other message details.
final Long currentTime = System.currentTimeMillis();
final String time = currentTime + "";
final StorageReference fileref = storageReference.child("Image Messages")
.child(uid + time);
StorageTask uploadTask = fileref.putFile(uri);
uploadTask.continueWithTask(new Continuation() {
#Override
public Object then(#NonNull Task task) throws Exception {
if(!task.isSuccessful()){
throw task.getException();
}
return fileref.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if(task.isSuccessful()){
Uri downloadUrl = task.getResult();
String myUrl = downloadUrl.toString();
Map<String, Object> chat = new HashMap<>();
chat.put("message", myUrl);
chat.put("time", currentTime);
chat.put("sender", mUser.getUid());
chat.put("groupId",Gid);
chat.put("type","image");
chat.put("username",preferences.getData("username"));
chat.put("name",preferences.getData("usernameAdded"));
firestore.collection("aGroups").document(Gid).collection("Chat")
.add(chat).addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
showChatMessages();
dialog.dismiss();
Toast.makeText(getApplicationContext(),"Message Sent", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(getApplicationContext(),"Error", Toast.LENGTH_SHORT).show();
}
});
}
}
});
For sending text message
Briefings - Here I upload the message and it's details
Map<String, Object> chat = new HashMap<>();
chat.put("message", message.getText().toString());
chat.put("time", System.currentTimeMillis());
chat.put("sender", mUser.getUid());
chat.put("groupId",Gid);
chat.put("type","text");
chat.put("username",preferences.getData("username"));
chat.put("name",preferences.getData("usernameAdded"));
firestore.collection("aGroups").document(Gid).collection("Chat")
.add(chat).addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
Toast.makeText(ChatInterface.this, "Message Sent", Toast.LENGTH_SHORT).show();
showChatMessages();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(getApplicationContext(),"Error", Toast.LENGTH_SHORT).show();
}
});
This is where I add callbacks
private void showChatMessages() {
firestore.collection("aGroups").document(Gid).collection("Chat")
.orderBy("time", Query.Direction.DESCENDING)
.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot value, #Nullable FirebaseFirestoreException error) {
if(error != null){
Log.d("Check", "listen failed: " + error.getMessage());
}
else{
Log.d("Check", "Snapshot worked");
List<ChatModel> list = new ArrayList<>();
list.clear();
for(QueryDocumentSnapshot query : value){
list.add(new ChatModel(
query.getString("groupId")
, query.getId()
, query.getString("message")
, query.getString("sender")
, query.getLong("time")
, query.getString("name")
, query.getString("username")
, query.getString("type")
));
}
recycler_interface.setAdapter(new RealChatRecyclerInterface(mUser.getUid(),list));
}}
});
}
I am adding my whole RealChatRecyclerInterface in this pastebin link.
Use holder.setIsRecyclable(false); in your RealChatRecyclerInterface

My hashmap is not getting implemented in firebase database

I'm using this hashmap to transfer the username from one child(Users) to another(Notes) in database.
In my app you can create as well as update notes.
I want that every time a note is created or updated in the database a username is added along with the note. the username is saved in the users child.
But when the note is created the username doesn't show up. But when the note is updated, it is added in the child.
here is the code:
fAuth = FirebaseAuth.getInstance();
fNotesDatabase = FirebaseDatabase.getInstance().getReference()
.child("Notes").child(fAuth.getCurrentUser().getUid());
UsersRef = FirebaseDatabase.getInstance().getReference().child("Users");
current_user_id = fAuth.getCurrentUser().getUid();
btnCreate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String title = etTitle.getText().toString().trim();
String content = etContent.getText().toString().trim();
if (!TextUtils.isEmpty(title) && !TextUtils.isEmpty(content)) {
createNote(title, content);
putUsername();
} else {
Snackbar.make(view, "Fill empty fields", Snackbar.LENGTH_SHORT).show();
}
}
});
private void putUsername() {
UsersRef.child(current_user_id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String username = snapshot.child("username").getValue().toString();
HashMap usernameMap = new HashMap();
usernameMap.put("username", username);
fNotesDatabase.child(noteID).updateChildren(usernameMap);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
I'm not able to understand as how come the username is added when the note is updated but not when the note us created.
I have updated the second note thats why there is a username but when is simply created the upper one there username is not showing.
EDIT
putData method :
private void putData() {
if (isExist) {
fNotesDatabase.child(noteID).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild("title") && dataSnapshot.hasChild("content")) {
String title = dataSnapshot.child("title").getValue().toString();
String content = dataSnapshot.child("content").getValue().toString();
etTitle.setText(title);
etContent.setText(content);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
createNote method:
private void createNote(String title, String content) {
if (fAuth.getCurrentUser() != null) {
Calendar calFordDate = Calendar.getInstance();
SimpleDateFormat currentDate = new SimpleDateFormat("dd-MMMM-yyyy");
saveCurrentDate = currentDate.format(calFordDate.getTime());
if (isExist) {
Map updateMap = new HashMap();
updateMap.put("title", etTitle.getText().toString().trim());
updateMap.put("content", etContent.getText().toString().trim());
updateMap.put("timestamp", ServerValue.TIMESTAMP);
updateMap.put("date",saveCurrentDate);
fNotesDatabase.child(noteID).updateChildren(updateMap);
SendUsersToPostActivity();
Toast.makeText(this, "Article updated", Toast.LENGTH_SHORT).show();
} else {
final DatabaseReference newNoteRef = fNotesDatabase.push();
final Map noteMap = new HashMap();
noteMap.put("title", title);
noteMap.put("content", content);
noteMap.put("timestamp", ServerValue.TIMESTAMP);
noteMap.put("date",saveCurrentDate);
Thread mainThread = new Thread(new Runnable() {
#Override
public void run() {
newNoteRef.setValue(noteMap).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(NewNoteActivity.this, "Article Created", Toast.LENGTH_SHORT).show();
SendUsersToPostActivity();
} else {
Toast.makeText(NewNoteActivity.this, "ERROR: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
});
mainThread.start();
}
}
}
It's hard to be certain, but I don't see where you set the noteID value that putUsername depends on.
In general though, I'd recommend changing createNote to take all the data that it needs for the new note, including the user name:
btnCreate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String title = etTitle.getText().toString().trim();
String content = etContent.getText().toString().trim();
if (!TextUtils.isEmpty(title) && !TextUtils.isEmpty(content) && fAuth.getCurrentUser() != null) {
UsersRef.child(current_user_id).child("username").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String username = snapshot.getValue(String.class);
createNote(title, content, current_user_id, username);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException()
}
});
} else {
Snackbar.make(view, "Fill empty fields", Snackbar.LENGTH_SHORT).show();
}
}
});
private void createNote(String title, String content, String uid, String username) {
Calendar calFordDate = Calendar.getInstance();
SimpleDateFormat currentDate = new SimpleDateFormat("dd-MMMM-yyyy");
saveCurrentDate = currentDate.format(calFordDate.getTime());
Map updateMap = new HashMap();
updateMap.put("title", title);
updateMap.put("content", content);
updateMap.put("timestamp", ServerValue.TIMESTAMP);
updateMap.put("date",saveCurrentDate);
updateMap.put("uid",uid);
updateMap.put("username",username);
final DatabaseReference noteRef = isExist ? fNotesDatabase.push() : fNotesDatabase.child(noteID);
noteRef.updateChildren(noteMap).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(NewNoteActivity.this, "Article "+(isExists ? "updated" : "created"), Toast.LENGTH_SHORT).show();
SendUsersToPostActivity();
} else {
Toast.makeText(NewNoteActivity.this, "ERROR: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
Some of the changes in this code versus yours:
Looks up the user name before creating the new note. Uses a addListenerForSingleValueEvent for this, to ensure we only do this once for every button click.
Only loads the username child of the user profile, since that's all you use.
Use the values you pass into createNote instead of recalculating them from the UI views.
Only has a single write to the database, as updateChildren works fine for creating the initial data too.
There is no need to run the Firebase setValue call on a new thread, as Firebase runs it off the main thread already.
Please don't leave onCancelled empty, as it may hide important error messages.

Android Firebase How to wait for image upload before registering to database?

I am new to android development and I have an issue.
I have a fragment in which a user can post an announcement and should be able to upload a photo(optional).
When the form is full and the "Post announcement" button is pressed, I trigger the method to save the information to the database.
The only problem I am facing is retrieving the Uri of the newly uploaded photo.
This is the code which extracts the information.
public Map<String, Object> appendDataFromAnnouncementForm(){
String title = titleLineEdit.getText().toString();
String category = categoryLineEdit.getText().toString();
String description = descriptionLineEdit.getText().toString();
String date = dateLineEdit.getText().toString();
String time = timeLineEdit.getText().toString();
String location = locationLineEdit.getText().toString();
//Image upload to firebase + getting the Uri
if(localPhotoUri != null){
uploadImageToFirebase(generatePhotoName(localPhotoUri), localPhotoUri);
}
Map<String, Object> newAnnouncement = new HashMap<>();
//#####################################################
if(uploadedImageUri != null) // <- this is always null
{newAnnouncement.put("imageUri", uploadedImageUri.toString());}
//#############################################################
newAnnouncement.put("title", title);
newAnnouncement.put("category", category);
newAnnouncement.put("description", description);
newAnnouncement.put("date", date);
newAnnouncement.put("time", time);
newAnnouncement.put("location", location);
return newAnnouncement;
}
Below I am posting the code which uploads the photo to Firebase Storage. Since
private void uploadImageToFirebase(String photoName, Uri localContentUri) {
imagesStorageReferance = myStorageReference.child("images/" + photoName);
imagesStorageReferance.putFile(localContentUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
//getUploadedImageUri(referenceToImageFolder);
imagesStorageReferance.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Log.d(TAG, "onSuccess: The download url of the photo is "
+ uri.toString());
uploadedImageUri = uri; /// <- I want to retrieve this
}
});
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "onFailure: Failed uploading the photo to the database " + e.getMessage());
}
});
}
From what I have read on the Internet, this is an synchronization problem(basically, the app registers the information to the database before my photo is uploaded). There are many solutions which I have tried, but I can't really figure it out one to work on my case...
I would be very grateful if you could provide me some explanation on what I should do in order to fix this. How can I wait the photo to be uploaded ?
I am sharing the code from my project:
Assign this globally:
StorageTask uploadTask;
String myUrl = "";
and this is code:
private void uploadImage()
{
if (imageUri != null)
{
final StorageReference reference = storageReference.child(System.currentTimeMillis()+"."+getExtension(imageUri));
uploadTask = reference.putFile(imageUri);
uploadTask.continueWithTask(new Continuation() {
#Override
public Object then(#NonNull Task task) throws Exception {
if (!task.isComplete())
{
throw task.getException();
}
return reference.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if (task.isSuccessful())
{
Uri downloadUri = task.getResult();
myUrl = downloadUri.toString();
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Categories")
.child(randomKey);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("categoryId", randomKey);
hashMap.put("categoryImage", myUrl);
hashMap.put("categoryName", editText.getText().toString());
databaseReference.setValue(hashMap);
save.setVisibility(View.VISIBLE);
startActivity(new Intent(AddCategoryActivity.this, CategoriesActivity.class));
}
else
{
save.setVisibility(View.VISIBLE);
Toast.makeText(AddCategoryActivity.this, "Failed!", Toast.LENGTH_SHORT).show();
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
save.setVisibility(View.VISIBLE);
Toast.makeText(AddCategoryActivity.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
else
{
save.setVisibility(View.VISIBLE);
Toast.makeText(this, "No Image Selected", Toast.LENGTH_SHORT).show();
}
}
Since firebase works asynchronously, the code continues to execute regardless of whether firebase has finished the upload process or not. In your case, the time to run the code following firebase is faster than the upload time to firebase to eventually assign uploadedImageUri = uri; which explains why you are getting a null value for uploadedImageUri present directly after the call for upload.
For this matter, I would suggest you to register to database inside uploadImageToFirebase function after uploadedImageUri = uri; to ensure that uploadedImageUri is never null and always fetched before database registration.
private void uploadImageToFirebase(String photoName, Uri localContentUri) {
imagesStorageReferance = myStorageReference.child("images/" + photoName);
imagesStorageReferance.putFile(localContentUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
//getUploadedImageUri(referenceToImageFolder);
imagesStorageReferance.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Log.d(TAG, "onSuccess: The download url of the photo is "
+ uri.toString());
uploadedImageUri = uri;
String title = titleLineEdit.getText().toString();
String category = categoryLineEdit.getText().toString();
String description = descriptionLineEdit.getText().toString();
String date = dateLineEdit.getText().toString();
String time = timeLineEdit.getText().toString();
String location = locationLineEdit.getText().toString();
Map<String, Object> newAnnouncement = new HashMap<>();
newAnnouncement.put("imageUri", uploadedImageUri.toString());
newAnnouncement.put("title", title);
newAnnouncement.put("category", category);
newAnnouncement.put("description", description);
newAnnouncement.put("date", date);
newAnnouncement.put("time", time);
newAnnouncement.put("location", location);
//UPLOAD newAnouncement TO FIREBASE HERE...
}
});
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "onFailure: Failed uploading the photo to the database " + e.getMessage());
}
});
}

Global variable value assignment remains the same after re-assignment in function (Android Studio)

programmers, I am very new to android studio and java, in this case, I am trying to upload retrieved user info and store them in firebase database. the retrieve process is successful, and the retrieve URL can be seen after logged. However, the String pathToProfile is not assigned with the URL, when I checked the log, it is null. Thanks in advance!
Global declaration:
String pathToProfile;
Map<String, Object> UserInfo = new HashMap<>();
Function to retrieve the download URL
// retrieved URL should be saved in user document
private void retrieveProfileViaURL () {
profileRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
pathToProfile = uri.toString();
UserInfo.put(PROFILE_URL, pathToProfile);
Log.d(TAG, "retrieve profile image successful" + pathToProfile);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Log.d(TAG, "retrieve profile image failure");
// pathToProfile = "uri download unsuccessful";
}
});
}
Function to upload userinformation to firebase
private void uploadUserInfo(String user, String bioInfo) {
// CollectionReference users = db.collection("users");
String UID = getUserID();
retrieveProfileViaURL();
// UserInfo.put(USERID, UID);
UserInfo.put(USERNAME, user);
UserInfo.put(BIO, bioInfo);
mDocRef.collection("users").document(UID).set(UserInfo)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(USER_INFO, "Document has been saved");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(USER_INFO, "Document was not saved!", e);
}
});
}
All data from the Firebase Database is read asynchronously. You can not get values outside the call. That's why your pathToProfile shows null.
For Better approach you can try something like this.
After the user upload the data it will automatically allow user to write in data with url
private void retrieveProfileViaURL () {
profileRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
pathToProfile = uri.toString();
String UID = getUserID();
UserInfo.put(USERNAME, user);
UserInfo.put(BIO, bioInfo);
UserInfo.put(PROFILE_URL, pathToProfile);
mDocRef.collection("users").document(UID).set(UserInfo)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(USER_INFO, "Document has been saved");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(USER_INFO, "Document was not saved!", e);
}
});
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Log.d(TAG, "retrieve profile image failure");
// pathToProfile = "uri download unsuccessful";
}
});
}

Upload to Firebase Storeage wait for upload to complete then upload to Firebase and return task

I am trying to upload a custom object to Firebase Firestore, but the Firestore object should contain a download image url. The idea I have to do this is to upload the image first wait for that to complete, get a reference to the download url, update my custom class, then upload this to Firestore. I would then want to notify my view when this last upload(upload to Firestore) is completed. I was thinking of doing this by returning a task. Here is what I have for upload image:
ref.putFile(file).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
ref.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
//use uri to update object and then upload to firestore
mObject.setImageUri(uri)
uploadToFirestore(myObject);
}
Log.d(TAG, "onSuccess: uri= "+ uri.toString());
}
});
}
});`
I am not sure how to return the final task of Firstore upload as it is done within the task of image upload. My goal is to listen for when the uploadToFireStore() is completed and then inform my view. Any suggestions would be appreciated. Thanks!
Edit: I have structure like so-
View has gets info from user passes it to viewmodel as a custom object. View model then calls db to perform upload.
my idea is to return a task from db to viewmodel which will return said task to view. View checks for completion and then stops loader. Is this a good way to think about this?
My working example.
public class SomeClass {
private String downloadUrl;
private final FirebaseStorage storage = FirebaseStorage.getInstance();
private int count = 0;
public interface Callback {
void callingBack();
void getReady();
}
public int getCount() {
return count;
}
private Callback callback;
public void registerCallBack(Callback callback) {
this.callback = callback;
}
public String getImageUri () {
return downloadUrl;
}
public void uploadImage (String srcPath, String fileName, Context context, int size) {
StorageReference storageRef = storage.getReference();
StorageReference imageRef = storageRef.child(fileName);
try {
InputStream inputStream = new FileInputStream(new File(srcPath));
imageRef.putStream(inputStream)
.continueWithTask(task -> imageRef.getDownloadUrl())
.addOnCompleteListener(task -> {
downloadUrl = task.getResult().toString();
callback.callingBack();
this.count++;
if (this.count == size) {
callback.getReady();
this.count = 0;
}
});
} catch (Exception e) {
Toast.makeText(context, "Connection error", Toast.LENGTH_LONG).show();
}
}
}
Activity Code
public void someMehtod() {
String fileName;
String filePath;
int size = YOUR_SIZE;
String[] imgUrlList = new String[size];
for (int i = 0; i < size; i++) {
fileName = "img_" + i + ".jpg"; // set target file name
filePath = "/storage/emulated/0/Download/images_" + i + ".jpg"; // for example (u need get your real source file paths)
getImageUri.registerCallBack(new GetImageUri.Callback() {
#Override
public void callingBack() {
imgUrlList [getImageUri.getCount()] = getImageUri.getImageUri();
}
}
#Override
public void getReady() {
// here u can use your URLs
for (int k = 0; k < size; k ++) {
Log.d(TAG, "getReady: " + imgUrlList [k]);
}
});
getImageUri.uploadImage(filePath, fileName, this.getContext(), imgListCount);
}
}
I figured out how to solve the issue. Using callbacks. Create an interface like so
public interface Callback {
void result(Result result);
void url(Uri downloadUrl);
}
Note: result is an enum class with two values FAILED and SUCCESS
Then in your view call the view model like so
ViewModel.saveoBJECT(mObject, new Callback() {
#Override
public void result(Result result) {
switch (result){
case SUCCESS:
mProgressbar.setVisibility(View.GONE);
break;
case FAILED:
Log.v(TAG, "Failed");
Toast.makeText(getApplicationContext(), "OOPS ERROR!", Toast.LENGTH_LONG).show();
break;
}
}
#Override
public void url(Uri downloadUrl) { }
});
and in your db do do something like this
uploadImage(Uri.parse(imageString), prepend, new Callback() {
#Override
public void result(Result result) {}
#Override
public void uri(Uri downloadUrl) {
saveObjectInDB(downloadUrl, new Callback() {
#Override
public void result(Result result) {
callback.result(result);
}
#Override
public void url(Uri downloadUrl) { }
});
}
});
in the upload image function
ref.putFile(file).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
ref.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
callback.journey(uri);
Log.d(TAG, "onSuccess: uri= "+ uri.toString());
}
});
}
});
and in saveObjectInDB function you do this
db.collection(DATABASE).add(O)
.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
Log.w(TAG, "Document upload complete");
callback.result(Result.SUCCESS);
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error adding uploading document", e);
callback.result(Result.FAILED);
}
});

Categories

Resources