Nodes are getting created in Firebase everytime I click a button - java

Thanks for helping. I am creating an Android app which is working perfectly well. But I am facing a minor problem. The application contains message functionality for the posted ads. When the user opens an ad he is greeted with two options of call or message, where if the user clicks on the message button then he is sent to the chat screen, at the time of the button press the info gets stored in firebase database but I want the info to get stored only for the first time and if the users clicks the button next time then he should be taken to the pre-generated node, not on the new one.
Below is my code for adding the new nodes on the click of the button. Please lemme know if there is any way through which I can stop nodes from getting generated on every button click:
mChat.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent chatIntent = new Intent(ExpandActivity.this, ChatActivity.class);
chatIntent.putExtra("user_id", mId);
chatIntent.putExtra("user_name", mName);
chatIntent.putExtra("ad_id", user_id);
chatIntent.putExtra("cow", m);
startActivity(chatIntent);
mRootRef.child("Chat").child(uid).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
DatabaseReference user_message_push = mRootRef.child("Chat").child(uid).push();
m = user_message_push.getKey();
if (!dataSnapshot.hasChild(user_id)) {
mRootRef.child("AdvertData").child(user_id).addValueEventListener(new
ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String image = dataSnapshot.child("image").getValue().toString();
String title = dataSnapshot.child("title").getValue().toString();
String price = dataSnapshot.child("price").getValue().toString();
Map chatAddMap = new HashMap();
chatAddMap.put("seen", false);
chatAddMap.put("timestamp", ServerValue.TIMESTAMP);
chatAddMap.put("image", image);
chatAddMap.put("title", title);
chatAddMap.put("price", price);
chatAddMap.put("chatUser", mName);
chatAddMap.put("ads", user_id);
chatAddMap.put("chatUserId", mId);
Map chatAddMap1 = new HashMap();
chatAddMap1.put("seen", false);
chatAddMap1.put("timestamp", ServerValue.TIMESTAMP);
chatAddMap1.put("image", image);
chatAddMap1.put("title", title);
chatAddMap1.put("price", price);
chatAddMap1.put("chatUser", name);
chatAddMap1.put("ads", user_id);
chatAddMap1.put("chatUserId", uid);
Map chatUserMap = new HashMap();
chatUserMap.put("Chats/" + uid + "/" + m, chatAddMap);
chatUserMap.put("Chats/" + mId + "/" + m, chatAddMap1);
mRootRef.updateChildren(chatUserMap, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError != null) {
Log.d("CHAT_LOG", databaseError.getMessage().toString());
}
}
});
Below is the picture of how my database looks like:

