I'm trying to find out how far the offline capabilities of Firebase on Android actually go.
As far as I understand, it should be possible to make the Database "persistent" with FirebaseDatabase.getInstance().setPersistenceEnabled(true);
The documentation reads:
The Firebase Realtime Database stores data returned from a query for use when offline. For queries constructed while offline, the Firebase Realtime Database continues to work for previously loaded data. If the requested data hasn't loaded, the Firebase Realtime Database loads data from the local cache. When we come back online our data will load and reflect the query.
Is this also true when the offline state is beeing forced by goOffline?
In this question the user got an answer from firebase support:
While you can use goOffline() to force the client offline for a long time, performance will deteriorate over time. The Firebase clients will queue intermediate state changes, instead of updating the stored state as the server does.
Does this mean the "local database" isn't actually updated like it would be when offline due to connection loss?
Because most of the time any query or value event listener doesn't come back, onDataChange is never called as is onCanceled (I checked!)
If only the connection is lost, it actually works as advertised, although sometimes with up to a minute delay, which seems to be a problem on its own.
What is then the intention of even offering the goOffline() method if this just stops the interaction with the database completely?
In my implementation the app starts offline, with an anonymous authentication. So in the beginning of course the "local database" will be completely empty. But shouldn't the value events at least fire onDataChanged with an empty datasnapshot?
I tried staying online until I received the anonymous UID and added an empty entry into firebase database, which then is queried/cached. After that if I call goOffline, no more entries can be added and no more queries will be answered.
Similar to the above mentioned question, my plan is to offer the user the option to stay offline, with of course the downside of the build up of stored write events in the local cache (but that shouldn't be that big of a problem as there isn't that much data)
So how can I make this work if even possible at all?
The only thing I can see is to have some different database solution in the beginning for actual offline capabilities which has to be translated & transferred to firebase when the user chooses to go online.
Related
I am developing a chat app that uses firebase database to store data. The usual approach while developing a chat app is to keep the database nodes synced so that you access the messages offline. So the problem rises when I implement the firebase offline capabilities to keep the data nodes synced. Firebase suggests two required steps for accessing data offline:
Enabling disk persistance
this is enabled according to the documentation by using this line of code (in my case I add it in application class):
FirebaseDatabase.getInstance().setPersistanceEnabled(true);
and
Keeping a node synced
this is enabled by simply adding keepsynced(true) to any databasereference that you wish to keep synced, like this:
ChatNode.keepSynced(true);
What is the difference between the two?
According to the firebase team answers on this site, I deduced that:
1) (Disk persistance) stores the data on the device disk to use them when needed, and data is stored wether you write data or read data.
a) If you write data offline: data is stored on disk and is sent to database when you go online again.
b) If you read data offline: the listener that was read online and was kept in disk and stored, you will be able to read it offline from disk.
2) (keep synced true) will keep a database reference synced in 2 ways:
a) If you are also using (disk persistence) with (keep synced) you will be able to keep data synced on disk ... which seems to be the default behavior of (disk persistence).
b) If you are using (keep synced) alone then you only store to what is known as the app memory.
The problem
I did set both of the methods, but my app is now very laggy and slow and sometimes stops on its own.
The question
If all the things that I said above are true, then would this method of offline capability be a heavy load on my app?
If I kept many listeners synced and set persistence enabled, then would the disk become full of data? Should I clean the data? Is the data on disk cleaned by itself in both methods? Is data cleaned by itself from memory?
I want to avoid the lagging and slow response in my app, thanks for your help.
You are right about your assumptions. If you are using FirebaseDatabase.getInstance().setPersistenceEnabled(true); means that Firebase will create a local copy of your database which also means that every change that is made while you are offline, will be added to a queue. So, as this queue grows, local operations and application startup will slow down. So the speed depends on the dimension of that queue. But rememeber, Firebase is designed as an online database that can work for short to intermediate periods of being disconnected and not as an offline database.
Second, if are using many listeners, don't forget to remove the listener accordingly to the life-cycle of your activity like this:
databaseReference.removeEventListener(valueEventListener);
I'm writing an Android application that uses the Firebase RealTime Database and Firebase Cloud functions. Several of my cloud functions are triggered by writes to the RealTime database and are used further process data saved by the Android client application.
I'd like my app to handle network connectivity changes gracefully. I understand that Firebase handles loss of connection by saving changes to the RealTime database locally and then syncing the changes to the server when connectivity is restored. This is well documented in the Firebase Documentation.
In my case though, since I need the Cloud Function post-processing of data saved to some paths to have occurred before it is useful, there's no point in having this data saved if it isn't going to make it to the server (and therefore trigger a Cloud Function), in a timely manner.
I'm using the updateChildren function from DatabaseReference to save the data and have a CompletionListener attached to monitor the outcome. I thought I may be able to use the DISCONNECTED and/or NETWORK_ERROR DatabaseErrors to identify cases where my data won't be reaching the server. However, if I interrupt the network connection before updateChildren is called, there aren't any errors generated. In this case, Firebase has likely saved the data locally with plans to sync it later, so updateChildren is considered to have been completed successfully.
My questions then are:
When are the DatabaseErrors DISCONNECTED and NETWORK_ERROR actually used by Firebase? Can I use them in some way to help manage connectivity issues?
What are the best practices for handling cases where Firebase data must make it to the server in order to be useful? Should I really just be POSTing my data to the Cloud Function directly?
Does Firebase have any notion of a timeout period that can be watched and data invalidated if it isn't synced within a specific period of time?
Yes, I recognize that I can use a listener attached to /.info/connected to detect changes in the connection state, but I'd rather be able to react and gracefully handle my case as it happens. I feel that my usage of the Realtime database together with Cloud Functions is common enough that there must be generally accepted way to implement it.
Any thoughts appreciated. Many thanks.
Did you try OnDisconnect method of firebase realtime database ?
I have an application that pulls some simple data from Firebase Realtime Database, and to make things simple here is the flow that I want to have.
If phone is connected to the internet:
Get the data from the firebase database
If phone is offline
If there is data in firebase cache -> get data from cache
If there is nothing in firebase cache -> show some default data stored locally in app
The problem is that I don't see possible way to detect if data is available in firebase cache. So when phone is offline I cannot see if I should display the locally stored data or cache from firebase database.
Agree above answer, Firebase will do it for you, if you do it in the right way. In order to solve your problem, you should understand the difference between the two approaches of firebase offline cache - reading-from-memory and reading-from-disk.
Read this article -> https://pamartinezandres.com/lessons-learnt-the-hard-way-using-firebase-realtime-database-c609b52b9afb
in your case, just add, FirebaseDatabase.getInstance().setPersistenceEnabled(true); to enable reading from disk
and add yourReferenceForFirebase.keepSynced(true); to keep the data synched
then your app will work as you expected.
But, only this part: "If there is nothing in firebase cache -> show some default data stored locally in app", seems impossible.
Firebase does it for you.
Firebase applications work even if your app temporarily loses its network connection.
Also firebase apps automatically handle temporary network interruptions.
Cached data is available while offline and Firebase resends any writes when network connectivity is restored.
If it is not enough and you need to work offline you can also enable the disk persistence just adding:
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
More info here.
EDIT:
There is no way to know whether a value comes from the local cache or from the remote server.
There is only a way to know if your app is currently connected to the Firebase Database server.
To achieve it you can detect the connection state by listening for the .info/connected value.
Is it possible that an application's listview updates the data from Firebase without even opening the application?
I am working on a restaurant application which has to work offline, so the user must NOT open the application to get the new menu, rather it must be updated automatically (whenever the user is connected to internet) even if the application isn't opened. Is it possible to be achieved?
I think you're confusing updating the DATA with updating the MENU. A menu is a rendered object - if you're driving it with a listview, naturally it won't be updated when the app isn't running because there's no reason to draw a listview update if the listview isn't being shown.
But you can absolutely update the data, and we do this in News Rush to give the user access to new data while offline, if they were online earlier. Just make sure persistence is enabled and run the same query that drives your listview. Make sure the path/params are identical. Persistence will remember that data and if the user is offline the new menu will still show correctly the next time the app is started.
You should update it outstide the app, but, you can enable offline capabilities,
Enabling Offline Capabilities on Android
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
Firebase apps work great offline and we have several features to make
the experience even better. Enabling disk persistence allows your app
to keep all of its state even after an app restart. We provide several
tools for monitoring presence and connectivity state.
To keep data fresh:
Keeping Data Fresh
The Firebase Realtime Database synchronizes and stores a local copy of
the data for active listeners. In addition, you can keep specific
locations in sync.
DatabaseReference scoresRef =
FirebaseDatabase.getInstance().getReference("scores");
scoresRef.keepSynced(true);
The client will automatically download the
data at these locations and keep it in sync even if the reference has
no active listeners. You can turn synchronization back off with the
following line of code.
scoresRef.keepSynced(false); By default, 10MB of previously synced
data will be cached. This should be enough for most applications. If
the cache outgrows its configured size, the Firebase Realtime Database
will purge data that has been used least recently. Data that is kept
in sync, will not be purged from the cache.
Read more:
Enabling Offline Capabilities on Android
I am planning to switch to Firebase as my local and online database for my Android app. As per the docs, Firebase stores changes to the local database first and then pushed it to the online DB when network is available.
In my app, I would be putting some really sensitive data about the user in the database. So here are my questions,
How secure is the local Firebase database?
How difficult is it for a well-intentioned hacker with the right tools to hack it?
Is it just a simple JSON file like the online database, which anyone with root access can open?
Thanks.
In a general sense, Firebase Realtime Database can be used while offline. However, the expectation is that the app is supposed to be connected most of the time, and changes to the database that happen while offline will be synchronized when it has connectivity. 100% offline use is not really a supported use case, because the canonical data store is on the server.
The local copy of the database is limited to (10MB, at least on Android this is the case). If you intend to write to the database beyond this limit while offline, it will evict part of your cached data to make room for whatever you’re adding. Then, you will no longer be able to read those evicted values until the app goes back online. Worse, managing a growing list of writes to apply when back online is taxing on the app, so you don’t want to plan a lot of writes while offline.
Also, if you have permissions or validations defined for your database, these can only be checked on the server. So, if you’re doing offline writing to your local cache and you no longer have an active listener, you may never know if those writes fail.
Because of these caveats, it’s better not to think of Firebase Realtime Database as an “offline” database. It’s better to think of it as a “synchronized” database that actively syncs to the server while connectivity is present.