I am currently setting Firebase Analytics properties like gender and usernames as follows:
firebaseAnalytics.setUserProperty("username", /*someusername*/);
After successfully setting them I want to be able to receive them at some other point inside my application. Somehow similar to the Firebase Database.
Is this possible? I have not found any explanation in the Firebase documentation.
Currently, it is not possible to retrieve Firebase Analytics User Property.
The best way you can do is to also store those properties to Firebase Database for each user. The database structure should look something like this
{
"users": {
"<uid>": {
"username": "someusername",
"gender": "M",
"birthDate": 758634444000
}
}
}
The uid is retrieved from FirebaseUser.getUid()
Hope this helps :)
Related
I am writting chat app with flutter, I don't know how to set the rule on firebase such only the 2 users in a group chat can write and read. This is how I store message on firebase.
String date = DateTime.now().millisecondsSinceEpoch.toString();
groupId = userId-anotherId
var ref = FirebaseFirestore.instance
.collection('messages')
.doc(groupId)
.collection(groupId)
.doc(date);
FirebaseFirestore.instance.runTransaction((transaction) async {
transaction.set(ref, {
"senderId": userId,
"receiverId": anotherId,
"timestamp": date,
'content': msg,
"type": 'text',
});
});
Thank you for any help.
Contacting database from frontend is not the most secure way.
If you are making this app for learning then it is fine.
But for production app, you should add custom logic like this in your backend and connect your frontend with that API.
Something like this.
Flutter app --> API --> YOUR_LOGIC --> DATABASE
You would need a collection of members for a group chat. That way you can very easy check with the rules just if a member uid is under the path of groupChats/{groupID}/members/{id}. You can even make a function for the firestoe rules like this:
//Checks if user is member of group
function isMember(groupID) {
return get(/databases/$(database)/documents/groupChats/${groupID}/members/$(request.auth.uid)).data==true
}
The databse structure would be:
-
groupChats
--group1
members
--userUid1
--userUid2
--group2
members
--userUid2
--userUid4
You can use a boolean or any data you want.
The solution was very simple. I saw in youtube. enter link description here
This is the security rule:
match /messages/{groupChatId}/{document=**} {
allow write, read:if request.auth.uid in groupChatId.split(" - ") }
I am creating an android application using the Firebase authentication and database.
For my app I need to identify the users after they logged in and redirect them to two different activities. (admin/simple user)
In my app I have only 10-20 users all time, and there isn't a way to register, it's a company only app.
Thanks for help.
If max users you expect is 20 then why would you need a authentication usage ( Google, Facebook ) etc. Have a simple database entry for all users as follows:
{
"app_title": "YourApp",
"users": {
"-KTYWvZG4Qn9ZYTc47O6": {
"username": "pkondedath",
"useremail": "hello#kondedath.com",
"password" : "hello123"
"userpic": "example.com/a.png",
"prevelidge" : "superuser"
},
"-KTYWvZG466ADFRR667": {
"username": "someone",
"useremail": "hello2#kondedath.com",
"password" : "hello1234"
"userpic": "example.com/b.png",
"prevelidge" : "normal"
}
}
}
Provide a user to input username( unique) and password and search through database to see if username and password matches and check his/her prevelidge and redirect to particular activity appropriately.
eg
mFirebaseRef = new Firebase("https://yourapp.firebaseio.com/").child("users")
Use above database reference to search users. You can also use the same to add new user. When adding a new user, give them default prevelidge.
This model fits well for less userbase like 20.
For more user bases( thousands, millions) you can use google authentication and use the User UID returned and create a new entry in your database(users).
Hope this helps you.
I am using a FirebaseRecyclerAdapter to inflate a RecyclerView with data provided by the Firebase Realtime Database.
I began sorting the nodes by their child date which was set to be the value of ServerValue.TIMESTAMP. I added a indexOn property to the parent node of the nodes I want to sort with the value date to the Firebase Database Rules.
"parent-node": {
".read": "auth != null",
".write": "auth != null",
".indexOn" : "date",
...
},
This worked fine but newer nodes were added to the end of my RecyclerView. As the FirebaseRecyclerAdapter and its FirebaseArray add nodes with a ChildEventListener, it means that the data was sorted from oldest to newest.
I managed to reverse this by using the negative value of ServerValue.TIMESTAMP.
private void prepareUpload() {
//mDatabase is a reference to the root of the Firebase Database
final DatabaseReference timestampReference = mDatabase.child("timestamp");
final String timestampKey = timestampReference.push().getKey();
timestampReference.child(timestampKey).setValue(ServerValue.TIMESTAMP);
timestampReference.child(timestampKey).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() != null) {
if (!(Long.parseLong(dataSnapshot.getValue().toString()) < 0)) {
timestampReference.child(timestampKey).setValue(0 - Long.parseLong(dataSnapshot.getValue().toString()));
} else {
upload(/*Starting upload with new timestamp here (this is just a dummy method)*/);
timestampReference.child(timestampKey).removeValue();
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, databaseError.getMessage());
}
});
}
Now the nodes I want to sort look like this.
{
"-K_tlLWVO21NXUjUn6ko" : {
"date" : -1483806697481,
"debug" : "old",
...
},
"-K_tmjVqTUcKXHaQDphk" : {
"date" : -1483807061979,
"debug" : "newer",
...
},
"-K_uC-AJIvDOuBzhJ3JJ" : {
"date" : -1483813945897,
"debug" : "newest",
...
}
}
They are sorted from newest to oldest and get added to the top of my RecyclerView exactly as I wanted it to be.
Coming to my personal question:
Is this a proper way to sort nodes from newest to oldest? This seems like a big workaround to me.
Am I missing something?
Thanks in advance!
Edit: I just saw that my prepareUpload() method is uselessly sending the negative value to the database again, just to receive it once again afterwards.. I will change this to calculate the negative value on client side. Please ignore this.
No, you are not missing anything. And yes, that's a proper way to sort nodes from newest to oldest.
That's just the way firebase works. Many times, you might feel like you're doing a big workaround and you think "There must be a simpler way to do this", but there's probably not.
Firebase is indeed a great platform to build your application on. But it still has a few things to improve, like the realtime database. I mean, there is no way to query your data properly. You may be able to do some basic filtering and sorting, but If you want to do more than that, you're on your own.
To help us with that, they have created the Firebase Database for SQL Developers Series which you can watch on this link. Those series explain that there is no proper/default way to structure your data on Firebase. Everytime you start a different project, you'll always have to spend some minutes brainstorming about how you can structure the data in a way that it simplifies and reduces queries for better performance.
I hope Google some day implements more searching and filtering capabilities in this data service.
What you have done is absolutely correct. The only difference is, you should have both, a timestamp and a negativeTimestamp key just in case you need either of them. It all depends on your requirements anyways.
In-fact people from firebase suggest the same. You can watch this youtube video and move to 04:40 to see the answer to your question from the firebase team themselves.
In terms of getting the sort order that you want, yes, inverted time stamps are the answer. Check out this older answer: https://stackoverflow.com/a/25613337/4816918 for more information.
The .indexOn key is only for performance optimizations (see the bottom of the "Index Your Data" page, so the correct way to request ordered data is by using .orderByChild,.orderByKey, or .orderByValue in your query. Look for the "Sort data" section of the "Work with Lists of Data on Android" page.
I have some Edittext that allows the user to enter data:
AppName
Date
Title
Quantity
User
I started a new Firebase project and it is currently a blank slate.
I am setting up my Firebase instance like this:
private DatabaseReference mDatabase;
mDatabase = FirebaseDatabase.getInstance().getReferenceFromUrl("https://myapp.firebase.io");
How I want it is everytime a new adding occurs, I would like to add it like this (AppName is the common ground for all entry):
AppName
Date
Title
Quantity
User
Date
Title
Quantity
User
...
...
AppName
Date
Title
Quantity
User
Date
Title
Quantity
User
...
...
How can I do the following:
The first time it is added, the AppName will be the parent node, and
anytime after Firebase should check to see if the parent node exist
and is the same and add it to that, otherwise create a new parent node
and add the children node to the new parent node.
I currently have my auth set up like this:
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
I had to change to true for my app to write to Firebase.
How can I:
Not register the user but only allow the app to able to write to
Firebase.
EDIT:
I am doing the following:
mDatabase.child("AppName").setValue(etName.getText().toString());
mDatabase.child("AppName").child("Date").setValue(etDate.getText().toString());
mDatabase.child("AppName").child("Title").setValue(etQuantity.getText().toString());
mDatabase.child("AppName").child("Quantity").setValue(User.getText().toString());
mDatabase.child("AppName").child("User").setValue(etUser.getText().toString());
Instead of adding, it is overwriting the previous entry. How can I append.
If I understood you, you need that not registered users could edit your database on Firebase and how to know If you added an ID.
First of all, as Ishan Fernando said, If you add data with the same id, this data will be overwrited, and using the push method, Firebase will create an unic ID to add you data
Read this: https://firebase.google.com/docs/database/android/read-and-write?hl=en
This Gist, thanks to the user realgt, could help you to know if the Appname exists or not: https://gist.github.com/anantn/4323949#gistcomment-998628
This will get all your data and you could check if you need add it or not
And, if you don't want to register users, but you need them to write the database, I think that you need to register them as anonymous users:
https://firebase.google.com/docs/auth/android/anonymous-auth
Firebase needs registered users (using social networks, email o anonymously) to modify it, so try the anonymous method. The problem is when the user get out of your app, this user will keep registered on your database. So, I recommend you, (Please, correct me if I'm wrong) to erase the user when onStop starts and create it again when onReady starts.
I hope it helps.
I have a quick question about the best practices for data structure in a firebase database.
I want users of my app to be able to maintain a friends list. The firebase documentation recommends creating a schema (not sure if thats the proper word in this context) that is as flat as possible. Because of this I thought it would be a good idea to separate the friends section from the player section in the database like so:
{
"players":{
"player1id":{
"username":"john",...
},
"player2id": ...,
"player3id": ...
}
"friends": {
"player1id"{
"friends":{
"friend1Id":true,
"friend2Id":true
}
},
}
"player2id"{
"friends":{
"friend1Id":true,
"friend2Id":true
}
},
}
}
So my questions are as follows:
Is this a good design for my schema?
When pulling a friends list for one player, will the friends lists of EVERY player be pulled? and if so, can this be avoided?
Also, what would be the best way to then pull in additional information about the friends once the app has all of their IDs. e.g. getting all of their user names which will be stored as a string in their player profile.
Is this a good design for my schema?
You're already thinking in the right direction. However the "friends" node can be simplified to:
"friends": {
"player1id": {
"friend1Id":true,
"friend2Id":true
}
}
Remember that Firebase node names cannot use the character dot (.). So if your IDs are integer such as 1, 2, and 3 everything is OK, but if the IDs are username be careful (for example "super123" is OK but "super.duper" is not)
When pulling a friends list for one player, will the friends lists of EVERY player be pulled? and if so, can this be avoided?
No. If you pull /friends/1 it obviously won't pull /friends/2 etc.
Also, what would be the best way to then pull in additional information about the friends once the app has all of their IDs. e.g. getting all of their user names which will be stored as a string in their player profile.
Loop through the IDs and fetch the respective nodes from Firebase again. For example if user 1 has friends 2, 3, and 4, then using a for loop fetch /players/2, /players/3, and /players/4
Since firebase pull works asynchronously, you might need to use a counter or some other mechanism so that when the last data is pulled you can continue running the completion code.