Android: what is the best way to send presence? - android

I want to send that the user is currently using the app to my server in regular interval.
User is active,
When he is on any activity of my app and the user should see it in screen.
User is Inactive,
If the user is not in any of my app's activity
If the user has minimized the app
If the user is in my app's activity only, but screen is locked
For this, I have implemented Android's ActivityLifecycleCallbacks and trying to send user is active in onActivityResumed() and inactive in onActivityPaused()
It works as expected, but there are many activities in my app, so transition between Activities also send this presence status, which is very bad for end user.
How can I control this ? How can I send only at regular intervals instead of flooding the presence ?
Generally what is the best way to do something at regular intervals in Android ? which means, the task should be done only on particular intervals even it has called any number of times.
UPDATE
How it works now and how do I need:
Making quick transitions from Launcher -> ActivityA -> ActivityB -> ActivityC
Current Behaviour:
A's onResume() triggers userActive()
A's onPause() triggers userInactive()
B's onResume() triggers userActive()
B's onPause() triggers userInactive()
C's onResume() triggers userActive()
Required Behaviour:
Since the user is actively in app after all these transitions happen, it should send userActive() only once. It can either send at first transition, (Launcher to ActivityA) or at last transition(ActivityB => ActivityC).
In simple words, the userActive() should not called if it is called within last X seconds.

Implement your LifecycleCallback as a singleton or let your Application class implement it. Let it have a counting variable.
public void onActivityResumed(){
if(activeCount == 0){
// an Activity is active ... do something
}
++activeCount;
}
public void onActivityPaused(){
--activeCount;
if(activeCount == 0){
// all Activities paused
}
}
You may want to synchronize your counting variable or use an atomic integer.
To send info on a regular interval, just let a background service check the value of activeCount periodically.

As per Android's documentation, the best way would be to implement dedicated background service which would be establishing connections on a periodic basis and send all new events in one pack.
Most of similar services are designed the same way. Backgound Service has this nice feature that it's one of the first to be killed when system is running out of memory, thus your other activities will remain intact and be running smoothly. Once resources are available again, you could configure it to pick up from where it left and send the report to your servers.
My personal rule of a thumb: if something is not directly related to handling user controls, make it as a service
--- Edit 1:
Android Documentation

Related

Android capture event when app is closing forcibly

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

Do i get a Android Broadcast or Event when the app comes back to focus

I want to be notified when my Android App comes back to focus or is started. The tricky part is, i don't care for the events which appear when switching Activities within the App. The Events i am interested in are:
App is started
App is reactivated on any Activity (brought back to front by the user)
I tried handling it with the onStart() and onResume() Methods, but they fire every time a Activity is loaded and call onStop even when they just switch Activities within the app
I checked the lifecycle (http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle) but even the onDestroy() is called when solely switching Activities within the App.
How can i determine if my App is reactivated or just switching Activities?
you have to override Application class for **App is started** this will call once every time when app is open.
Two possible solutions come to mind, neither of them is very clean.
1) Use a timer
Every time in your onPause() method, you schedule a timer that sets a flag after 1 Second (or something longer, depends on your exact use-case). In each onResume() you check if the flag has been set, e.g. your App has been inactive for longer than the timer interval. If the flag is set you know the user did something else between the onPause() and onResume()
2) Set a flag manually
Every time you trigger a switch between Activities in your App, you set a flag somewhere in your application. In your onResume() method, you check if the flag is set, e.g. the switch was triggered by your App. If it is not set, the user comes from outside of your App.
Both methods, however, can't discriminate any further between possible use-cases. All these cases will look the same to you:
the user presses the home button and resumes the app at any given time later
the user turns the screen off, and back on again
the user gets a phone call and then immediatly returns to your app
This might lead to undesired behaviour of your App. I don't know what exactly you want to use this mechanism for, but you have to think very hard about all the possible cases, and if you want them to trigger your behaviour, or not.

Main activity removed from stack - set uset state as offline

