How can i count a query / dataSnapshot? [duplicate] - java

This question already has answers here:
Default FirebaseApp is not initialized
(34 answers)
Closed 3 years ago.
I want to show the number of active users in my StartActivity. The users are divided into two groups: players and spectators. I tried it in my database with a Boolean value. How can I show / count the users?
Database:
Firebase Pic
StartActivity:
XML Pic
Here is my StartAytivity.class code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_start);
Button run = findViewById(R.id.button2);
run.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(StartActivity.this, MainActivity.class);
startActivity(intent);
}
});
FirebaseApp.initializeApp(this);
watcher = findViewById(R.id.textView3);
player = findViewById(R.id.textView4);
onlineCount();
}
Here is my OnlineCount code:
public void onlineCount(){
//watcher
refwatcher = FirebaseDatabase.getInstance()
.getReference("online_list")
.child("watcher")
.child(Objects.requireNonNull(FirebaseAuth.getInstance().getCurrentUser()).getUid()).child("online");
Query query = refwatcher.orderByChild("online").equalTo(true);
refwatcher.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
wcount = (int) dataSnapshot.getChildrenCount();
watcher.setText(getString(wcount) + getText(R.string._29_349_watchers_online));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
//player
DatabaseReference refplayer = FirebaseDatabase.getInstance().getReference("online_list").child("player");
refplayer.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
player.setText("1" + getText(R.string._230_player_online));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Here is my debug code:
Caused by: java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at com.bbinktattoo.nerve.StartActivity.onlineCount(StartActivity.java:65)
at com.bbinktattoo.nerve.StartActivity.onCreate(StartActivity.java:57)
at android.app.Activity.performCreate(Activity.java:7326)
at android.app.Activity.performCreate(Activity.java:7317)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)

Your issue has nothing to do with the problem your question implies. You want to know how to count your database entries. Every element in firebase is a node and can have n children and has exactly 1 parent. The relation ship between a node and its parent is 1:1 while the relation ship between the node and its children is 1:n.
So if you want to count the amount of elements you have to call the getChildren() Method on the parent node, which will return n references to the n nodes.
However, it seems like you're not initializing the Firebase SDK as supposed to. Make sure you read and understand the related docs
https://firebase.google.com/docs/android/setup
I would guess that you have not set the correct configuration parameters

Your issue is not the counting itself but Firebase seems improperly setup in your app. Make sure to follow the official guide step by step. Also check Logcat for errors and warnings from Firebase, usually there is something useful.

Related

Firebase realtime database listing data with auto increment in Java

In Firebase, I list my data by auto increment. However, when i any data is deleted, i can't new data added. Updating is being made on the last added data. I need a solution for this.
Firebase
My Source:
public class MainActivity extends AppCompatActivity {
EditText name_et;
Button button_save;
FirebaseDatabase firebaseDatabase;
DatabaseReference databaseReference;
long autoincrementid =0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
name_et = findViewById(R.id.aaaa);
button_save = findViewById(R.id.btnsave);
databaseReference = firebaseDatabase.getInstance().getReference().child("Data");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if(snapshot.exists());
autoincrementid=(snapshot.getChildrenCount());
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
button_save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String a = name_et.getText().toString();
databaseReference.child(String.valueOf(autoincrementid+1)).setValue(a);
Toast.makeText(MainActivity.this, "+++++", Toast.LENGTH_SHORT).show();
}
});
}
}
Right now you use the count of children to determine what the next number is. That works well if all sequential indexes are occupied, but (as you found) not when you delete one of more indexes in there.
The proper solution in that case depends on what you want to happen. I know of these general use-cases:
You want the list to behave like an array, which means that when you remove #3 in your JSON, the #4 and #5 actually get a new index. This will require you to change all other items when you remove one. For more on this see the answer I gave just now to another question: Firebase Remove with Javascript
You want to have an always increasing sequential index, typically referred to as a sequence or auto-increment values in relational databases. If you want this, you'll have to store the latest index that you handed out somewhere separate in the database and transactionally update that whenever you add an item to the list.
You want to put new items at the first available index, reusing the indexes of any deleted nodes. This seems to be your use-case, so we'll look at that further below.
Possible code for a solution that finds the first available id:
databaseReference = firebaseDatabase.getInstance().getReference().child("Data");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
int autoincrementid = 0;
do {
autoincrementid++;
} while (snapshot.hasChild(""+autoincrementid));
snapshot.child(""+autoincrementid).setValue("New value");
})(
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException(); // never ignore errors
}
});
A few notes on this code:
I didn't run it, so there may well be some minor errors in there. If you get any of those, please try to figure them out on your own and edit the answer to include the solution.
You probably should use a transaction here to ensure there are no conflicting updates. The logic of the loop will be the same though.

How can I read values from Firebase Realtime Database by using a Java method in AndroidStudio?

My Firebase Realtime Database has been built by loading an object of the Java class HashMap. In my Android Studio app I'm trying to write a method that takes a String (the key) as input, searches through the database and if the string is found it returns the associated Float (the value), otherwise it returns 0. How can I do this? Any help would be really appreciated!
EDIT: I've tried to follow the suggestions, adapting them to my particular case, but I didn't manage to solve the problem yet.
I wrote the following code in MainActivity:
DatabaseReference myRef;
Float tempValue;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
myRef = FirebaseDatabase.getInstance().getReference("myRoot");
tempValue=0f;
...
}
public void retrieveValueFromDatabase(String childName, final MainActivity activity){
myRef.child(childName).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Float value=dataSnapshot.getValue(Float.class);
if (value==null){
value=0f;
}
activity.tempValue=value;
//First Toast
//Toast.makeText(activity,"tempValue = "+tempValue.toString(), Toast.LENGTH_LONG).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
public void useValues(){
retrieveValueFromDatabase(childName,this);
//Second Toast
//Toast.makeText(this,"tempValue = "+tempValue.toString(), Toast.LENGTH_LONG).show();
//code using tempValue from here
...
}
If I uncomment the first toast, the correct value inside tempValue is shown, but if I uncomment the second toast, the value of tempValue shown is the default one (0.0). What am I missing?
You need to use addValueEventListener to retrieve data from the database:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("myRoot").orderByChild("name").equalTo("peter");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.i("Database", dataSnapshot.child("floatValue").getValue(Long.class));
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
})
Here, you add a reference to the root node, then query using equalTo() to check if name = peter exists in the database and return the float value.
You should read the guide:
https://firebase.google.com/docs/database/android/read-and-write

