Android Activity Recognition updates are not regular - android

Related to this question.
I am experiencing that Activity Recognition updates are not delivered on a regular basis. The power saving mode on my phone is disabled and I set the fastest possible detection interval (0), yet sometimes intents are not delivered for more than 10-20 seconds. It seems the delays mostly happen during an activity transition (e.g., still -> in vehicle), but this is just a hypothesis.
In my application I need be able to set a strict upper bound for the interval between intents, has anyone achieved something like that?

This may come a little late. However yes this is normal. I have noticed that there is a delay during a transition from activity A to activity B (e.g. from still to walking) while there is generally no delay when the activity is constant. I guess this is because the sensor tries to collect as much evidence as possible in case of activity change (e.g. to avoid returning false positives). I doubt there is any way to change that.

Related

Scheduling Repeating Events -- Handler.PostDelayed and Doze

Context
I'm working on a screen filter app (like f.lux) for Android. I'm currently working the feature to gradually fade in the filter as the sun sets. The state does not matter when the screen is off, but when the screen is on, it's important that the fade progress be correct (or immediately updated).
Technical requirements
I want to fire a series of intents at semi-regular intervals.
When the screen is off, they can be ignored / discarded, except:
when the screen turns on, the most recent intent must be fired immediately.
I do not want to drain the battery unnecessarily.
Obvious solutions and why they don't work
I could use AlarmManager.setInexactRepeating, which is supposedly the most energy-efficient of the alarms, except:
Your alarm's first trigger will not be before the requested time, but it might not occur for almost a full interval after that time.
I think this implies that the first trigger will necessarily happen within the first interval, meaning the device will be woken, causing unnecessary battery drain.
I could use AlarmManager.set to schedule the first alarm. When it goes off, I could update the screen, then schedule the next alarm. This would work, but would wake up older devices (without Doze) on each alarm, instead of waiting until the screen turns on. It's also using AlarmManger as a timer, which the documentation explicitly recommends against:
For timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
Okay, so,
I could set a single alarm to starts up a Handler, which would update the UI periodically. But wait: this relies on postDelayed, which says (emphasis mine):
Time spent in deep sleep will add an additional delay to execution.
I think that means, when the device wakes up from sleep, the next update might not happens for a whole interval. Am I reading this right? Forcing the user to wait a minute or two before the next update is a deal-breaker.
CountDownTimer and ValueAnimator both use this method in their implementations, so if my interpretation of Handler is right, they're both out.
I could use a handler-based method and also receive events when the screen is turned off, at which point I'd cancel the existing animation, then start a new one. This looks to be the best solution, but it seems like there should be a simpler way to do it.
Conclusion
There are a ton of other SO questions on this topic. Everyone and their mother recommends using a Handler, but there's absolutely no information about how it behaves when the device goes to sleep, aside from the quote above. It's really weird that (apparently) nobody else has run into this issue -- am I doing something really unusual, or missing something basic?
Can anybody provide insight about how Handler.postDelayed really behaves when the device goes to sleep, and recommend what I should do in this particular instance?

Activity Recognition PendingIntent stop been called in the middle of the night

my application collects periodically Activity Recognition's Detected activity data.
I implemented it exactly as described in the documentation , but with one minute interval.
as long as the user is logged in - the application registered with a PendingIntent to receive updates from google play process..
please not lecture me about battery usage, network, and performance problem derived from request updates each minute, unless it have something to do with my problem:
the problem: in some devices (in Nexus 5 it happens the most), for a 5-6 hours in the middle of the night - the IntentService stopped been called.
I'm not sure, but suspects it have something to do with Google optimizations and the significant motion sensor not detecting any motion entering the activity recognition mechanism to be in sort of idle mode, as described in the documentation that can happened.
it's important to my app to know what is the current activity each minute approximately even if it stay the same, or idle for a long time..
my question:
how can I know if the periodically activity recognition stopped been called because of the significant motion sensor or from any other reason?
it there a way to force somehow the Google play process to perform activity updates without stop it for a time it assumes not needed?
Per ActivityRecognitionClient.requestActivityUpdates:
To conserve battery, activity reporting may stop when the device is 'STILL' for an extended period of time. It will resume once the device moves again. This only happens on devices that support the Sensor.TYPE_SIGNIFICANT_MOTION hardware.
As you suspected. There's no reason you cannot save the last value using the many data storage techniques - a simple SharedPreference might be enough for your case.
If you are directly triggering actions based on the IntentService being called (a bad idea since other apps may cause it to trigger extremely quickly) rather than only on changes in activity, then you should decouple those actions and instead set an alarm or trigger a periodic sync adapter for whatever specific time interval you need, reading the current value from the last activity you received.

How do i shut down everything in any case of my app being closed?

