I'm trying to extract the auto-generated Id under a document so I can use it elsewhere.
Here is the full code:
mStartChatButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final HashMap<String, Object> myChatFields = new HashMap<>();
myChatFields.put("dateJoined", ServerValue.TIMESTAMP );
myChatFields.put("status", "");
myChatFields.put("snoozeUntil", "");
myChatFields.put("myCharacter", "");
myChatFields.put("requestedCustomChatCode", "");
myChatFields.put("groupChatName", "");
myChatFields.put("toInviteMembers", "");
myChatFields.put("lastMessage", "");
myChatFields.put("lastMessageTimeStamp", ServerValue.TIMESTAMP);
mWhammyUsersCollection.document(mCurrentUserId).collection("my-chats")
.document().set(myChatFields)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
String chatId = mWhammyUsersCollection.document(mCurrentUserId)
.collection("my-chats").document().getId();
Log.v("CHATS", chatId);
myChatFields.put("chatCardId", chatId);
Intent goToChatActivity = new Intent(UserProfileActivity.this,
ChatActivity.class);
startActivity(goToChatActivity);
}
});
As you can see I'm using the code shown below to generated a Collection called "my-chats" and the .document() is creating the auto-generated document id.
mWhammyUsersCollection.document(mCurrentUserId).collection("my-chats")
.document().set(myChatFields)
.addOnSuccessListener(new OnSuccessListener<Void>() {
Then I'm using the line of code shown below to try get the id from that document.
String chatId = mWhammyUsersCollection.document(mCurrentUserId)
.collection("my-chats").document().getId();
Finally using the line of code below, I'm trying to put it into the HashMap I have created.
myChatFields.put("chatCardId", chatId);
There are two main problems I am having:
1) The line of code I'm using to extract the document Id is not working and is extracting some other new auto-generated id (I'm guessing it is because I'm using the .document() method before the .getId() method).
2) Also the information for some reason does not get added to the HashMap with the last line of code I put.
How can I solve these two issues?
To explain it a bit more graphically:
Picture of database
I'm trying to retrieve "1" and add it in the area of "2".
1) The line of code I'm using to extract the document Id is not working and is extracting some other new auto-generated id (I'm guessing it is because I'm using the .document() method before the .getId() method).
No, this is happening because you are calling CollectionReference's document() method twice:
Returns a DocumentReference pointing to a new document with an auto-generated ID within this collection.
So every time you are calling document() method, a fresh new id is generated. To solve this, please change the following lines of code:
mWhammyUsersCollection.document(mCurrentUserId).collection("my-chats")
.document().set(myChatFields)
.addOnSuccessListener(/* ... */);
to
String id = mWhammyUsersCollection.document(mCurrentUserId).collection("my-chats")
.document().getId();
mWhammyUsersCollection.document(mCurrentUserId).collection("my-chats")
.document(id).set(myChatFields)
.addOnSuccessListener(/* ... */);
See, I have used the id that was generated first time inside the refernce. Now inside the onSuccess() method, you should use the same id that was generated above:
myChatFields.put("chatCardId", id);
And not a newer one, as you do in your actual code.
2) Also the information for some reason does not get added to the HashMap with the last line of code I put.
This is happening becase you are using a wrong reference. Using a reference that contains the correct id will solve your problem.
For part one, you'll want to get the document reference in the onSuccess function vs. void. So that would look something like this -
mWhammyUsersCollection.document(mCurrentUserId).collection("my-chats").add(myChatFields)
.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
String chatId = documentReference.getId();
Log.v("CHATS", chatId);
myChatFields.put("chatCardId", chatId);
Intent goToChatActivity = new Intent(UserProfileActivity.this,
ChatActivity.class);
startActivity(goToChatActivity);
}
});
In Documentation writed that
However, sometimes there is no meaningful ID for this document and it's easier to let Cloud Firestore automatically generate an ID for you. You can do this by calling add().
So you can follow #R. Wright answer.
You can get your id from collection data as QuerySnapshot.Just store the position/id
mFirebaseStore.collection("allorder").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
try {
if (!queryDocumentSnapshots.isEmpty()) {
id = queryDocumentSnapshots.getDocuments().get(position).getId();
mArrayList.clear();
List<OrderDetails> data = queryDocumentSnapshots.toObjects(OrderDetails.class);
mArrayList.addAll(data);
mCustomerName.setText(mArrayList.get(position).getCustomerName());
mCustomerContact.setText(mArrayList.get(position).getContactNumber());
mCustomerLocation.setText(mArrayList.get(position).getArea().equals("") ? "No Location Found" : mArrayList.get(position).getArea());
mCustomerInstruction.setText(mArrayList.get(position).getSpecialInstruction().equals("") ? "Type Something" : mArrayList.get(position).getSpecialInstruction());
mTotalPrice.setText(mArrayList.get(position).getTotalPrice().equals("") ? "0" : mArrayList.get(position).getTotalPrice().toString());
String orderStatus = mArrayList.get(position).getOrderStatus();
if (orderStatus.equals("pending") || orderStatus.equals("rejected")) {
mLayout.setVisibility(View.VISIBLE);
} else if (orderStatus.equals("accepted")) {
mLayout.setVisibility(View.GONE);
}
JSONArray json = new JSONArray(mArrayList.get(position).getItemList());
List<AdminOrderDetailsModel> mList = new ArrayList<>();
for (int i = 0; i < json.length(); i++) {
JSONObject jsonObject = json.getJSONObject(i);
AdminOrderDetailsModel model = new AdminOrderDetailsModel();
model.setPackageName(jsonObject.getString("packageName"));
model.setPackageType(jsonObject.getString("packageType"));
model.setPrice(jsonObject.getString("price"));
model.setDuration(jsonObject.getString("duration"));
model.setQuantity(jsonObject.getInt("quantity"));
mList.add(model);
}
AdminOrderDetailsAdapter adapter = new AdminOrderDetailsAdapter(getApplicationContext(), mList);
setRecyclerLayoutManager(getApplicationContext(), mOrderListView, LinearLayoutManager.VERTICAL);
mOrderListView.setAdapter(adapter);
}
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
});
Related
I have a Firestore database with the following structure in a hierarchical form:
collection("notes") > document(currentUserId) > collection("mynotes") > document(auto-generated-key) > items...
I have added data to the Firestore as follows :
mAuth = FirebaseAuth.getInstance();
database = FirebaseFirestore.getInstance();
//here scheduleModel is a model class with constructor(String, boolean, String) with getters and
//setters for three of them
scheduleNoteModel = new ScheduleNote(noteTitle, isImp, strDate);
I have added the note item like this.
database.collection("notes").document(mAuth.getUid())
.collection("mynotes")
.document() //generated id automatically...
.set(scheduleNoteModel)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(getContext(), "data added ...", Toast.LENGTH_SHORT).show();
etNoteTitle.setText("");
//dismiss (hide) the bottom sheet after adding item
BottomSheetScheduleFragment.this.dismiss();
//refresh the fragment
}
});
The problem is getting that id back while deleting the item. I know there are many questions similar to this, some of them were good but I couldn't figure out to solve them. I had a look at this link solution but I wasn't able to solve
In adapter
holder.deleteNoteIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deleteNote(noteModel);
}
});
Method to delete
private void deleteNote(ScheduleNote note, int itemPosition, View view) {
mAuth = FirebaseAuth.getInstance();
database = FirebaseFirestore.getInstance();
//getting the doc id of auto-generated code in Firestore.
String id = database.collection("notes").document(mAuth.getUid()).collection("mynotes").document().getId();
Toast.makeText(context, "position " + itemPosition + "doc id " + id, Toast.LENGTH_SHORT).show();
database.collection("notes").document(mAuth.getUid())
.collection("mynotes")
//.document("72NMkKY73CXHVN7DFE8W") get that id automatically
.document(id)
.delete()
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
//notifyDataSetChanged();
Snackbar snackbar = Snackbar.make(view, "Note Deleted successfully", Snackbar.LENGTH_SHORT);
snackbar.show();
}
});
}
id in the above variable isn't matching the real id. How to get that id?
I basically want two information for this :
How to get the document Id before adding it to the Firestore so that I can attach this to my model class and later on delete based on that ID, has any solution?
Or, just get the document Id by the Model Class that I pass when clicking on the item in RecyclerView?
I actually did a lot of research but couldn't figure it out. Any quick help would be appreciated, thanks.
It doesn't seem to mee, that you are following this link solution. First of all, as also #Frank van Puffelen mentioned in his comment, "document().getId()" will always generate a brand new ID each time is called. So you should save that ID into a variable for later use, so you can delete the desired document right from the adapter. Your "ScheduleNote" class, besides the "noteTitle", "isImp", and "strDate" fields, should also contain a field called "id". So your declaration class should look like this:
class ScheduleNote {
public String noteTitle, strDate, id;
public boolean isImp;
public ScheduleNote() {}
public ScheduleNote(String noteTitle, String strDate, String id, boolean isImp) {
this.noteTitle = noteTitle;
this.strDate = strDate;
this.id = id;
this.isImp = isImp;
}
}
Now, in your particular case, the following lines of code for adding the object to Firestore will do the trick:
CollectionRefference mynotes = database.collection("notes").document(mAuth.getUid())
.collection("mynotes")
String docId = mynotes.document().getId();
To create an object of "ScheduleNote" type, please use:
ScheduleNote scheduleNoteModel = new ScheduleNote(noteTitle, strDate, docId, isImp);
// ^
// newly added
To actually write the data to Firestore, please use:
mynotes.document(docId).set(scheduleNoteModel).addOnSuccessListener(/* ... */);
// ^
To be able to delete that document, you should use the following lines of code:
database.collection("notes").document(mAuth.getUid())
.collection("mynotes")
.document(id)
.delete(note.id)
.addOnSuccessListener(/* ... */);
And this is because, the following line generates again a new ID, which is not correct, as you need to use the one that was generated earlier:
String id = database.collection("notes").document(mAuth.getUid()).collection("mynotes").document().getId();
First of all add document to your collection without any data in it.
DocumentReference addedDocRef =database.collection("notes").document(mAuth.getUid())
.collection("mynotes")
.document();
log.i("Added document with ID: " + addedDocRef.getId());
Then add document id to your model class for later use.
Now, set data for document using your model class.
addedDocRef.set(scheduleNoteModel)
I'm trying to extract the auto-generated Id under a document so I can use it elsewhere.
Here is the full code:
mStartChatButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final HashMap<String, Object> myChatFields = new HashMap<>();
myChatFields.put("dateJoined", ServerValue.TIMESTAMP );
myChatFields.put("status", "");
myChatFields.put("snoozeUntil", "");
myChatFields.put("myCharacter", "");
myChatFields.put("requestedCustomChatCode", "");
myChatFields.put("groupChatName", "");
myChatFields.put("toInviteMembers", "");
myChatFields.put("lastMessage", "");
myChatFields.put("lastMessageTimeStamp", ServerValue.TIMESTAMP);
mWhammyUsersCollection.document(mCurrentUserId).collection("my-chats")
.document().set(myChatFields)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
String chatId = mWhammyUsersCollection.document(mCurrentUserId)
.collection("my-chats").document().getId();
Log.v("CHATS", chatId);
myChatFields.put("chatCardId", chatId);
Intent goToChatActivity = new Intent(UserProfileActivity.this,
ChatActivity.class);
startActivity(goToChatActivity);
}
});
As you can see I'm using the code shown below to generated a Collection called "my-chats" and the .document() is creating the auto-generated document id.
mWhammyUsersCollection.document(mCurrentUserId).collection("my-chats")
.document().set(myChatFields)
.addOnSuccessListener(new OnSuccessListener<Void>() {
Then I'm using the line of code shown below to try get the id from that document.
String chatId = mWhammyUsersCollection.document(mCurrentUserId)
.collection("my-chats").document().getId();
Finally using the line of code below, I'm trying to put it into the HashMap I have created.
myChatFields.put("chatCardId", chatId);
There are two main problems I am having:
1) The line of code I'm using to extract the document Id is not working and is extracting some other new auto-generated id (I'm guessing it is because I'm using the .document() method before the .getId() method).
2) Also the information for some reason does not get added to the HashMap with the last line of code I put.
How can I solve these two issues?
To explain it a bit more graphically:
Picture of database
I'm trying to retrieve "1" and add it in the area of "2".
1) The line of code I'm using to extract the document Id is not working and is extracting some other new auto-generated id (I'm guessing it is because I'm using the .document() method before the .getId() method).
No, this is happening because you are calling CollectionReference's document() method twice:
Returns a DocumentReference pointing to a new document with an auto-generated ID within this collection.
So every time you are calling document() method, a fresh new id is generated. To solve this, please change the following lines of code:
mWhammyUsersCollection.document(mCurrentUserId).collection("my-chats")
.document().set(myChatFields)
.addOnSuccessListener(/* ... */);
to
String id = mWhammyUsersCollection.document(mCurrentUserId).collection("my-chats")
.document().getId();
mWhammyUsersCollection.document(mCurrentUserId).collection("my-chats")
.document(id).set(myChatFields)
.addOnSuccessListener(/* ... */);
See, I have used the id that was generated first time inside the refernce. Now inside the onSuccess() method, you should use the same id that was generated above:
myChatFields.put("chatCardId", id);
And not a newer one, as you do in your actual code.
2) Also the information for some reason does not get added to the HashMap with the last line of code I put.
This is happening becase you are using a wrong reference. Using a reference that contains the correct id will solve your problem.
For part one, you'll want to get the document reference in the onSuccess function vs. void. So that would look something like this -
mWhammyUsersCollection.document(mCurrentUserId).collection("my-chats").add(myChatFields)
.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
String chatId = documentReference.getId();
Log.v("CHATS", chatId);
myChatFields.put("chatCardId", chatId);
Intent goToChatActivity = new Intent(UserProfileActivity.this,
ChatActivity.class);
startActivity(goToChatActivity);
}
});
In Documentation writed that
However, sometimes there is no meaningful ID for this document and it's easier to let Cloud Firestore automatically generate an ID for you. You can do this by calling add().
So you can follow #R. Wright answer.
You can get your id from collection data as QuerySnapshot.Just store the position/id
mFirebaseStore.collection("allorder").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
try {
if (!queryDocumentSnapshots.isEmpty()) {
id = queryDocumentSnapshots.getDocuments().get(position).getId();
mArrayList.clear();
List<OrderDetails> data = queryDocumentSnapshots.toObjects(OrderDetails.class);
mArrayList.addAll(data);
mCustomerName.setText(mArrayList.get(position).getCustomerName());
mCustomerContact.setText(mArrayList.get(position).getContactNumber());
mCustomerLocation.setText(mArrayList.get(position).getArea().equals("") ? "No Location Found" : mArrayList.get(position).getArea());
mCustomerInstruction.setText(mArrayList.get(position).getSpecialInstruction().equals("") ? "Type Something" : mArrayList.get(position).getSpecialInstruction());
mTotalPrice.setText(mArrayList.get(position).getTotalPrice().equals("") ? "0" : mArrayList.get(position).getTotalPrice().toString());
String orderStatus = mArrayList.get(position).getOrderStatus();
if (orderStatus.equals("pending") || orderStatus.equals("rejected")) {
mLayout.setVisibility(View.VISIBLE);
} else if (orderStatus.equals("accepted")) {
mLayout.setVisibility(View.GONE);
}
JSONArray json = new JSONArray(mArrayList.get(position).getItemList());
List<AdminOrderDetailsModel> mList = new ArrayList<>();
for (int i = 0; i < json.length(); i++) {
JSONObject jsonObject = json.getJSONObject(i);
AdminOrderDetailsModel model = new AdminOrderDetailsModel();
model.setPackageName(jsonObject.getString("packageName"));
model.setPackageType(jsonObject.getString("packageType"));
model.setPrice(jsonObject.getString("price"));
model.setDuration(jsonObject.getString("duration"));
model.setQuantity(jsonObject.getInt("quantity"));
mList.add(model);
}
AdminOrderDetailsAdapter adapter = new AdminOrderDetailsAdapter(getApplicationContext(), mList);
setRecyclerLayoutManager(getApplicationContext(), mOrderListView, LinearLayoutManager.VERTICAL);
mOrderListView.setAdapter(adapter);
}
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
});
I'm using socket.io for my chat app. I have an ArrayList which contains last message, username, time. Whenever a new message arrives in JSON format then it should check if JSON contained username is present in ArrayList or not. If present, then updates the ArrayList otherwise add in ArrayList.
Here is my code:-
private Emitter.Listener handle1 = new Emitter.Listener() {
#Override
public void call(final Object... args) {
ChatLists.this.runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject)args[0];
try {
String sendername = data.getString("sender");
String lastMessage = data.getString("message");
String profileImage = data.getString("Profile");
String token = data.getString("fb_token");
chat_list chat_list = new chat_list(sendername,
profileImage, lastMessage, "0", "", "dummy", token);
if (chat_lists.size()==0){
chat_lists.add(chat_list);
}else {
for (int i=0;i<chat_lists.size();i++){
if (chat_lists.get(i).getContactname().equals(sendername)){
chat_lists.set(i,chat_list);
}else {
chat_lists.add(chat_list)
}
}
}
contactlistAdapter = new ContactlistAdapter(chat_lists);
recyclerView.setAdapter(contactlistAdapter);
contactlistAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
};
Well, you can use contains() & set() methods of ArrayList in a logical way to solve your problem like below:-
if(chat_lists.contains(username))
chat_lists.set(indexOf(username), new_username);
else chat_lists.add(new_username);
Try it:
if(chat_lists.contains(chat_list)){
chat_lists.remove(chat_list);
chat_lists.add(chat_list);
} else {
chat_lists.add(chat_list);
}
Read about architecture patterns, for example, MVP.
You need to store your messages somethere (in Model) and update view relative to data.
Also read about RecyclerView, cause of ListView is a little bit deprecated
if (chat_lists.get(i).getContactname().equals(sendername)){
above statement has problem them. It's not getting under your if condition and following the chat_lists.add(chat_list) statement.
Instead equals use ignoreCasequals. If still wont it solve your problem please use debug mode or logs check chat_lists.get(i).getContactname()
and sendername same or not.
I am building a simple Journal application that user can use to take notes. I am trying to get the list of journals from database in an activity. When I get it, it is displaying the whole note that the user had input. I just want to get the first line of words so that the user can click on it to get the full notes.
Here is my code
This is where i save the code to database
private void saveNoteToDB(View v) {
Note note = new Note();
String newNotes = enterNotes.getText().toString();
note.setTheNotes(newNotes);
//Save to Db
db.addNotes(note);
Snackbar.make(v, "Note Saved", Snackbar.LENGTH_LONG).show();
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
alertDialog.dismiss();
startActivity(new Intent(ListNotes.this, ListNotes.class));
}
}, 1500);
}
This is where i get items from the database
//Get notes from Database
noteItem = db.getAllNotes();
for (Note c : noteItem) {
Note note = new Note();
note.setTheNotes(c.getTheNotes());
note.setId(c.getId());
note.setDateNotesAdded(c.getDateNotesAdded());
listItem.add(note);
}
recyclerViewAdapter = new RecyclerViewAdapter(this, listItem);
recyclerView.setAdapter(recyclerViewAdapter);
recyclerViewAdapter.notifyDataSetChanged();
}
You can limit the string by using
note.setTheNotes(c.getTheNotes().substring(0,20) + "...." );
Note: 20 can be configurable number and may very in your case.
UPDATE : actually you want to do this when you are getting the data from DB.
note.setTheNotes(c.getTheNotes().substring(0,20) + "...." );
Use this for set the limit of string
I'm trying to insert some data into my firebase but encountered the following error, the 2nd data is missing. Here are the code:
Firebase.setAndroidContext(this);
Button btnSave = (Button) findViewById(R.id.btnSave);
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
//Creating firebase object
Firebase ref = new Firebase(Config.FIREBASE_URL);
//Getting values to store
String name = mName.getText().toString().trim();
String address = mAddress.getText().toString().trim();
String latlng = mLatLng.getText().toString().trim();
//Creating Person object
FM_Spots spots = new FM_Spots();
//Adding values
spots.setName(name);
spots.setAddress(address);
spots.setLatLng(latlng);
//Storing values to firebase
//ref.child("FM_Spots").setValue(spots);
Firebase newRef = ref.child("FM_Spots").push();
newRef.setValue(spots);
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.getMessage().toString(), Toast.LENGTH_SHORT).show();
}
}
});
}
I only have 2 fields which are name and the address is having data from the last field (latlng). Please advise, thank you.
-sea-
When you said "2nd data" you meant that the second field of the writable object is missing, right?
If so, you can use updateChildren(Map map) method instead of setValue() to specify fields you want to write directly:
newRef.updateChildren(convertFMSpotsToMap(spots));
where convertFMSpotsToMap() is something like this:
private static Map<String, Object> convertFMSpotsToMap(#NonNull FM_Spots spots) {
HashMap<String, Object> map = new HashMap<>();
map.put("name", spots.getName());
map.put("address", spots.getAddress());
return map;
}