I'm making chat application with Firebase Realtime Database.
I Made
public class MessageAdapter extends BaseAdapter implements ChildEventListener{
...
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Message msg = dataSnapshot.getValue(Message.class);
this.addItem(msg);
this.notifyDataSetChanged();
}
...
}
and this MessageAdapter refresh my Listview when data is added to Firebase.
But
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Message msg = dataSnapshot.getValue(Message.class);
this.addItem(msg);
this.notifyDataSetChanged();
}
onChildAdded Method is called whenever I started app. I want to load Message Only after User starting app. It loads every messages which is stored in my Firebase Realtime Database.
Is there a way to load only new message after user starting application? and furthermore I want to make this to load specific number of messages like if I set the number as 5, when user start an app it loads from Firebase Database only 5 stored messages.
Okay, so there are a couple questions here, first would be to make the app wait before querying the data base. To do this I would suggest pausing the thread for a few seconds while it loads the data using a handler.
handler1.postDelayed(new Runnable() {
#Override
public void run() {
// Your Database Reference Listener
}
}, 1000);
also to listen to only a few from firebase just change the listener like so
yourDatabaseReferance.limitToFirst(10).addChildEventListener(new ChildEventListener()
Related
is it possible for android to automatically update the data that is stored in real time database? For example, the data that is gonna be stored in my firebase real time database is going to be constantly changing within seconds because it is connected to a back-end system that triggers its change. Could it be done that every time the data has changed, the textView in my application that shows that data gets updated every time as well ? For now, I have a button that updates the data on click, but is it possible to update it automatically without a button? My code looks like this for now :
a = findViewById(R.id.insidetempView);
b = findViewById(R.id.filterView);
c = findViewById(R.id.humiditytextView);
d = findViewById(R.id.CO2textView);
Button saveButton = findViewById(R.id.numbersButton);
saveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
reff = FirebaseDatabase.getInstance().getReference().child("Numbers");
reff.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String CO2 = snapshot.child("CO2").getValue().toString();
String filter = snapshot.child("Filter").getValue().toString();
String humidity = snapshot.child("Inside_humidity").getValue().toString();
String temp = snapshot.child("Inside_temperature").getValue().toString();
a.setText(temp);
b.setText(filter);
c.setText(humidity);
d.setText(CO2);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
});
This blog post should provide you with the solution you need go through it and you will be able to do what you want https://firebase.googleblog.com/2017/12/using-android-architecture-components.html
it has information on using android Architecture Components with Firebase Realtime Database. and when you observe LiveData you can implement all changes instantly
I use firebase real time database.
I have set : "FirebaseDatabase.getInstance().setPersistenceEnabled(true);"
So ok perfect, when I'am offline, all the data are being loaded just like I was online.
But I have a few questions.
In my app, I have chat group with few people.
Let's assume someone is in a group and is offline. He writes what he wants in the chat and the messages will be send when he will turn online.
But, while he is offline, someone kicks him out of the group. How do I tell firebase :
if (the user still belongs to the group)
{
sync messages
}
else
{
don't sync messages
}
I have tried to check if the users still belong to the group while he is offline but when it goes back online everything has already been checked in offline mode so the data are just sent without reckecking again.
Let's imagine I have 50 messages in my chat. While I'am offline, I get 5 messages. When I go back online, will it redownload the 55 messages or just the 5 extras message?
I am just trying to figure out if I the firebase sync is going to cost me a lot of data or not.
EDIT
Here is the way I retrieve data from chat :
public void retrievedata() {
UserMessageRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) /**** HERE IS THE PROBLEM***/
{
if (dataSnapshot.exists()) {
DisplayMessages(dataSnapshot);
}
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
//Nothings
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
//Nothings
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) { //Nothings
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
//Nothings
}
});
}
//function to retrieve messages
private void DisplayMessages(DataSnapshot dataSnapshot) { Iterator iterator = dataSnapshot.getChildren().iterator();
String chatImage = (String) ((DataSnapshot) iterator.next()).getValue();
String chatMessage = (String) ((DataSnapshot) iterator.next()).getValue();
String nID = (String) ((DataSnapshot) iterator.next()).getValue();
String chatTime = (String) ((DataSnapshot) iterator.next()).getValue().toString();
ListOfChats.add(new ChatClass(nID, chatMessage, chatTime, chatImage));
adapter.notifyDataSetChanged();
}
Now here is the problem.
If I'am offline and go into the chat, the messages are just retrieved from disk, ok works fine.
BUT If I go online and I got 2 new messages : instead of calling the onChildAdded for the 2 news messages, it download ALL of the messages and THEN call the onChildAdded with the old child and the 2 news child. What I want, is that the 2 news messages are added to the local json file in my phone and that everyting isnt downloaded everytime I open the conservation.
So with a firebase database which is about 30KB, I got 5-10 MB of downloads everyday even If I add 2KB in it per day... (It's for university project so we are like 2 users for now)
So is there a solution to this (firebase just update the json file into the local database without downloading eveything) or do I have to do my own SQL database and make a smart sync adapter?
I am sure that firebase must have done something smart about this.
Calling FirebaseDatabase.getInstance().setPersistenceEnabled(true) merely ensures that recently received data is cached on disk. It doesn't enable automatic synchronization of the data.
To enable automatic synchronization of a node, you can call keepSynced(true) on a reference to that node.
When the Firebase client finds it already has data for a reference that it is connecting a listener to, it hashes the local data, and sends the resulting hashes to the server. The server then sends back the data that is needed to update the client's version of the data. This is typically a lot less data than the full data set.
Also see my answer here: How does firebase client know what data to sync?
My app is using Firebase and there are almost 200 users live at the a given time. Most of the users are complaining that the data doesn't load. I was using ChildEventListener for obtaining the data which keep the connection alive and reflects live changes. There is a limit of 100 connections in the free plan. I guess that is the reason my data is not loading at times. After reading the doc I found another way to read data using ValueEventListener. Below is the code I'm currently using
public void getImages() {
Query imagesQuery = FirebaseDatabase.getInstance().getReference().child("englishDps").child(mChildName).orderByKey().limitToLast(21);
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Image image = dataSnapshot.getValue(Image.class);
image.setNodeKey(dataSnapshot.getKey());
mTempImages.add(image);
if (mTempImages.size() == 21) {
mLastKey = mTempImages.get(0).getNodeKey();
Collections.reverse(mTempImages);
mTempImages.remove(mTempImages.size() - 1);
mImages.addAll(mTempImages);
setAdapter();
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
if (isAdded()) {
Toast.makeText(getActivity(), "Problem loading more images...", Toast.LENGTH_LONG).show();
}
}
};
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot imageSnapshot : dataSnapshot.getChildren())
{
Image image = imageSnapshot.getValue(Image.class);
image.setNodeKey(imageSnapshot.getKey());
mTempImages.add(image);
if (mTempImages.size() == 21) {
mLastKey = mTempImages.get(0).getNodeKey();
Collections.reverse(mTempImages);
mTempImages.remove(mTempImages.size() - 1);
mImages.addAll(mTempImages);
setAdapter();
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
// imagesQuery.addChildEventListener(childEventListener);
// imagesQuery.addValueEventListener(valueEventListener);
imagesQuery.addListenerForSingleValueEvent(valueEventListener);
}
According to the docs
"While using a ChildEventListener is the recommended way to read lists
of data, there are situations where attaching a ValueEventListener to
a list reference is useful.
Attaching a ValueEventListener to a list of data will return the
entire list of data as a single DataSnapshot, which you can then loop
over to access individual children.
Even when there is only a single match for the query, the snapshot is
still a list; it just contains a single item. To access the item, you
need to loop over the result:.
This pattern can be useful when you want to fetch all children of a list in a single operation, rather than listening for additional
onChildAdded events."
I was thinking this will solve the data loading problem but my previous version of the app will still keep using live connection and I'm still seeing random success and failures for data load call in new version of the app with more than 150+ users live right now on old version of the app. What will happen if the old version of the app opens more than 100 connection and the new version of the app tries to load data ? i.e. if 100 connections in the free plan are used will a query with
imagesQuery.addListenerForSingleValueEvent(valueEventListener);
succeed or fail ?
When an Android app first uses the Firebase Database SDK, it makes a connection to the Firebase servers. If there are at that moment already as many connection as are allowed to your database, the new connection will be rejected. The type of listener has no influence on this.
For a lot of discussions covering this already, see this list. Some good ones:
Limitation of free plan in firebase
How the Connection is calculated in Firebase
When are new connections allowed after limit of 100 concurrent connection is reached in firebase?
How exactly are concurrent users determined for a Firebase app?
How to limit concurrent connections on Firebase Android
Having looked at your code. I recommend inserting a closing connection once the read of images from json are completed. In the free package there is a limit of connections so once they read the images, they're technically still connected.
Looking at your Datasnapshot, they don't do anything but still querying the Firebase. I also recommend look into indexing too.
https://firebase.google.com/docs/database/rest/save-data
https://firebase.google.com/docs/database/security/indexing-data
I am developing a new Android app using Firebase (first time to use Firebase). and I opted to use the Persistence mode as it suits my app better.
My problem is that the app doesn't sync data to the server, hence, other devices, even if the device used to store data is online!!
Code is fine (as far as I can tell), if I disable the Persistence mode, everything works fine, but for sure I don't have the cached data on the device.
This happens in different devices and emulator as well, and the weird thing is that sometimes the devices sync, and then stop syncing again, for no reason!
I appreciate any recommendations here.
code:
My App class:
//....
Firebase.setAndroidContext(this);
Firebase.getDefaultConfig().setPersistenceEnabled(true);
Firebase.getDefaultConfig().setLogLevel(Logger.Level.DEBUG);
//...
Sending code in Message class:
//....
Firebase senderRef = new Firebase(MyApp.FirebaseURL).child("Messages").child(sender_Id);
senderRef.keepSynced(true);
senderRef.push().setValue(this, null);
//....
receive code:
//...
Firebase ref = new Firebase(MyApp.FirebaseURL).child("Messages").child(sender_Id);
Query query = ref.orderByKey();
query.limitToLast(MAX_CHAT_MESSAGES_TO_SHOW);
query.keepSynced(true);
query.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Log.d("Firebase", "Message Child Added");
Message message = dataSnapshot.getValue(Message.class);
mMessages.add(0, message);
mAdapter.notifyDataSetChanged();
}
//...
I have done in both ways:
If you want to sync with firebase server
FirebaseDatabase.getInstance().goOnline();
If you do not want to sync with firebase server
FirebaseDatabase.getInstance().goOffline();
Full code:
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
/**
* User anyone function from below as required,
* Read comment proper
*/
// If you want to sync with firebase server
FirebaseDatabase.getInstance().goOnline();
// If you do not want to sync with firebase server
FirebaseDatabase.getInstance().goOffline();
}
}
Hope this would help you.
I'm making a Android chatting app with firebase.
When Framgment is creating a view, I try to get user lisst,
But it has delay like 4~5 sec. Is there faster way to get data immediately with firebase?
Firebase firebase = new Firebase(AppDefine.FIREBASE_URL).child("friendlist-"+ac.getUserId());
firebase.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
HashMap<String,String> map = (HashMap) dataSnapshot.getValue();
mFriends.add(new ChatUserInfo(map.get("id"),map.get("name")));
mAdapter.notifyDataSetChanged();
}
}