Online users in firebase chat app - android

I am building a chatapp using firebase database. I need to show online users, how can I do that?
I already tried this
connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected");
connectedRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
boolean connected = snapshot.getValue(Boolean.class);
if (connected) {
} else {
}
}
#Override
public void onCancelled(DatabaseError error) {
System.err.println("Listener was cancelled");
}
});
But I don't know how to use it, please help me.

To achieve this, you need to create a new category in your Firebase database called onlineUsers. Every time a user is connecting to your app, add him to this newly created category. Then you can query on that category to see the exact number of users like this:
int numberOfUsers = dataSnapshot.getChildrenCount();.
If you need to display a green dot for online members in a list of members, then the way in which you need to add these users in this new node, is to have the id as it's key and the value as a boolean. The default boolean value must be false, which means that the user is not logged in. Your new node should look like this:
userId1: true
userId2: false
userId3: true
Every time a user signs in, change the value of that user from false to true. To display them, just query your database accordingly to see which users have the value of true.

If clients have a server to work up against,
each client connection is reported to the server, which increments a coutner.
And for such increment server is notifying (e.g. using Firebase data notification message) all clients.
This is how all clients will have indication about how many are conencted at any given time.
(When a new user is logged in, server is sending data about current number of connections)

Related

getChildren() method in firebase is not working correctly when two users uses the mobile app at same time

