The App performs a simple sign up (using FirebaseAuth, FirebaseUI & Google Sign In). When authenticated successfully, I take firebaseUser.userId
and use it to fetch user profile from Realtime Database (example location /users/{userId}/someUserDataIsHere
).
In case Realtime Database returns null
object for that userId, it means the user with that userId does not exist in realtime DB, and is signing in for the first time (using Sign up with Google Account), hence a profile should be created (or in other words, user is about to register). In other case, if Firebase db returns user object, the app moves forward to the home screen.
The user profile contains some mandatory data like userId, email, and a name. But also contains some optional data like age, country etc, that could be empty.
The problem is that from time to time, when a user starts the app and the whole authentication process starts, after successful authentication, RealtimeDatabase tries to fetch user profile (for userId provided by FirebaseAuth), but error java.lang.Exception: Client is offline
occurs, returns an empty object so the app "thinks" the user is new and must be inserted in the Realtime Database, and does that (even if it said "Client is offline" like 300ms before)
How it is offline when it authenticated user a few milliseconds before, failed to fetch data for that user from the realtime database (because it is offline??), and managed to write a new profile to the realtime database few ms after?
It does not make a huge problem, because it inserts data to the same userId key (it performs update technically), but remember that I have some optional fields, and those will be reset when this case happens. It is strange from the user's perspective because the user entered some optional fields (for example age) and it disappeared after some time.
I must point out the most usual use case for this:
- User starts the app, sings in successfully and it is authenticated, provided with all the data for operating the app on a Home screen
- Exit/kills the app
- Starts the app after 2 hours
- Authenticates successfully but fails to fetch user profile for that userId (which is valid and exists in the Realtime Database) due to Client is Offline error
- Performs new user insertion successfully
Some of the dependencies that I use in the app ->
implementation platform('com.google.firebase:firebase-bom:26.4.0')
implementation 'com.google.firebase:firebase-analytics-ktx'
implementation 'com.google.firebase:firebase-auth-ktx'
implementation 'com.google.firebase:firebase-messaging-ktx'
implementation 'com.google.firebase:firebase-database-ktx'
implementation 'com.firebaseui:firebase-ui-auth:6.2.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.1.1'
implementation 'com.google.android.gms:play-services-auth:19.0.0'
Also, using this on app start:
FirebaseDatabase.getInstance().setPersistenceEnabled(false)
And this is the error I get (UPDATED with logs of some other GET request):
2021-01-30 16:12:12.210 9157-9599/com.fourexample.oab D/PersistentConnection: pc_0 - Connection interrupted for: connection_idle
2021-01-30 16:12:12.221 9157-9599/com.fourexample.oab D/Connection: conn_0 - closing realtime connection
2021-01-30 16:12:12.221 9157-9599/com.fourexample.oab D/WebSocket: ws_0 - websocket is being closed
2021-01-30 16:12:12.224 9157-9599/com.fourexample.oab D/PersistentConnection: pc_0 - Got on disconnect due to OTHER
2021-01-30 16:12:12.372 9157-9599/com.fourexample.oab D/WebSocket: ws_0 - closed
2021-01-30 16:13:07.094 9157-9166/com.fourexample.oab I/zygote64: Debugger is no longer active
2021-01-30 16:13:08.682 9157-9599/com.fourexample.oab D/Persistence: Starting transaction.
2021-01-30 16:13:08.687 9157-9599/com.fourexample.oab D/Persistence: Saved new tracked query in 3ms
2021-01-30 16:13:08.705 9157-9599/com.fourexample.oab D/Persistence: Transaction completed. Elapsed: 22ms
2021-01-30 16:13:11.708 9157-9599/com.fourexample.oab D/PersistentConnection: pc_0 - get 1 timed out waiting for connection
2021-01-30 16:13:11.713 9157-9157/com.fourexample.oab I/RepoOperation: get for query /requests/rs falling back to cache after error: Client is offline
2021-01-30 16:13:11.715 9157-9157/com.fourexample.oab D/Persistence: Starting transaction.
2021-01-30 16:13:11.718 9157-9157/com.fourexample.oab D/Persistence: Saved new tracked query in 2ms
2021-01-30 16:13:11.726 9157-9157/com.fourexample.oab D/Persistence: Transaction completed. Elapsed: 9ms
2021-01-30 16:13:11.741 9157-9157/com.fourexample.oab E/RequestService: java.lang.Exception: Client is offline
at com.google.firebase.database.connection.PersistentConnectionImpl$2.run(PersistentConnectionImpl.java:432)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
question from:
https://stackoverflow.com/questions/65927977/android-realtime-database-throws-error-client-is-offline-but-its-not