How do I pull data from firebase into android studio at the exact point in the code?

Is there any way to pull data from firebase where the code is? I currently have valueEventListeners, but they all run after the code below them, thus invalidating the following code. I want to be able to pull a value exactly where the code is, not later.
As of yet, I have not found anything online about this.
A good example of my problems in the code:
public void onItemClick(AdapterView<?> l, View v, final int position, long id) {
FirebaseAuth mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
final String uid = user.getUid();
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
cCESnapshot = dataSnapshot.child(uid).child("currChallenges").child(challengeList.get(position));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Intent intent = new Intent();
intent.setClass(this, ChallengeView.class);
intent.putExtra("snapshot", cCESnapshot.toString());
intent.putExtra("name", challengeList.get(position));
startActivity(intent);
}
cCESnapshot is null because the intent runs before the valueEventListener.
The onDataChange() is asynchronous, so the only way to use the retrieved data is inside onDataChange(), example:
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
cCESnapshot = dataSnapshot.child(uid).child("currChallenges").child(challengeList.get(position));
Intent intent = new Intent();
intent.setClass(this, ChallengeView.class);
intent.putExtra("snapshot", cCESnapshot.toString());
intent.putExtra("name", challengeList.get(position));
startActivity(intent);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
This is an asynchronous operation, when the data will arrive, the onDataChange callback will be triggered. Your startActivty code will be executed sequentially and this is why you get no value in cCESnapshot.
Move the startActivity code inside the listener.
But be careful, because each time the onItemClick click listener will be called, you'll add a value event listener. That way, you'll have multiple calls to onDataChange in each click and so multiple startActivities.
Instead, i recommend using addListenerForSingleValueEvent which will be triggered only after a single change in data.

Retrieving data from Firebase in Android activity

I read many threads regarding how to get data from Firebase database instance, but none of them worked for me.
My code in the activity:
public class Violations extends AppCompatActivity
{
TextView textView7;
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference dbref = database.getReference("save");
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_violations);
textView7 = findViewById(R.id.textView7);
dbref.addValueEventListener(new ValueEventListener()
{
ArrayList<String> Violations = new ArrayList<>();
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
for (DataSnapshot postSnapshot: dataSnapshot.getChildren())
{
Violations.add(postSnapshot.getValue().toString());
System.out.println(postSnapshot.getValue().toString());
}
for(int i=0; i < Violations.size(); i++)
{
textView7.setText(textView7.getText() + Violations.get(i) + System.lineSeparator());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
}
There is no error in there, but no data displays. I am pretty sure, my problem is connecting to the right instance and retrieving the data.
Firebase data, are like this:
Can someone please help me in there?
Thanks you in advance.
Initialize the Firebase database & the DatabaseReference inside onCreate() method:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_violations);
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference dbref = database.getReference("save");
...
..
Also, the reference you are getting is save but the Firebase database shows that is : you violate .... You may try changing the name to save or getting the right data : you violate ....
Try to use addListenerForSingleValue() instead of addValueEventListener(). Hope it helps. And change your firebase link save to you violate your own speed limit with
I cannot see in your database schema o reference named save but I see one named You violate your own speed limit with, which mush be used in your reference in order to be able to get data from the database. So to solve this, please use the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = rootRef.child("You violate your own speed limit with");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
ArrayList<String> violations = new ArrayList<>();
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String speed = ds.getValue(String.class);
violations.add(speed);
Log.d(TAG, speed);
}
//Do what you need to do with y our violations list
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage());
}
};
ref.addListenerForSingleValueEvent(valueEventListener);
The result in your logcat will be all those values:
3 km / h at time: ...
3 km / h at time: ...
//an so on

How to update only specific field on Firebase Database on android

i was trying to update only one field when user clicks a button
here is the database
i need to update report_status when user clicks a button
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
report_value=Integer.parseInt(arrayforreport.get(posi));
report_value++;
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//i need to update report_status by id
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
In order to update a value in your Firebase database there is no need to attach a listener, that is needed only when you need to read data. So to update a particular node, you only need to use setValue() method directly on the databaseReference object.
So assuming that the type node is a direct child of your Firebase database, please use the following line of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
rootRef.child("type")
.child("Whatsapp")
.child("Shopping Deals")
.child(shoppingDealId)
.child("report_status")
.setValue("newValue");
In which shoppingDealId is the id of a particular shopping deal. You can get this id using the following line of code:
String key = ref.push().getKey();
addValueEventListener is to retrieve the value, you don't need it to set the value.
First get the key from DatabaseReference then use setValue to change the value.
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
report_value=Integer.parseInt(arrayforreport.get(posi));
report_value++;
DatabaseReference databaseReference = adapter.getRef(position);
String key = databaseReference.getKey();
databaseReference.child("type").child("Whatsapp").child("Shopping Deals").child(key).child("report_status").setValue(report_status);
}
});

Categories

Resources