I want to send info about user non-fatal exceptions through recordException() method, but default crashlytics implementation sends them only after app is restarted (which is quite a strange behaviour o_O)
I tried to disable automatic reports collection through setCrashlyticsCollectionEnabled(false) method and send them manually through sendUnsentReports(), but, alas, firebase continues to send them only after the app is restarted.
Has anybody solved that kind of a problem and how?
Yes, that’s expected. Logged exceptions are not sent immediately when they are recorded, otherwise there would be pull requests at random intervals which would use up a lot of bandwidth and battery.
They are batched and sent either on startup or at crash time, and when you call sendUnsentReports, all cached reports are sent at that time, but it doesn’t send anything from the current session.
Related
so I'm working with realtime database and I'm trying to make a chat app for practice.
I want to add the message to my list then let the message item inside the list upload the message to the server, I'm also showing an indicator that tells the user if the message is being uploaded, there are other approaches to apply this but I want to go with this one, anyways.
there isn't any problem when there is an internet connection. the problem is when there isn't any internet connection, the message is added to the list and the indicator appears, when the internet connection returns everything works fine still.
but if I send a message (while offline) and then leave the chat room and return to the chat room, the messages will get loaded and the indicator won't appear altho it isn't uploaded to the server (the data is cached now).
I want to find a way to tell if the data has been uploaded or not? I don't want to check the server to see if the node exists, I can't do that to every message it will cost too much, thank you.
If you enable disk persistence, Firebase keeps all of its pending writes in its disk cache. When the app restarts, it reads those pending writes and starts trying them. This is usually the right behavior for your users.
Unfortunately there is no built-in way to persist completion handlers for the Realtime Database. So upon a restart it becomes impossible for you to detect when the pending writes have been committed on the server.
So this typically means that you need to do something custom to detect the situation, and will have to determine for yourself whether the use-case is worth the effort.
If your messages are in some way ordered/timestamped (for example, if you add them by calling push()) you can keep track of what the last message is for which you received a confirmation from the server. That way you will know when the client restarts, which messages may not have been sent to the server yet.
Your onDataChange or onChildAdded will be called for those unconfirmed message straight away though when your app restarts, so you'll need an additional mechanism to detect when those unconfirmed messages are written on the server.
The best approach I know if is to write a "dummy" message when the app starts. Since the pending writes are treated as a first-in-first-out queue, your new dummy message write will be sent to the server after all the pending writes from the previous run. So when your completion handler gets called for this dummy message, you can be sure that all messages before it have also been committed (or rejected in case they violate your security rules).
Firebase cloud functions fires an onFinalize event when a file has been uploaded to the storage. So you could probably write a cloud function like this.
exports.uploadedServer = functions.storage.object().onFinalize((object) => {
const filename = object.name
//mark this filename or filekey as upload complete
return
})
You should be able to find more explanation here.
My use case: chat application. The user wants to send an image message to the other user. But the upload process takes a while to the firebase, the user may not stay in that fragment or app till the upload is complete. User may even close the app assuming his/her message will be sent.
Question: How do we guarantee the message delivery after the send button is clicked irrespective of the app is active or inactive.
You might want to take a look at the new WorkManager API. In their own words - "a library for managing deferrable (meaning it doesn't need to be done instantly) and guaranteed (guaranteed to happen eventually even if app is killed or restarted)"
You should probably still send the instant message using other means though, but the actual uploading of the image can be deferred to the WorkManager. See this video
I got an app which uses Firebase.
The Firebase's records holds a "status" field which is supposed to give information if the user is offline or online.
I initialize it like that:
fireBase = new Firebase("https://myProj.firebaseio.com/users");
child = fireBase.child(MyApp.myStringIdentifier);
child.child("status").setValue(ClientStatus.ONLINE);
child.child("status").onDisconnect().setValue(ClientStatus.OFFLINE);
The initialization works fine, and the onDisconnect() is also called after a lot of time there's no internet connection and firebase does change the status to offline as expected.
The problem is that the onDisconnect event is also called when the user swipes out the app from the recent apps list, but I want the user to remain online since I got services which are still running in the background which should handle some events even when the app is closed (They are still running, but other users get the offline status of the closing user and then the actions to that user are blocked) .
Is there a way to prevent to onDisconnect event to be called when the user swipes out the app?
The onDisconnect handlers of your Firebase Database client are called:
when the database client actively disconnects from the Firebase server
when the server detects that the database client has disappeared (by the socket connection timing out)
Note that neither of these has anything to do with your application lifecycle, which seems to be what you are interested in.
If you want to change the database when your application is destroyed, you should probably listen to application lifecycle events to detect when the application exits.
When the user of an Android devices uses the overview display to "swipe away" an app, that's a signal that they don't want to use the app any more, and they're not interested in returning to it any time soon. Android will kill the app process. Killing the app process will close the connection that it has to your Realtime Database. Closing the connection will cause onDisconnect() to execute on the server. You have no control over this process when the user makes their decision. This is by design of the Android platform, which is to allow the user to make the final decision about what can actually run on their device. As the app developer, you are not empowered to force your own decision on the matter.
If you want to send the app a message even though it's been killed by the user, you can instead use Firebase Cloud Messaging to deliver events that the user has expressed interest in.
I'm using https://github.com/google/go-gcm to send push notifications from our Go backend to Android devices. Recently, these push notifications started failing because the call to SendXmpp() was returning with the following error:
write tcp <IP>:<port>-><IP>:<port>: write: connection timed out
Restarting the Go process that called SendXmpp() makes this error go away, and push notifications start working again. But of course, restarting the Go process isn't ideal. Is there something I can do explicitly to handle this kind of error? For instance, should I close the current XmppClient and retry sending the message, so that the retry instantiates a new XmppClient and opens a new connection?
I would recommend using or implementing a (exponential) backoff. There are a number of options on GitHub here; https://github.com/search?utf8=%E2%9C%93&q=go+backoff though that's surely not a comprehensive list and it's not terribly difficult to implement.
The basic idea is you pass the function you'd like to call in to the back off function which calls it until it hits a max failures limit or it succeeds. Between each failure the amount of time waited is increased. If you're hammering a server, causing it to return errors, a method like this will typically solve your problems and make your application more reliable.
Additionally, I'd recommending looking for one that has an abort feature. This can be implemented fairly easily in Go by passing a channel into the backoff function (with the function you want to call). Then if your app needs to stop you can signal on the abort channel so that the back off isn't sitting there with like a 300 second wait.
Even if this doesn't resolve your specific problem it will generally have a positive effect on your apps reliability and 3rd party API's you interact with (don't want to DOS your partners).
I have a very common problem but wasn't able to find a proper solution/pattern to solve it. My application has two kinds of data that need to be automatically updated:
general data
user-related data
If the user is not logged in, only general data are downloaded and displayed, if the user is logged in, his/her data are handled too.
I need to periodically download these data from a Web service, starting from the boot of the device (after the action android.intent.action.BOOT_COMPLETED is triggered).
Since my app can be moved to the SD, I will also need to register for the android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE action.
Issue 1: starting from API level 11 (Honeycomb) all actions aren't sent to applications in a stopped state. I haven't quite understood this, does this mean that my app can't listen for actions if it has just been installed and never opened (so only once if we count updates out)? Or does this mean that, after every system reboot, the action will be triggered only when the application starts?
Issue 2: if the application has been moved to SD, SyncAdapters won't be able to be run, so I have to rely on the general BroadcastReceiver-Service-Alarm-PendingIntent strategy. But how can I understand if the SyncAdapter won't be started by the system? (I already handle Accounts by the AccountManager)
Do you know of any library that takes care of all of this? It seems quite strange, isn't this a common issue?
Re: issue 1, as far as I can tell, an app is not "alive" until the user explicitly runs it for the first time. It will then still be "alive" until the end of the days, unless the user explicitly stops it using the Force stop button in Android's Applications management settings. He will then have to re-run manually the app for it to be able to receive broadcasts and stuff.