Firebase Database Persistence Bug in Android - android

I have been using and testing my Android app thoroughly for the last 2 weeks.
I am using the Firebase Realtime Database exhaustively in my app and the most important thing is that, my app needs to work offline seamlessly.
I have a splash screen, where I sync all the data for a particular user node just while starting and proceed.
I using keepSynced(true); and setPersistenceEnabled(true); for sure.
Have noticed a serious issue, which is causing a lot of problem.
Scenario 1
I run the app for the first time with internet connection, the app works fine.
Scenario 2
I run the app for the first time without internet connection, nothing works. No callback is fired.
Scenario 3
I run the app consecutively with/without internet connection, it works fine.
Scenario 4
But, when I run the app after 1 or 2 days without internet connection, nothing works. No callback is fired.
I seems that the disk persistence is cleared automatically, that is why the data is not available offline and no callback is fired.
So, how can I control when the disk persistence is cleared? Is there a way to make sure that the persistence is never cleared? Is there a way to configure the size of the disk persistence also?
EDIT
This is what I am doing in the onCreate() of my application class.
private void initializeFirebaseDatabase() {
if (!FirebaseApp.getApps(this).isEmpty()) {
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
firebaseDatabase.setPersistenceEnabled(true);
}
}

Check this link out com.google.firebase.database.DatabaseException: Calls to setPersistenceEnabled() must be made before any other usage of FirebaseDatabase instance I guess this question is similar to the one in the link and its solved.

I had the same problem, with a Splash screen setting setPersistenceEnabled(true) there, but when I called finish() and tried to open the app again got the error.
Solved it killing the app instead of Calling finish().
I use OnBackPressed() to finish the activity and a Boolean isFinishing flag, to distinguish between sending the app to background and killing it.
And finally I kill it in OnDestroy() with:
android.os.Process.killProcess(android.os.Process.myPid());

Related

Maintaining connection to Firebase realtime database after app is closed if there is data that is still queued to be stored?

I'm using Firebase's realtime database on Android and the way I understand how it works is that even if the app disconnects from the network, Firebase will simply queue the transactions that the user has initiated and then perform then when connectivity is resumed. This works really well but if the app is closed then this queue seems to be discarded.
The Firebase docs on handling offline capabilities states the following:
Transactions are not persisted across app restarts
Even with persistence enabled, transactions are not persisted across
app restarts. So you cannot rely on transactions done offline being
committed to your Firebase Realtime Database. To provide the best user
experience, your app should show that a transaction has not been saved
into your Firebase Realtime Database yet, or make sure your app
remembers them manually and executes them again after an app restart.
But as far as I know, there is no way of knowing whether or not data has finished being written to the database.
How exactly would you go about making the app manually remembering what still needs to be written to the database? Is there some way of accessing the queue of transactions that is yet to be carried out? Or is there some way of keeping the app running in the background after being closed that could just sync the data when connectivity resumes?
Thanks in advance.
But as far as I know, there is no way of knowing whether or not data has finished being written to the database.
There actually is. The Transaction.Handler interface has a [onComplete method](https://firebase.google.com/docs/reference/android/com/google/firebase/database/Transaction.Handler.html#onComplete(com.google.firebase.database.DatabaseError, boolean, com.google.firebase.database.DataSnapshot)). The boolean that is passed to that argument is a flag to indicate if the transaction was committed:
committed
True if the transaction successfully completed, false if it was aborted or an error occurred
For more information, see the Firebase documentation on transactions.
I think I had the problem you are facing, in my case was a simple confusion. That Firebase warning is not about "transactions" in general, is about the "transaction" method provided by them.
In Android this is reference().runTransaction().
The "transaction" method is used to validate data first, by example, if more than one user can subscribe to an event simultaneously, you can make sure that the last vacant was available.
Since the "transaction" method query the database gives you the data, and the upload data, if there is no network connectivity there is no way to make sure that will work on app restart because there was never a first query to see the data you have to validate.
This seems logical to me, a "transaction" method will create a sort of bridge between the client and the database, this is not random, but because is part of the business logic, then you should warn the user visually that their changes might not be saved since it is offline, or even if it is sensitive not allow the user to do it.
In other cases, the data is indeed stored locally and then uploaded when the app is restarted. So if you do something like
reference.child(key).setValue(myObject);
Thant change will be local until the next time user has an internet connection.
You have to make sure to add the keepSynced to the references you actually need. Setting the syncing to the root, won't solve the problem as a waterfall, make sure to be specific with nodes you need to keep synced, this way the user will see the changed reflected visually in the app.
//Won't work
DatabaseReference root = FirebaseDatabase.getInstance().getReference();
root.keepSynced(true);
//This will work
root.child("event_list").keepSynced(true);
root.child("user_events").child(uid)keepSynced(true);

Android, Xamarin: How to make absolutely sure that a user gets delted once the app is destroyed?

I have a bit of a problem:
I am working on an instant chat application for android where I need to make sure that a user gets deleted from the database as soon as he or she closes the app. There is this line of code:
Firebase.Instance.CurrentUser.Delete();
Which deletes the current user. I could put a LogOut button and have this line integrated into the Onclick Event which will delete the user from the database. But chances are that peeps won't click that button but instead just close the app from the taskmanager. (Or maybe their phone runs out of battery?)
Well, the problem is obvious: I cannot have more than 100 users connected to my server ( for monetary reasons), so it is vital for me to have the user and all of his records deleted upon closure of the app.
My next thought was to put the above line of code into the OnDestroy() Method, yet I came to realize that this method is sometimes not called and also doesn't seem to be able to delete the user even when called (Maybe it is too much work? I don't know).
What else could I be trying?
You are solving imaginary problem. You cannot have more than 100 users actively connected to the Firebase at the same moment, but you can have more than 100 users.
You don't need to delete users, you need to detach all observers in onPause() and that is all.

