I have written an android app that uses firebase anonymous authentication and writes to the firebase database from a foreground service. I am using onDisconnect().removeValue() to cleanup data created by my app when the websocket is closed. When a user is actively engaging with the app, the onDisconnect() call triggers as expected (meaning my security rules are OK). However, when the foreground service is left running for a long period of time (e.g. overnight, screen turns off, etc.), the onDisconnect() call is never triggered again. The app continues to function upon wakeup (communicating with firebase server, etc.) but when it comes time to close the app (following a period of idle time), it seems that the onDisconnect() call has been lost somehow.
I have read that anonymous authentication sessions are quietly refreshed by the firebase SDK every hour. Is it possible this is happening in the activity (and being killed by the OS, but keeping the foreground service alive), therefore causing the server to discard the callback to onDisconnect? If so, can this functionality be preserved within the foreground service?
Firebase has had a bug recently (not sure if it's been fixed), where when it reauthenticates every hour, it loses the onDisconnect() because it no longer has permission to alter that node. This then causes the duplicate.
Some possible solutions:
Attach a timestamp and check if the last timestamp is over an hour, and if it is, then delete it when adding the new one.
Remove authentication requirements for writing in the node to keep track of the disconnects (this would not be secure though, depends on your needs).
Here are some more alternatives, and a better explanation of the problem from a member of the Firebase team: here.
Android application processes can live indefinitely. When the user stops using an app, Android may continue to keep the process alive, in order to make it load faster if and when the user comes back. You can think of this is an optimization, and you should expect this to happen sometimes. You shouldn't try to control this behavior - let Android manage this for you.
Your connection to the database is not being closed because the app is still alive and holding on to its connection to the database. I suggest you track for yourself when the user stops using your app, and force a cleanup at an appropriate time after that, without assuming that Android will ever kill your app's process.
Related
I want to store user logged out time in the database(for maintaining the user analytics) when the android app forcibly closed by user. Is it possible to capture event in MainActivity?
can any one suggest the better approach to achieve this?
there is no reliable way for this event detection - this would be kind-of insecure to inform app that it's going to be killed allowing to execute some code at that moment (as in your case - database handling). user clearly wants to stop this app, when it would get a possibility to execute some code just before gets killed then it may e.g. leave some alarm for now + 10secs in AlarmManager to restart some background service. this is opposite to what user wanted
best you can do is listening when last Activity is destroyed (onDestroy call), but this may occur in multiple cases, no ony force stop app by user. use some static int and ++ when Activity is created and -- when destroyed or use Application.ActivityLifecycleCallbacks on never APIs
I've just been reading about adding a service to my application, and since 7/8 there are now service restrictions to improve phone performance.
I've seen that the recommended approach is to use a job scheduler, but will that not just periodically start a new listener if I did that?
Basically I update my database, and using a snapshot listener I want to update my user in real time. When the app is closed, I'd like to send a notification.
My issues (if I'm correct) are that constantly making a new Firestore request will eat through my request allowance.
Also, if its a job scheduler it won't quite be real time?
I've read that you can use a foreground service, but this doesn't really seem like that task that needs a permanent notification and would annoy the user.
Anyone got any tips on how I'd implement this?
Thanks
Using a listener after an android application is closed
You can use a listener after an android application is closed, by not removing it. Once you are using a listener, you also need to remove it according to the life-cycle of your activity. But this will work only for a shot period of time because Android will stop your service if the app is not in the foreground. It does this to save resources when the app isn't being used. It also might stop your app from doing any networking, or even kill the app process completely. There's nothing you can do to prevent this, other than making it a foreground service, as you already mentioned.
A foreground service is probably not the best thing to do for your case, nor is it the best thing for your users. Read more about limitations on background services.
My recommendation is to use Firebase Cloud Messaging to notify your app when something has changed that it might be interested in. So your users will recieve notification even if they will keep their app closed.
I'm new to firebase realtime database, and have a basic question I cannot seem to find the answer to.
I need my Android app to keep track of changes in the database, so I understand I need to use addValueEventListener, with the onDataChange method. However will the method onDataChange, be called even if the app is destroyed? I need to be able to access the changes of the information in the database even if the app isn't running in the background, (for example the user force quits the app). This is because when the values reach a certain point, I want to show a pop up notification, so I need to able to read the values even when the app isn't running.
If the onDataChange is called even when the app is in the background, will this drain battery use since the phone is always listening for changes.
Sorry for the basic question, but I couldn't find the info.
Thanks!
...when the app is dead, is the EventListener still listeneing, and will onDataChange be called?
Event listeners are only active while the context they run in is active. For listeners you attach in an activity, that means they're active while the app is running. Even then Android might kill the listeners (or more accurately: the socket they use for communicating with the server) if the user isn't actively using the app.
If you want the listener to stay active longer, you can indeed consider managing the listeners in a background service. But even there, Android might close the listener to preserve battery life. That is the one thing to always keep in mind: if your use-case interferes with the user's preference (and most users are likely strongly prefer longer battery life over any specific app feature), it's unlikely to continue working in the long run.
A better approach is to combine listeners with Firebase Cloud Messaging for sending messages. FCM messages are more likely (though still not guaranteed) to be delivered when the user is not actively using the app, and you can use them to run some code of your app when they arrive. You'll want to use FCM's data messages for this, which is how most app deliver background updates.
You can also use an FCM data message to just wake up your own code, then have that code attach a listener, and get its updates. This type of behavior is known as sending a tickle, since all the data message does is waking the application code up.
I have android application with several services.
This application should send reports to remote server when this application has been started and when has been stopped.
But I don't know how to determine that application was stopped, because application may be stopped (crushed for example), but services still running.
I think that the algorithm should be like this:
Check the mark with last date from storage (and if this mark exists - send "stop" time to the server)
Send "start" message to the server, when application was started
Every 10 minutes application should writes current date and time mark on disk
If I will create service with this check - android can kill this single service when there is low memory, but application can be running. If I will create ScheduledExecutorService in Application class - application can stop, but services can be still running.
Can you help me with solution?
There's really not a single answer to this question. It has been asked many, many times here at SO, but all we can say is it really depends on our app's behavior.
You want to put some Log messages in onPause(), onStop(), onDestroy() in your Activity, and onDestroy() in your Service. Watch the the flow of the app carefully by looking at the Log printed out in the Logcat.
Lots of people try to rely on onDestroy() method because it looks like it is called when the app is completely terminated, but that's not always the case. Sometimes app crashes (force closes) or some people just manually force close it in the app information in settings. In that case, app does not follow the lifecycle of the activities.
One of the suggestions would be creating a thread that runs in background and send a UDP packet to a server saying that the app is alive in every few seconds.
PRO: You don't need to make a handshake with the server so it saves time/resources getting response back from the server.
CON: Thread running background does use battery. UDP can be only used in WiFi environment for recent Android OS.
Hope you find a good way. You may want to comment to your post when you found a good solution, because people would like to know how to solve it, too.
Why not try to trust standard methods Activity?
You should approach onDestroy and / or onPause. It depends on your logic.
In addition, you can try to override Application.onTerminate(). You can read about it (Application) lifecycle here.
I would like to notify my users of new content available in the latest version of my android game without using an external service like Push Notifications.
What I would like to do as a first step to achieve this is to just create a standard notification on application update.
This brings me to my question: is it possible to start a service the first time a user launches the game and then just keep it running indefinitely? I want to even keep it running after an update completes. Since it is possible that the code for the service may have changed between versions, would I need to stop the old version of the service manually and start the new version? Is it possible to even do something like this where the event that drives initiation of the service is the completion of an app upate?
My plan is to have this service check some persisted data about the last time the user was notified about new content and based on this I will be able to determine if a notification should be created for them after they update.
It's important that they are not required to go back into the game after update in order for the notification to be created. This is the problem that I am having now. Auto-updates occur and they don't know and hence also don't know that there are new stages, etc, available so they never go back into the game if they were already done with the previously available content.
It seems that games like Family Guy have got this approach working, but I am not sure if they implemented it in this way. Even after I update it, I will still get notifications even if I have not actually executed the app since update.
Services are mostly killed when other process needs the resources. Therefore use
startForground(...)
for running Services indefintly on background.
See here: http://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification)
What you can do is use the AlarmManager in your service that notifies you at certain time. Start the service, do the task and set again an alarm to notify you. In this way, you'll be able to run your service infinitely at periodic time.
I started redacting this answer on GameDev Stack Exchange before you
deleted the question. Unlike the guy who told you to delete, i thought it was an interesting question even for game dev stack exchange.
What you describe is a bad practice on android. I don't believe any game do that. What's more, android require "service" app to run as ForegroundService (This force you to display you app icon in the notification bar, so that users are always aware of running services) It can also be randomly be killed when the system lacks memory. However it can be implemented nicely using Alarms and AlarmManager.
Services and Notifications :
You can however schedule intents when the app is running, with AlarmManager, this is the good practice. Let's take a simple exemple : Candy Crush.
In Candy Crush, when you lose your last life, every 30 minutes you regain one, and have a limit of 5 lives. You want to notify the user when all his lives are back. How to do that ?
Exemple 1 :
When the user lose his last life or quit the game, schedule an intent with AlarmManager in (5-number_of_life)*30 minutes that will fire a local notification.
Exemple 2 :
Schedule an intent with AlarmManager every 30 minutes to check the number of lives, and fire a notification when the user have 5 lives again.
Using a Boot receiver may also allow you to schedule things as soon as the device boot.
However, users expects to be able to disable this kind of features.
Updates :
If you want your app to notify users when an update is available, you'll need to somehow check on the internet with a request on your server. You may schedule an intent again with alarm manager to check regularly if the update is available. If the user is ingame, you can also check it more regularly.
A lot of "online" games do that, and simply force the user to download the new update from the Play Store, before they can play again.