Here is the logic..! Use addListenerForSingleValueEvent. It is called only one time. And Get key only if snapshot doesn't exist
DatabaseReference user_message_Ref = mRootRef.child("Chat").child(uid);
// First check if snapshot exist()
user_message_Ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists())
{
// GO TO THE DESIRED ACTIVITY
navigateToYOURActivity();
}else
{
// GET KEY
String key = user_message_Ref.push().getKey();
// & UPDATE DATABASE
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

I want the info to get stored only for the first time and if the
users clicks the button next time then he should be taken to the
pre-generated node
It's probably because of addValueEventListener().
You can try using addListenerForSingleValueEvent() which does this only one time i suppose.

When you are using the following lines of code:
DatabaseReference user_message_push = mRootRef.child("Chat").child(uid).push();
m = user_message_push.getKey();
You are generating a new random id at every button click. This is what push() method does. If you want the second time you click the button to access the same reference, you should store that id in a variable and use the same variable again, not generate another one.

Related

How can I retrieve second data from array list

I can only retrieve first data "9780071792745" from my database. The app crashed when I tried to retrieve data from b. Here is my code
public class wish_list extends AppCompatActivity {
TextView display;
//private String wishlist;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wish_list);
display=(TextView)findViewById(R.id.tvDisplay);
//start here
DatabaseReference myRef = FirebaseDatabase.getInstance().getReference().child("Users")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("Wishlist");
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
List<String> wishlist_item = new ArrayList<String>();
for (DataSnapshot postSnapshot: snapshot.getChildren()) {
wishlist_item.add(postSnapshot.getValue().toString());//got all wish list item from database
String a = wishlist_item.get(0);
String b = wishlist_item.get(1);
display.setText("Hi" + a);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
}
I can only retrieve from String a = wishlist_item.get(0) and cannot retrieve from String b = wishlist_item.get(1);
How can I retrieve?
Here is my data structure from my firebase database:
I can also tried to retrieve like this display.setText("Hi" + wishlist_item); and it worked but cannot retrieve from display.setText("Hi" + b);
error is :
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1 at java.util.ArrayList.get(ArrayList.java:437)
You are trying to retrive data from index 1 while that index is not created yet. When you enter the for loop, the for loop is getting the first item from the snapshot and adding it to the wishlist_item arraylist. What you need to do is this:
List<String> wishlist_item = new ArrayList<String>();
for (DataSnapshot postSnapshot: snapshot.getChildren()) {
wishlist_item.add(postSnapshot.getValue().toString());//got all wish list item from database
}
String a = wishlist_item.get(0);
String b = wishlist_item.get(1);
display.setText("Hi" + a);
This will work. Because you let your foreach loop to finish. This line:
wishlist_item.add(postSnapshot.getValue().toString());//got all wish list item from database
won't put all items from a snapshot, it will add one item at the time, the one that foreach loop is using right now. You first need to understand how for and foreach loops work: https://www.geeksforgeeks.org/for-each-loop-in-java/

How to load children from Firebase

I have some code that will store the number of times a particular OS has been voted for on Firebase. I use the following to store it:
DatabaseReference windowsChoice;
And inside the onCreate method:
FirebaseDatabase.getInstance().getReference("Windows");
Inside the button method I store the data to firebase with:
String id = "TimesClicked";
windowsChoice.child(id).setValue(b); //b holds the amount of times that Windows has been clicked
The resulting format is such:
{"Windows":{"TimesClicked":8},"choice1Num":23} // ignore choice1Num
The following code will get me the value of Windows (TimesClicked:8):
String result = new Connector().execute().get();
JSONObject ob = new JSONObject(result);
String jsonString = ob.getString("Windows");
String id = "TimesClicked";
windowsChoice.child(id).setValue(b);
intent.putExtra("result", jsonString);
startActivity(intent);
But how can I get the value of the TimesClicked label?
But how can I get the value of the TimesClicked label?
Simply, by using the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference timesClickedRef = rootRef.child("Windows").child("TimesClicked");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
long timesClicked = dataSnapshot.getValue(Long.class);
Log.d("TAG", "timesClicked: " + timesClicked);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore errors!
}
};
timesClickedRef.addListenerForSingleValueEvent(valueEventListener);
The result in the logcat will be:
timesClicked: 8

Can´t finish Activity