Close Firebase database connection when leaving Android app

I made an Android app which receives realtime data from Firebase database. In my main Activity the user has to log in with e-mail and password and by success it opens a new Activity, which receives data.
It seems to be, that when the user leaves my app, the Firebase connection is still established. That is not good for the battery.
How is the way to manage the connection for closing and reopen the app? I think I need to use onPause() and onResume(). I found something like goOffline(), but I cannot found this method in the new Firebase.
Yes, you may use the activity lifecycle methods like onPause(), onStop() on onDestroy() to close your connection.
Also, it seems Firebase still has a goOffline() method - https://www.firebase.com/docs/android/api/#firebase_goOffline.
An alternative to using the goOffline() and goOnLine() methods is to remove ValueEventListeners and ChildEventListeners when they are no longer needed. My experience (with SDK 3.X only) is that Firebase will automatically disconnect after about 1 minute when then are no listeners registered and no other reason to be connected, such as a pending write.
I've recently added Firebase database to my App, but noticed occasionally high battery usage, and it appears to be linked to my App keeping the radio active (radio active for 1 hour 30 mins in 10 hours, but app usage approx 5 minutes).
I believe that this is linked to Firebase database as I have disabled the in-app purchase broadcast receiver which is the only other network element. I don't have any open listeners (I'm using single-value events), but some of the transactions are mutable, so it's possible one of them has failed to complete, and is regularly re-trying. Database persistence is off.
I'm currently testing the following simple addition to pause/resume (got to get some code in the answer :-) ) :
#Override
protected void onResume()
{
super.onResume();
if (FirebaseDatabase.getInstance() != null)
{
FirebaseDatabase.getInstance().goOnline();
}
}
#Override
public void onPause() {
super.onPause();
if(FirebaseDatabase.getInstance()!=null)
{
FirebaseDatabase.getInstance().goOffline();
}
}
And so far, so good. ** The main thing to note is switching activities, requires you to have this in every app that uses Firebase (I had a sign-in activity which stopped functioning as it was reading the username from the database) **
5/12/16 - update after a couple of weeks of testing. The high battery use returned yesterday. I'm testing primarily on Lollipop, and there's loads of complaints about the radio being left open for other apps. Others testing my App on Android M don't report any problems, so it's possibly a Lollipop issue. I'm going to continue to test, this time trying to remove unnecessary transactions to see if this helps... Hope this helps someone.

android app hangs when run for a long time

I have an Android app which listens to a port and updates the screen based on what it hears. This works flawlessly. The problem happens when I leave the app running for say 20-30 mins. During this time the screen would have gone blank for power saving (display). After this point, the app either becomes unresponsive or totally hangs. I doubt if it's memory leaks. Can't figure out how to go about debugging this issue. Any pointers? TIA
May be there are variables that are lost, try to save and restore the state of your Activity using the methods onSaveInstanceState() and onRestoreInstanceState().
check https://stackoverflow.com/a/151940/1434631
I was building a widget for android and same thing was happening to me. I believe the problem is that process is destroyed and started again from time to time, and then all your variables lose value. You should use content provider to store them and then obtain them when lost.

My application object's onCreate was called while my app was running, and my app reset. What would cause this?

I have a multi-Threaded android application. One of the things my application does is saves various data to a database on a server via webservices. I was trying to figure out why things were not saving to the server correctly, and saw in one of my log files, that the application objects onCreate() method and constructor were called in the middle of one of the requests going up to the server. These request are in the background and are sent via an intentservice.
I have my application set to catch unhandled exceptions and log them, and I did not see anthing in there. The application onCreate() and constructor was called, the application was kicked back to the main/first screen, the user then had to re-login, and it seems that the database was wiped(which is something else I am wondering about).
So, my main questions are: Why did the application object onCreate() and Constructor get called(why did the application get killed), why did the database get wiped when the above happened because if I do a force stop from inside of settings, applications, it never kills my db.
two words: low memory
I have the same problem. No solution for now. Try to take advantage of the onLowMemory() method, maybe the OS will spare your app.
My application object gets restarted randomly (not any time) when I am coming back from an external application (ex. camera or gallery) for onActivityResult().
Hope that helps someone.
If the application is not a service, but a 'normal' application that calles your intentservice, it is subject to the normal application lifecycle: this means it will get killed when in the background.
Look for the explaining image on this site: http://developer.android.com/guide/topics/fundamentals/activities.html
Take note of the red "Process is killed" part on the left, an the subsequent "onCreate()" afterwards.
I've actually seen very similar behaviour that was caused by a NumberFormater trying to parse a null String. After the call to parse(), the application simply reset itself back to the splash screen with no errors at all. Wasn't fun to track down, pretty much stepped through half the code base trying to find out what was happening - the debugger disconnected and the app restarted when stepping past the parse call.

Categories

Resources