How to get value of last node added to the database - java

I'm trying to access a certain value within the last added Firebase node. In my database I have a set of Clients, which through my app, can be added to. Inside a client there's a piece of information titled 'clientName'. I would like to get this value.
Once I get the value, I'm trying to give a toast message showing that value.
Here is my code inside the onClick method of my button. I'm not sure why it's not working. If you know of another way I could do this or a way to fix my current code I'd really appreciate it!
Thanks in advance guys!
my_button[bt].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (my_button[Index].getId() == ((ImageButton) v).getId()) {
String bla = (String) getIntent().getExtras().get("id");
String address = "https://console.firebase.google.com/project/cssecond-92a2d/database/data/clients/" +bla+"/clientName";
Firebase ref = new Firebase(address);
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(com.firebase.client.DataSnapshot dataSnapshot) {
String value = (String) dataSnapshot.getValue();
Toast.makeText(HomePageNews.this,"In your hands you have: "+ value ,Toast.LENGTH_LONG).show();
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
}
});

Everything looks fine in your code. The problem is this line of code:
String bla = (String) getIntent().getExtras().get("id");
The id that is returning from that intent is null, so your reference is also null. In order to fix this, you need to change the code to get the correct value from the intent that is coming from your previous activity and than it should work.

Related

NumberFormatException occurs on previous String key when Database changes

Every time the value in database changes causes the related activity stops working. But after starting the activity again the display and data retrieved will still work and is updated.
I found this in Logcat:
AndroidRuntime: FATAL EXCEPTION: main
java.lang.NumberFormatException: For input string: "201908241000gjjj"
That is a string key for database:
//formatDateTime and parseDateTime are methods to simplify simpleDateFormat and return String
String stringDate = formatDateTime(dateFromString, "yyyyMMdd");
String stringTime = parseDateTime(taskTime, "hh:mm a", "HHmm");
final String key = stringDate + stringTime + taskParticipant;
dbrSchedule.child(key).setValue(schedule); //schedule is model class
I never ask the code to retrieve and parse it to Numeric. Inside onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dbrCurrentTask.orderByChild("dateOrder").startAt(stringDateForWorkingInProgress).endAt(stringDateForCurrent).addValueEventListener(todayTasks);
}
private ValueEventListener todayTasks = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
scheduleList.clear();
for (DataSnapshot scheduleTaskDS : dataSnapshot.getChildren()) {
final ScheduleFD scheduleTemp = scheduleTaskDS.getValue(ScheduleFD.class);
if (scheduleTemp != null) {
if ((scheduleTemp.getDateOrder().equals(stringDateForCurrent) && !scheduleTemp.getStatus().equals(getString(R.string.task_completed))) || (!scheduleTemp.getDateOrder().equals(stringDateForCurrent) && scheduleTemp.getStatus().equals(getString(R.string.working_in_progress)))) {
scheduleList.add(scheduleTemp);
}
}
}
tra = new TaskFDAdapter(ScheduleCheckInOut.this, scheduleList);
trv.setAdapter(tra);
if (!scheduleList.isEmpty()) {
handler.postDelayed(runnable, 360);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
};
#Override
protected void onDestroy() {
super.onDestroy();
dbrCurrentTask.orderByChild("dateOrder").startAt(stringDateForWorkingInProgress).endAt(stringDateForCurrent).removeEventListener(todayTasks);
}
Also I have did same thing but with try catch:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
dbrCurrentTask.orderByChild("dateOrder").startAt(stringDateForWorkingInProgress).endAt(stringDateForCurrent).addValueEventListener(todayTasks);
} catch (NumberFormatException e){
//refresh
finish();
overridePendingTransition(0, 0);
startActivity(new Intent(getApplicationContext(), THIS_ACTIVITY.class));
overridePendingTransition(0, 0);
}
But it still show NumberFormatException in Logcat and stop working when database value is changed.
I also tried to change my string key to without any numeric but same Exception shown.
After a lot of testing, I found that the string key 201908241000gjjj which shown in Error: java.lang.NumberFormatException: For input string: "201908241000gjjj" is the previous string key of string key 201908261000ffghrr which the child value changed:
{
"Schedules": {
"201908231000bb": {children}
"201908241000gjjj": {children} //NumberFormatException show this key
"201908261000ffghrr": {children} //value changed
}
}
For any changes in children will show the Exception for the previous string key. If children changed in 201908241000gjjj, then Exception show 201908231000bb.
And if children changed in 201908231000bb, it have no error because 201908231000bb is the first and have no previous string key for it.
Why is this weird things happen? Will the size of children influence this? I have another reference group have 3 children and String values for each child with no issue when Database changes but this reference group (Schedules) has about 34 children and String values for each child.
I expect no matter how the value in database is changed, the activity will keep working, but it goes back to the previous activity and then pops up "Application not working" after any change in the referred database.
I find a bit unclear what is your question, but here is my try:
You are getting NumberFormatException in .getValue(ScheduleFD.class) in the listener, that is a guess I make from your post, you should have the exact line in your logcat.
You don't necessarily need to wrap the query in a try catch, you may catch something, but it won't be a NumberFormatException, if you want to use the try/catch, wrap it around .getValue(ScheduleFD.class) inside the EventListener, where I think is more certainly that you are getting the exception.
However if you are getting the exception there is because your logic is wrong, what's the point on getting the value if you are expecting to catch an exception?
The way you are storing your data in the database must be consistent with the way you are going to retrieve it.
If I'm wrong I'd suggest to add your ScheduleFD.class to your question along with a sample data of what you are trying to get.