I have tried className.this.finish and finishActivity() to invoke the finishing of my activity and I have initialised the activity with the following methods - startActivityForResult() or finishAndRemoveTask()
The propose of this activity is to register a device this is done when under Devices/(MAC address of the device)/Users/ it save in fire base up to 4 different notification tokens of 4 users different. So what I'm trying to do but it falling is to check if the number 1 have info, check 2 if have info, check 3 and if this have info, check the 4 if all have info the app show a message saying "you have reached the maximum number of users".But if one number available it suppose to save in that number and only in that number the notification token.
What it is happening is that when I click the button the loop never end. it send the same notification token for the four users show the mensage "you have reached the maximum number of users" and then it come back to the activity before this one but it still executing the registration code. I know this because if I deleted an user in firebase it immediately resend the info and you can see the message "you have reached the maximum number of users" again
this is the code of the activity that send the info:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_cerca);
fAuth = FirebaseAuth.getInstance();
entr = findViewById(R.id.AddButton);
mDatabase = FirebaseDatabase.getInstance().getReference();
sDatabase = FirebaseDatabase.getInstance().getReference();
aDatabase = FirebaseDatabase.getInstance().getReference();
MAC =findViewById(R.id.macCerca);
NOM = findViewById(R.id.momCerca);
configured = false;
getUserProfile();
getNotificationId();
entr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MacCerca = MAC.getText().toString().toUpperCase();
NombreCerca = NOM.getText().toString();
//mDatabase.child("Devices").child(MacCerca).child("Id").setValue("AD:23");
mDatabase.child("Devices").child(MacCerca).child("Users").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String user1 = (String) dataSnapshot.child("1").getValue();
String user2 = (String) dataSnapshot.child("2").getValue();
String user3 = (String) dataSnapshot.child("3").getValue();
String user4 = (String) dataSnapshot.child("4").getValue();
if(user1 == null){
aDatabase.child("Devices").child(MacCerca).child("Users").child("1").setValue(token);
aDatabase.child("Devices").child(MacCerca).child("NombreCerca").setValue(NombreCerca);
aDatabase.child("Users").child(mail).child("Device").setValue(MacCerca);
AddCerca.this.finish();
}else if(user2 ==null){
aDatabase.child("Devices").child(MacCerca).child("Users").child("2").setValue(token);
aDatabase.child("Devices").child(MacCerca).child("NombreCerca").setValue(NombreCerca);
aDatabase.child("Users").child(mail).child("Device").setValue(MacCerca);
AddCerca.this.finish();
}else if(user3 ==null){
aDatabase.child("Devices").child(MacCerca).child("Users").child("3").setValue(token);
aDatabase.child("Devices").child(MacCerca).child("NombreCerca").setValue(NombreCerca);
aDatabase.child("Users").child(mail).child("Device").setValue(MacCerca);
AddCerca.this.finish();
}else if(user4 ==null){
aDatabase.child("Devices").child(MacCerca).child("Users").child("4").setValue(token);
aDatabase.child("Devices").child(MacCerca).child("NombreCerca").setValue(NombreCerca);
aDatabase.child("Users").child(mail).child("Device").setValue(MacCerca);
AddCerca.this.finish();
}else{
Toast.makeText(AddCerca.this, "Límite de usuarios registrados exedidos", Toast.LENGTH_SHORT).show();
AddCerca.this.finish();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
});
}
and I create this activity like this:
startActivity(new Intent(CercaElectrica.this, AddCerca.class));
Firebase look like this:
When it suposed to be only in the user 1, or if user 1 have some data it have to update user 2 and the same with 3 and 4
I found the error. insted of:
mDatabase.child("Devices").child(MacCerca).child("Users").addValueEventListener(new ValueEventListener() {
change for:
mDatabase.child("Devices").child(MacCerca).child("Users").addListenerForSingleValueEvent(new ValueEventListener() {

How to retrieve a Boolean value from Firebase to a TextView?

I'm making a shopping app and User has to subscribe to the 'Fast-delivery' option if he needs to order it faster. When the User puts a tick to the 'Fast-delivery' Checkbox, the boolean value is being uploaded to the Firebase realtime database -->
database
And I want to see if the User has subscribed to the 'Fast-delivery' option from the Admin Panel. I retrieve all the order information to a RecyclerView in the Admin Panel. I want to set a TextView as "Fast Delivery : On/Off" when the Admin views the order details from the Admin Panel.
This is what I have tried:
#Override
protected void onStart()
{
super.onStart();
ordersRef = FirebaseDatabase.getInstance().getReference().child("Orders");
FirebaseRecyclerOptions<AdminOrders> options =
new FirebaseRecyclerOptions.Builder<AdminOrders>()
.setQuery(ordersRef, AdminOrders.class)
.build();
FirebaseRecyclerAdapter<AdminOrders, AdminOrdersViewHolder> adapter =
new FirebaseRecyclerAdapter<AdminOrders, AdminOrdersViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull final AdminOrdersViewHolder holder, final int position, final #NonNull AdminOrders model)
{
holder.userName.setText("Name: "+ model.getName());
holder.userPhoneNumber.setText("Phone Number: : "+ model.getPhone());
holder.userTotalPrice.setText("Total Amount: $"+ model.getTotalAmount());
holder.userDateTime.setText("Order Time: "+ model.getDate() + model.getTime());
holder.userShippingAddress.setText("Shipping Address: "+ model.getAddress() + "," + model.getCity());
holder.showOrdersBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
String uID = getRef(position).getKey();
Intent intent = new Intent(AdminNewOrdersActivity.this, AdminUserProductsActivity.class);
intent.putExtra("uid", uID);
startActivity(intent);
}
});
ordersRef.child(userID).child("fast_delivery").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
TextView switch1 = (TextView) findViewById(R.id.switch1);
switch1.setText(String.valueOf(this));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
And I'm getting this error
java.lang.NullPointerException: Can't pass null for argument 'pathString' in child()
You have a NullPointerException indicating that userID is not initialized, hence this error:
Can't pass null for argument 'pathString' in child()
To solve this, please add the following line of code:
String userID = FirebaseAuth.getInstance().getCurrentUser().getUid();
Right in front of:
ordersRef.child(userID).child("fast_delivery").addValueEventListener(/* ... */);
i guess if im right.. you have created separate tree for orders where you are getting orders
create model class give name as same as childname are where you're getting boolean value of fast_delivery use that boolean value to convert it to string and hence compare that value if String.valueof(boolean)is="true" then print to textview or vise versa with off

get a child name from Firebase Database Progmatically

In Firebase database i have a directory called Global_downloads then inside there are a few children.
child.("Casting apps") which i can locate with in my app code using a String value called AppType.
the next child.("All cast") is the child i need. i can get it into firebase by using an onitem click with my listview. which then sends it to firebase in the form of a child.
but how can i locate the name for the child(Allcast) progmatically? so i can then get the number of downloads?
here is my code for my child listener
#Override
public void onChildAdded(final com.firebase.client.DataSnapshot dataSnapshot, String s) {
String counter = dataSnapshot.child("Global_downloads").child(Apptype).
child("I need this child").child("downloads").getValue(String.class);
Downloadscount.add(counter);
String[] arr3 = Downloadscount.toArray(new String[Downloadscount.size()]);
the rest of the items in the constructor are for other items in my listview
///my custom adapter where it returns the info to my listview
apkData = new dataListAdapter(mContext, arr, arr1, arr2, mrootRef, Apptype,arr3);
mlv.setAdapter(apkData);
apkData.notifyDataSetChanged();
mlv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
final Firebase ref = mrootRef.getRef();
//here is where i assign the name to firebase in my counter class which works
apkNames = AppNameList.get(i).toString(); //this is the name i want to send back to the top and use as a Child name.or can i get the child name another way.
gc = new Global_counter(ref,Apptype,apkNames);
gc.App_DownLoadCounter();
this is my listview there are more items on my list other than Allcast.
but all cast is the only item downloaded. if more items are pressed it adds that name to the list too. the text view you can see is the downloads im trying to add
To get the coresponding item that was downloaded, please use the following line of code inside onItemClick() method and then just use it inside your DatabaseReference.
String downloadName = (String) adapterView.getItemAtPosition(i);
Assuming that Global_downloads node is a direct child of your Firebase root and the value of downloads is of type Integer, to get the number of downloads please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference downloadsRef = rootRef.child("Global_downloads").child(Apptype).child(downloadName).child("downloads");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int downloads = dataSnapshot.getValue(Integer.class);
Log.d("TAG", downloads);
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
downloadsRef.addListenerForSingleValueEvent(eventListener);
Your output will be:
0
In your situation, the key is Apptype and the value is downloads.
I'm assuming Global_dowbloads under your root reference.
To get all the downloads with app name, you need to read the data as key->value
Like this
DatabaseReference mRef = FirebaseDatabase.getInstance().getReference();
mRef.child("Global_downloads").child(Apptype)
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot snapshot: dataSnapshot.getChildren()){
Log.v("app_name", snapshot.getKey());
Log.v("app_downloads", snapshot.getValue(String.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

Categories

Resources