please hold back on the downvotes for a second and read.
After my question
Is there a way to create a controlling instance that controls several activities of my app?
and after reading detect when application is closed
i am wondering... i have lots of activities in my app, and several services, i access about all the hardware that the device has. Access to those things makes sense for as long as the app is running. Activities can change but the need for access to those things is there in every single one of them (slight exaggeration).
I know of two ways that seem suitable for my needs.
1) i extend Application and instantiate some objects there that access or calculate stuff that is needed everywhere
2) i do the same in a subclass of Activity
In both cases i would like to unregister broadcastreceivers and stop services. Services are not bound (for a reason). So whats the proper way to close and unregister things in all those cases that can happen ?
its possible that onDestroy is not called
i am not notified of my process being closed/killed by the system
So how do i create something that is always there for all my activities but stops and cleans up whenever my app is being closed ?!
You can't, never ever never create something that is 'always there' in Android, it is simply not part of the architecture. Even with a startforeground service if the device is low on memory or asleep your services can still be destroyed (and calling ondestroy is not guaranteed as you point out).
The most reliable way I've found to keep something 'alive forever' in a quasi-sense is to set a repeating alarm schedule with RTC_WAKEUP and use a WAKE LOCK.
The problem with those things however is that they will eat through battery like no tomorrow! If you are just concerned about all that stuff while the screen is on, an inexact repeating RTC alarm w/o wake lock seems to work well for most scenarios.
Edit: I sorta answered your question indirectly, but in addition to the above, when you are done with a resource declare it null or unregister it. If you have long living services with stuff registered and Android decides to kill your service and not call onDestroy, well there is not much you can do about that, just move on (and be sure you are save your states in persistent storage so you can retreive them at next init at the state they were last left off at.)

Is it possible to hold multiple Wake Locks?

I'm developing a small utility app that scans 2D barcodes, and then submits each barcode to an IntentService where a longer task is performed.
When the activity is shown, it should prevent the device from sleeping, until the barcode is processed in the service. If the service finishes the processing, it stops itself, but the activity should still be visible.
I'd like to hold a SCREEN_DIM_WAKE_LOCK WakeLock during the activity lifecycle, but as this type doesn't prevent the CPU from sleeping, I'd also need to acquire a PARTIAL_WAKE_LOCK in the activity when a new 2D code is scanned, and release it in the intent service after it has been processed.
The SCREEN_DIM_WAKE_LOCK purpose is to avoid the user the inconvenience of pushing the power button each few seconds to wake up the device and be able to read a new barcode. The user will have to read a great number of codes one after another and the activity should be around even for the short intervals where there's no user interaction.
I know in Android there's no 100% guarantee of the app being on top, not closed, or foregrounded due to several conditions my app can't control, but I'd like to go as far as I can.
So it is possible to hold multiple WakeLocks? Where could they be declared to be accesed both by the activity and the service? (Singleton, extending Application?)
It is possible to hold multiple WakeLocks. In fact it's done all the time when multiple applications sync at the same time when the screen is off. (Imagine your GMail and Facebook apps sync at the same time when the screen is locked. They don't know about each other will have different WakeLocks. May or may not be different types of WakeLocks)
Android will make sure everyone's expectations are met (maximum battery drain in other words.)
In my opinion, I think you're over-thinking the fact that you need a SCREEN_DIM_WAKE_LOCK as this can accidentally drain a LOT of battery, but I may be wrong depending on your use case.
So the short answer is YES. You can hold multiple WakeLocks and Android will (should) act as expected. Only thing to keep in mind is that you release both Wakelocks properly.
In the issue of getting on top of the screen, I think you should release the WakeLock of your activity when it goes to Paused state (when somehow another activity is on top, or use intentionally press the power button). Because at this point, user is interacting with another app, and you should respect it and let it control its own behaviour. You don't have to give up the partial wake lock from your service until you're done.
Hope This Helps.

How Can an Android Application Detect Whether Any of its Activities are Active?

We have an Android app that periodically polls for data and updates the display. The polling is performed by a background thread. Unfortunately, this background thread constantly runs, even when our app is offscreen or when the device is locked, which leads to unnecessary network activity and CPU/battery usage.
So, I would like to change the app such that it will suspend its polling activities in these cases:
When none of the application's activities are in the foreground.
When the device is locked.
What is the easiest way to detect whether the app is in either of these states?
Note: The app has several activities, so I don't think it is as simple as just keeping track of the activity lifecycle events. I would have to add code to each activity to keep track of whether any of my activities are in the foreground. If that's what I need to do, I'll do it, but I'm hoping there is a simpler way.
These are some questions which are related, but which don't seem to provide a good answer:
Android: How to detect if current stack of activities (task) moves to background?
How to be notified about entering suspend mode?
Simple check for Android application backgrounding
What is the easiest way to detect whether the app is in either of these states?
For the are-we-in-the-foreground issue, increment a reference count in a static data member in onStart() of each activity, and decrement it in onStop(). If onStop() sees 0, stop the polling. If onStart() sees that you're not polling, start polling.
For the is-the-screen-locked issue, don't worry about it. The device will fall asleep once the screen times out and your polling thread will not be running. Besides, I think your activity will be stopped in this case anyway.
BTW, this is one case where onStop() is the right answer, not onPause(), so the lifecycle handoff between your activities is handled properly.
If that's what I need to do, I'll do it, but I'm hoping there is a simpler way.
That's as simple as it gets.
My intuition says that says that you're thinking about this wrong. You're right to think that you need to curtail your polling when not necessary, but how about just not polling at all? You could use a push paradigm instead (see long polling or Android Cloud To Device Messaging). If your doing this polling to keep resources in sync, you might also want to checkout the android SyncAdapter.

Categories

Resources