How to add a set of suggestions into the setSuggestions

I am using the Material SearchView which is provided by the library 'com.miguelcatalan:materialsearchview:1.4.0'. This library uses setSuggestions to set suggestions into the search view like i shown in the following code. But the setSuggestions allows String[] only. I want to load a list of items from the firebase and put in to the suggestion. The problem is that setSuggestion does not allow ArrayList.
materialSearchView.setOnSearchViewListener(new MaterialSearchView.SearchViewListener() {
#Override
public void onSearchViewShown() {
//Do some magic
mProgress.setMessage("Loading...");
mProgress.show();
mDatabasePlaces.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot data:dataSnapshot.getChildren()){
Place models=data.getValue(Place.class);
placelist.add(models.getName());
}
mProgress.dismiss();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
materialSearchView.setSuggestions(placelist);
}
#Override
public void onSearchViewClosed() {
//Do some magic
}
});
}
In the code placelist is an ArrayList which is not allowed in the materialSearchView.setSuggestions(placelist); So how can I put that list of places into setSuggestions.
You can parse it to String[] like this
String[] parsedArray = placelist.toArray(new String[placelist.size()])
Due the asynchronous behavior of onDataChange method, to get your work done, please move the following line of code:
materialSearchView.setSuggestions(placelist);
Inside onDataChange method right after this line of code:
mProgress.dismiss();
As also Artur Akhnoyan mentioned in his answer, please change the argument from placelist to:
placelist.toArray(new String[placelist.size()])

addValueChangeListener doen't trigger in android

I have a app in building proccess in some where i need to get data from FirebaseDatabase and show them in custom list view here my code part of it for onDataChange method
myDatabase=FirebaseDatabase.getInstance();
myRef= myDatabase.getReference().child("TvSeries");
myAuth = FirebaseAuth.getInstance();
myUser = myAuth.getCurrentUser();
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot currentData : dataSnapshot.getChildren()){
if(currentData.child("tCategory").child("tPrimary").getValue().toString().equals("Aksiyon")){ }
selectedCategoryList.add(new DataForRow(currentData.getKey(),
currentData.child("tCategory").child("tPrimary").getValue().toString(),
currentData.child("tReleaseDate").getValue().toString()));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Integer size =selectedCategoryList.size();
Log.d("Size:", size.toString());
When i put in breakpoint onDataChange method it works but otherwise it didnt any suggestion is very helpful. Have a nice day all.
Your selectedCategoryList list is always empty because onDataChange() method has an asynchronous behaviour which means that is called even before you are try to add those objects of DataForRow class to the list. A quick solve for this problem would be to declare and use your selectedCategoryList list only inside the onDataChange() method or if you want to use it outside, you need to create your own callback and for that, I recommend you see the last part of my answer from this post.
Firebase works asynchronously. You probably got the data from firebase after you program executed the line with Log. As Tristan mentioned, if you put your Log inside of the listener, it will work

Print out only finished memberList

so the Code looks like this right now.
The Problem is that I get more than one Logprints. But I need only the full and finished meberList.
for (String memberByNumber : memberListByNumber) {
mFirebaseDatabaseReference.child("userUidsByNumber/").child(memberByNumber).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String userUid = dataSnapshot.getValue().toString();
memberList.add(userUid);
Log.d("LOL", "ContactsAdapter: " + memberList);
} else {
Snackbar.make(view, R.string.user_does_not_exist, Snackbar.LENGTH_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Snackbar.make(view, R.string.error, Snackbar.LENGTH_LONG).show();
}
});
}
I hope you understand my Problem and can help me.
Thanks in advance.
If onDataChange gets called for every member for memberListByNumber, then you can try
final int total = memberListByNumber.size();
for (String memberByNumber : memberListByNumber) {
mFirebaseDatabaseReference
.child("userUidsByNumber/")
.child(memberByNumber)
.addValueEventListener(new ValueEventListener() {
int n = total;
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String userUid = dataSnapshot.getValue().toString();
memberList.add(userUid);
if (--n <= 0) Log.d("LOL", "ContactsAdapter: " + memberList);
} else {
Snackbar.make(view, R.string.user_does_not_exist, Snackbar.LENGTH_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Snackbar.make(view, R.string.error, Snackbar.LENGTH_LONG).show();
}
});
}
I want to comment it but due to my reputation here I couldn't
So, here is my answer your logging every entry into one file so that it just makes printing the necessary entries much harder So go on different path and give one more if-else statement in existing one and use try-exception to divide the finished and canceled into some cache memory and then void the finished file
In firebase, there's never a thing as complete list.
Value events keep happening whenever any data changes under any of the child nodes. Also value events happen last ie after all child events are finished ensuring all children nodes at that point are present. Next event will give you the complete list at that particular point.
On each data change call, you can clear the list, add all the new values and print that. This is how firebase works.
If you want the entire list only once and don't want any new changes, you can add the value event listeners using addListenerForSingleValueEvent method. Now the list will be read once and no more. However if you have persistence enabled, the data will be read once from the phone cache and not from the db
Maybe what you are looking for is a ChildEventListener which will give you more granular control. This will have child added, deleted and changed events which will give you the list data one child at a time.
I don't know what your actual purpose is so this is the best i can try to explain. Hope this helps