I want the children count in firebase to assign token. So I was used getChildren() method. This method gives the count and the count was incremented and assigned to each member. The problem raised when two users uses the application at a same time. For example, the children count was 10. If both the users uses the app at same time then both users get count of 10 and it increments gives 11. Hence both the users get token 11. If other user who was use the app after the above two, gets the correct number as 12 and it increments to 13 and 13 was assigned to that user.
databaseArtists.orderByChild("artistName").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
++ct;
Log.d("log", "onDataChange: " + dataSnapshot1.child("Appointment").child(bdate).child(session).child(docname).child("artistName").getValue());
}
});
Is there anyway to solve my problem?
You need to have a progressive number constantly growing on user demand, and you have to make your users modify concurrently.
Firebase offers transactions to solve problems like this.
You will have a structure like this:
{
...
"tokenGenerator": {
"current": 0
}
...
"users": {
"userA": {
...
"token": 3
}
}
When you need to assign a token to a user, e.g. userA the user's client will run a transaction on $.tokenGenerator.token increasing its value and setting it to $.users.userA.token.

Firebase send notifications to users

I am trying to send notifications to some users that I have on my database on Firebase, I know that Firebase has a section related to notifications, but I just saw an example to how push notification directly from the Firebase website, I have an event in my app, when that event is created I want to send the notification to all users so basically this is the event:
public void createEventGame(View view){
Match match = new Match(userId,gameEventNameTxt.getText().toString(),dateMatch);
String key = myGameRef.push().getKey();
myGameRef.child(key).setValue(match);
/*if(radioMatchSelected){
}*/
if(radioEventSelected){
final HashMap<String,Boolean> matches = new HashMap<String,Boolean>();
matches.put(key,true);
Spinner spinner = (Spinner)findViewById(R.id.spinner);
final String text = spinner.getSelectedItem().toString();
Log.d("sizebb",text);
myRef.child(userId).child("FriendLists").child(text).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
long size = dataSnapshot.getChildrenCount();
Log.d("sizebb",String.valueOf(size));
for(DataSnapshot s: dataSnapshot.getChildren()){
friends.put(s.getKey(),false);
}
if(size < 10){
Snackbar snackbar = Snackbar
.make(findViewById(android.R.id.content), "You need to have atleast 10 friends in your group, go to your friendlist and add some friends!", Snackbar.LENGTH_LONG);
snackbar.show();
}
Event event = new Event(gameEventNameTxt.getText().toString(),hourWeek,userId,matches,friends,dayOfWeek);
myEventRef.child(event.getName()).setValue(event);
/*else{
friends.put(dataSnapshot.getKey(),true);
}*/
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Now how can i deal with notifications, is there any good tutorial talking about it? I can't find it, or do I need to deal with notifications with the database on firebase directly?
Not clear about the question, will try my best.
So you can send firebase notifications through console to all the users. You can also group users based on topics they subscribed and also to single devices (You need a token to send individual devices). Firebase cloud messaging. Also, you can send notifications from your program logic.
Look at the various types of notifications that you can send here.
Another place to quick start with firebase is their github repo. Almost you can find a quick start project for everything. Firebase Github repo
Have all the friends you want to send the Notification to subscribe to a common topic.
When the event occurs, call the Firebase REST API and send the notification to this topic and all your users should get them. Notification tag or Data tag or both is upto your usecase. I prefer Data tag only so as to ensure that everything that happens stays in the code that i write and not system code.
What topic name you choose and which people subscribe is upto you. This should get you started.

Firebase database snapshot returns null when I take a datasnapshot with usertoken string (sometimes), why?

I just started storing usertokens in my database for notification purposes. I have no problem storing and retrieving the data except with certain usertoken string values. But when I take a datasnapshot with a usertoken it returns null, only sometimes though.
My listener looks like this (just a regular listener):
udRef.addListenerForSingleValueEvent(new ValueEventListener () {
#Override
public void onDataChange(DataSnapshot datasnapshot) {
User user = datasnapshot.get value(User.class);
//do something with data here
//eg. Log.e("ERR", String.value Of(user));
//returns "null" for SOME users only, keep reading.
}
#Override
public void onCancelled (DatabaseError databaseError) { ... }
});
When a user creates an account, it automatically inserts a string token that looks like this:
"cL_AEuSZa1I:APA91bF9R-dDetqrSNMQMzAoHRmLOHXK2acK_zJLhFhZ5IhvNChPSx4P943GirVwsy5walc0RrvyGnMm49oLxNJ-uKsGRCELhJ-9kwnPmdHOyWJWz0Esm_Y0MB7BypNUuQ4qZQmoW5nO"
Tokens are used for push notifications using FCM. This is refreshed automatically as recommended by the FB guys. The token above isn't valid, in fact this very usertoken made my datasnapshot not work so I had to manually remove it! And yes, immediately I removed it I was able to capture the snapshot, it didn't return null anymore.
I do not know what I'm doing wrong, but when I look (with my eyes, not a script) at the usertokens in the database I can tell which ones will be troublesome. This is how:
All usertokens are too long, so Firebase's web console cuts them short like this "gftgvdgGhbgfc_fggg..."
All the troublesome tokens get cut also but without the 3 dots or closing quotes, they look like this "gftgvdgGhbgfc_fggg but when expanded they are normal like the working ones (length is same).
I have 30 users so I can easily go through them all :D
This is how my data looks (roughly):
"fhgfFghDfgghhfDDf" : {
"username" : "a_string_here"
"userPic" : "looong_string_link_to_fb_storage"
"usertoken" : "long_user_token_like the_one_in_question"
},...
Am I storing the tokens wrongly?, should I convert them to some other data type? Too many 'gotchas' in FB :(
Please note, I DO NOT have problems with anything else except the usertokens making my datasnapshot null, so any mistakes in the code are just typos (I typed this question from my phone referencing my laptop screen... don't ask)

Cannot save a ParseUser that is not authenticated, updating an object with a relation with a ParseUser

I am workin in an Android Project using parse.com and I have a table Requirement which has a column called "user_assigned" which is a relation to ParseUser. This user is in charge to modify the requirement even if he didn't create the Requirement, but when this user try to update the requirement values, it returns "Cannot save a ParseUser that is not authenticated"
P.D. All the ACL in the requirement are public, write and read.
// setting write permission
ParseACL postACL = new ParseACL(ParseUser.getCurrentUser());
postACL.setPublicWriteAccess(true);
postACL.setPublicReadAccess(true);
requirement.setACL(postACL);
requirement.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
callback.onFinish((Exception) e, requirement);
}
I don't want to change the user assigned I want to change other fields but the way I get and change the relation from the table is
ParseRelation<ParseUser> relation = requirement.getRelation("user_assigned");
relation.add(requirement.getUserAssigned());
I found a solution,
What is happening: 3 tables, Project, User and Requirements where a Requirement has a pointer to the Project and the Project has another pointer to an User called projectOwner. The problem happen when another user different to the projectOwner read some values of the projectOwner associated with the Requirements. If the new user wants to save some changes in the Requirements parse return the error "Cannot save a ParseUser that is not authenticated".
To fix it, i only read the objectId of the projectOwner and after I got the rest of the attributes of the ParseUser calling
ParseUser.getQuery();
query.get(objectId)
In other words, in my class Project, i have a method to get the attributes. When I want to get the projectUser (pointer) i got it like this:
User uTemp = (User) this.getParseUser("owner");
if(uTemp != null){
// this.setOwner(uTemp.extractAttributes());
uTemp = uTemp.getObjectId();
uTemp = UserDAO.getUserByObjectId(uTemp.getObjectId());
this.setOwner(uTemp);
}
I could fixed thanks to this, I hope it can be helpful.

Parse.Com Error saving relation

ParseRelation<ParseUser> relation = profile_user.getRelation(ParseConstants.KEY_LIKES);
relation.add(ParseUser.getCurrentUser());
profile_user.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException arg0) {
Toast.makeText(ViewProfilePic.this, "Liked!", Toast.LENGTH_SHORT).show();
}
});
In this program when a person visits a particular profile he can like that profile.
profile_user is a ParseUser object which is a particular profile. If the user clicks on the like button the current user should be added to the profile_user 's "likes relation. But this does not happen . Please help!
I found the solution. By default parse does not allow you to save unauthenticated users for security reasons I.e only the current user value can be modified. I overcame this using parse cloud code.

Categories

Resources