When the main activity is loaded I can set the logged user's state as online by updating a remote database row. If the user exits the app I must set the user state as offline.
If the app is exited using back button I have the onDestroy() method and in there I can set the user state as offline, but if I exit using Home button and I kill the app from settings onDistroy() isn't called.
Is there a way to know when the main activity is no longer on stack, so I can update the user's state?
onStop will be triggered when user clicks on back or home button. So handle your events in onStop.
public void onStop () {
//do your stuff here
super.onStop()
}
EDIT:
Also try
#Override
protected void onPause()
super.onPause();
}
Also you could have it check if the app is finishing with
if (this.isFinishing()){
//Insert your finishing code here
}
The home button doesn't call onDestroy as the activity is still on the Activity stack where as with the back button it is generally removed. When the ActivityManager decides to remove the activity from the stack, usually after a period of inactivity or when resources are required, onDestory will be called at which point your field will be reset.
I am not able to say definitively because I don't know all the information but it would seem that removing the users logged in state when you press home (in onStart as suggested by coder_For_Life22) might be bad, as if you returned to the activity the user would have to log in again, perhaps unnecessarily and the client side session management will become even more complex.
Your method of session management seems fairly questionable anyway unless you have some sort of server side session management where, for example if there was inactivity on the session the database field would be reset.
UPDATE
The only way I can think it might be possible is using the ActivityManager.getRunningTasks() or ActivityManager.getRunningAppProcesses() and checking if your app is among them. If you kill your app like you are suggesting then your app will not be among them and thus you know. It seems like a hugely complex solution if at all possible as you would need a separate background service running (which you could call getSystemService(ACTIVITY_SERVICE) on to get the ActivityManager) just so after you kill your app you still have something running which can check for this and perform the appropriate actions.
Killing your app this way neglects the activity life cycle and thus there isn't a hook in your activity where you can perform shut down calls.
It seems much more sensible to check for inactivity on the server side and reset the field this way, people don't often kill their apps like this and when they do they aren't likely to quickly hand the phone to someone else who would be able to access the information maliciously.
If the data requires such security then you should rethink your security model.

How do I test for activity inactivity time

I'm wondering what is the highest level I can go in-order to know when the user interacts with my application
preface: I'd like to logout of my application after X seconds of user inactivity.
so what I did is create a service with a timer, and a toggle function which resets the timer to X time.
after X time has passed, an intent is raised, and a broadcast receiver catches that intent and preforms the logout (closing the open logged in activities as well...)
as for the actual question, I need to call the "Timer Toggle" function each time the user interacts with the application.
where is the highest place in the android app that I can know when the user interacts with the phone
The only thing I found is to implement onClick and onKeyPress for each activity, is there another better way? maybe in the Application class?
I don't think there's any other way aside from sending events from the Activity itself.
You could look at overriding Activity.onUserInteraction().
But is it likely that the user will be in a single Activity of your application for "X seconds" without ever switching screens, or letting the device go into sleep?
I imagine it would be sufficient to update the timer/flag in onCreate, onPause and onResume. Plus maybe some commonly-called functions within the Activity.

Android : how to know when an app enters or the "background" mode?

I am trying to achieve the following with Android :
when the app is in background, a thread polls a server every now and then to retrieve data and notifies the user if new data is available. I am using a Service for that, fine.
when the app is in "active" use, i.e. one of its activities is visible, the polling should stop as it might interfere with other user actions.
I don't understand how to detect the transition between the "active" or "background" use of the app. The onResume() activity methods does not seem to help, as an activity can be hidden or visible during "active" use anyway. My understanding is that the app itself doesn't make the difference between the 2 states.
Can it be related when the HOME button is pressed ? Is there another way to do the distinction ?
I am thinking of an equivalent of iPhone's app delegate method applicationDidEnterBackground. Is it the right way to think with Android ? Or shall I use another approach ?
Thank you.
I'm going to reference the Activity Lifecycle. In between onResume and onPause your Activity is 'active', i.e., it's on the screen and the user can interact with it. If your activity's onPause method is called then you should assume that it is no longer 'active' and the user cannot interact with it anymore until onResume is called again. If you wish to track this in your service you're going to have to do this manually.
This is probably most easily achieved by calling a method in your service in Activity#onResume that increments a counter or sets a flag and in onPause reverting that change. If you have multiple activities then you're most likely going to need a counter, probably an AtomicInteger, and use it to determine when you should resume your polling.
I would probably wait for a small bit of time when the counter reaches 0, recheck it, and if it is still 0 resume polling. This would account for the gap between one activity's onPause and another's onResume.

Categories

Resources