Linked List not updating values

So I've debugged my program and have found that the part of my program is updating, whilst another isn't.
I have a method:
public void storeApplication(String name, String item){
Application app = new Application(name, item);
peopleAttending.add(app);
}
The debugger reports that an object is contained in the LinkedList (peopleAttending).
In another method:
public void populateListView() {
int noOfPeopleAttending = peopleAttending.size();
String noPeopleAttending = String.valueOf(noOfPeopleAttending);
Toast.makeText(GuestsAttending.this, noPeopleAttending, Toast.LENGTH_SHORT).show();
}
This method can be called after the previous one and states that there isn't an object within the LinkedList.
I've checked the object references just to make sure that they are pointing at the same reference and they are.
Any help would be greatly appreciated.
EDIT: Entire Class:
public class GuestsAttending extends Activity {
private LinkedList<Application> peopleAttending = new LinkedList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_guests_attending);
populateListView();
}
public void storeApplication(String name, String item){
Application app = new Application(name, item);
peopleAttending.add(app);
}
public void populateListView() {
// GuestsAdapter adapter = new GuestsAdapter(this, peopleAttending);
// ListView listView = (ListView) findViewById(R.id.listView);
// listView.setAdapter(adapter);
peopleAttending.size();
int noOfPeopleAttending = peopleAttending.size();
String noPeopleAttending = String.valueOf(noOfPeopleAttending);
Toast.makeText(GuestsAttending.this, noPeopleAttending, Toast.LENGTH_SHORT).show();
}
Second Edit:
Java Booking Screen Method:
public void saveBookingInfo(View view) {
GuestsAttending sendApplication = new GuestsAttending();
EditText applicantNameText = (EditText) findViewById(R.id.applicantNameTextField);
EditText itemToBurnText = (EditText) findViewById(R.id.itemToBurnTextField);
String appName = applicantNameText.getText().toString();
String appItemToBurn = itemToBurnText.getText().toString();
if (appItemToBurn.isEmpty() || appName.isEmpty()) {
Toast.makeText(BookingScreen.this, "Please fill in all fields.", Toast.LENGTH_SHORT).show();
}
else {
sendApplication.storeApplication(appName, appItemToBurn);
}
}
GuestsAttending Java Class: -- See Above.
Useful hint: It's really popular to set type of List as a List<> interface from java.util package instead of LinkedList<> itself.
Anyway, i am pretty sure that storeApplication method is not automatically triggered before onCreate method ran by Activity framework. Maybe your debugger is stopoing on it in different order (because of using threads or smth), but you should to log some invoke. Try to find it out.
I've found out what the problem is:
When I submit the booking information, it runs all the necessary methods. However, when the "storeApplication()" method has finished executing, the ArrayList 'empties' all the objects out.
I only noticed this when I used breakpoint and tried running the method twice, on the second time I entered booking details, the ArrayList stated it was empty.
I'm going to see if I can try and store the ArrayList in a more secure place.

Categories