In my Android application, I want to display a notification only when the user is not moving or only slowly moving. For example, when a user is driving, I don't want to display notifications. To accomplish this, I've looked into the Activity Recognition API and implemented a basic component -- and it basically works alright.
During some first test, I've noticed that occasionally see some strange output when I simply check for the activity with the highest confidence, e.g., getting a IN_VEHICLE while walking. Since this is based on statistics and what not, I'm not surprised of that. I, therefore, use simple sliding window over the last N activity types. Only when all values in the window are the same, I assume the respective activity.
Now I have 3 configuration parameters:
TIME_BETWEEN_REQUESTS (in milliseconds) as the minimum time between the request for the current activity value as part of the Activity Recognition API. The lower to value the more up-to-date but the higher the battery drain. For testing, I currently set it only to 5000 (=5sec)
MIN_CONFIDENCE (0..100) minimum confidence referring DetectedActivity.getConfidence(). Only if the confidence is larger than this threshold, I consider that the API is confident enough about the detected activity. On the Web, I see most commonly a MIN_CONFIDENCE >= 75
WINDOW_SIZE (>= 1) as the minimum number of the same activity types before I'm sure about the detected activity. Currently, I use WINDOW_SIZE = 3. So if a user is walking and the phone detects an occasional IN_VEHICLE I don't immediately assume that the users are driving. Only if the next two values are also IN_VEHICLE, I change the user's activity state.
Does this make sense? I'm a bit worried if I increase TIME_BETWEEN_REQUESTS -- What is a practical value anyway -- because it takes at least WINDOW_SIZE * TIME_BETWEEN_REQUEST before the activity state of a user will change. Right now it's 15sec, but if I would set TIME_BETWEEN_REQUESTS to 30sec and keep WINDOW_SIZE 3, it would require at least 90sec for a change to occur.
What are good/best practices here? Is the window even necessary or do larger values for TIME_BETWEEN_REQUESTS already do some kind of smoothing?
Related
I'm currently developing an app that uses the activity recogition api.
I have a main activity and an intent service which is called using requestActivityUpdates() and returns data for the activity using the broadcast api.
According to the documentation, requestActivityUpdates' first parameter, detectionIntervalMillis, stands for "the desired time between activity detections. Larger values will result in fewer activity detections while improving battery life. A value of 0 will result in activity detections at the fastest possible rate.".
I'm using a values as low as 100ms and still I get updates once every 3 minutes on average. What could be the problem here? I tested on 2 different fully charged devices already, so I believe this has nothing to do with power saving configurations.
edit: took the devices for a walk and it seems that the rate of updates go up to ~8s. Still way more than expected. :/
I'm developing a set of complications that I would like have regardless of the other installed apps and watch faces. Yes, at some point I am reinventing the wheel, but at the same time I am using this as a learning project. This will also ensure that I always have all the complications I use, available and that they all have the same format and style, instead of relying on 3rd party apps to provide them separately.
The set will have complications for Heart rate, gps coordinates, hours, minutes, seconds, dd/MM date, dd/MM/yy date, battery, etc.
When I started programing all this I found several problematic pieces (most likely because this is the first time I develop complications, or an app for android wear for that matter) and hence this question.
Note that some of this behavior might be specific to the Huawei Watch 2 LTE.
1) Upgrade interval push / pull.
I understand complications as data providers, whose only responsibility is to provide the data to whatever watch face is calling them. This means that we are not certain (and we rely on the watch face developer) to know about the complication and request updates accordingly. This turns some complications completely useless if not updated in time (for example display the Seconds). Could also leave to complications displaying old data (for example old GPS coordinates, old heart rate bpm).
So ok, I decided to implement ProviderUpdateRequester with the AlarmManager to push data to the watch face. The problem again, is with complications that should happen faster, like seconds, as Android will block pending intents if they are schedule too often. So in order to get around that, I decided to use Android handlers within the same service instance, which turn out to be not a good idea because of the next topic.
2) Complication lifecycle
By debugging, I found out that the instance of the ComplicationProviderService object that is executing onComplicationActivated, onComplicationUpdate, onComplicationDeactivated can be different. This means that this is not a sticky service (single instance) that will be always running, but every update creates a new instance of the service. This is problematic because of heavy initialization complications: for example GPS, or Heart Rate monitor that need to listen for new values and it might take a while to retrieve the first value. And also, for those complications that can't rely on AlarmManager, and/or need to keep some sort of state between updates executions.
3) Display aware service
To get around the previous point , let's say you have static variables on your complication service , which are initialized onComplicationActivated and disabled at onComplicationDeactivated. For example, this could be getting a reference for the LocationProvider and starting listening for location updates. This will ensure that each invocation to onComplicationUpdate will not have to perform the heavy/cold initialization and will have access to the most up-to-date data.
However, this also means that your logic will executed regardless if onComplicationUpdate is called or not.
When in ambient mode (or screen off) the watch face can decide not to update the complication by not calling onComplicationUpdate, but it's not aware of our static logic, nor the ComplicationProviderService has a callback invocation for when the screen goes into ambient mode or turns on/off. This is a problem, because in our example, if the screen is off, we are still going to be listening for GPS coordinates, and most likely draining the battery.
Sure, we can deal with this by using a combination of BroadcastReceiver (Intent.ACTION_SCREEN_ON/OFF) and DisplayManager.DisplayListener, but then again, not sure if i'm taking the correct path here, because this will mean that we are now creating services that need to be statically aware of the state of the display.
4) Detect screen on/off
The BroadcastReceiver for Intent.ACTION_SCREEN_ON/OFF works as expected when ambient mode is disabled, but it doesn't it's enabled. When ambient mode is enabled, Intent.ACTION_SCREEN_OFF is dispatched when going into ambient mode, but Intent.ACTION_SCREEN_ON is not dispatched when coming out of ambient mode. While a bit more complex, this can be accomplished by using DisplayManager.DisplayListener to get updates on the onDisplayChanged callback.
TL;RD
1) How do you ensure watch faces display your complications in a timely manner to always have correct and most up-to-date information?
2) How do you deal heavy/cold initialization of a ComplicationProviderService if everytime onComplicationUpdate is called the service instance is different?
3) Is making a long running service display-aware something crazy to do?
4) Technically the screen is still on when in ambient mode, so why is Intent.ACTION_SCREEN_OFF being broadcasted? Why isn't Intent.ACTION_SCREEN_ON/OFF symetrical when ambient mode is enabled?
5) Maybe complications shouldn't be use for exposing realtime information?
Thanks a lot
A couple of things to unpack:
Complications are not meant to be updated frequently (think minutes, not seconds) - this is to preserve battery.
ProviderUpdateRequester is designed more for (on average infrequent) irregular updates like messages coming through a chat app.
Time dependent complications - there are not an "update" as such but Wear provide ways for developers to count up / down from certain time and for displaying date related field (world clock, day of the month) without the provider sending the system updates all the time. For this last one, please refer to docs for ComplicationText.TimeDifferenceBuilder
and ComplicationText.TimeFormatBuilder.
For your use case, a more appropriate thing maybe to consider an always-on app. User uses it for a certain time period for a specific purpose so they explicitly agree to use to use more battery to track things like GPS or heart rate. For example, a lot of running apps on Wear do this.
I hope this helps.
I am studying the Cordova geolocation plugin for Ionic 2 and want to send the device location to my server when the app is opened.
To keep track of the route of the device I want to send the position all the time to the server. I was wondering how often I should do this. Every time the location changes seems a little too often!?
How do other tracking apps do this?
Granularity of position updates are inversely proportional to the battery power consumed and the network bandwidth used for transmitting the positional information.
I use the following guidelines:
Transmit position whenever the position has exceeded a defined distance 'D'
Transmit position whenever a defined period of time 'T' has elapsed since the last successful transmission
Transmit position when the app starts
Disable transmission when the activity is paused and enable it when the activity is resumed
Always save the last successful transmission (position and time stamp) for future reference
I typically store the defined parameters 'D' and 'T' in a configuration file, making it handy to test how the application performs for different values.
Using coarse GPS for reference, position accuracy is rarely better than 15 meters (without applying GPS corrections). With that in mind, you can set your 'D' value to something between 15-30 meters. If you are tracking vehicles, that distance can be exceeded pretty quickly, in which case a larger value may be preferable to avoid sending too much data.
You can also increase 'D' as a function of your positional velocity (speed). this would increase 'D' the faster the vehicle is moving, thus maintaining a consistent bandwidth usage.
The value of 'T' really depends on your application needs. If a vehicle is sitting idle, then I typically transmit updates once every 5 minutes.
I have used distances ('D') between 30-100 meters. If you are monitoring vehicle positions in an urban environment, you need to be able to pin point where that vehicle is within a crowded street plan. This becomes quite clear if you've ever used a GPS device to navigate in an older city, where the device often gets confused between streets that are in close proximity (i.e., New York, Boston, Montreal, etc.) In this case, a smaller value (> 15m) is preferable.
For added robustness, you might want to add some heuristics into your application. For example, popular after-market GPS devices for automobiles have to implement more intelligence into their applications, in order to snap the vehicle position to a location on a street or road. Otherwise, the vehicle would never show up on the street itself, but rather somewhere in the ditch, or right in the middle of a building on the map.
One example of such heuristics would be to assume that unless the vehicle has reached an intersection, it is still on the same street that was reported previously.
Ultimately, you need to try out different configurations in order to find what best suits your needs.
I want to know if the user is away for some amount of time. (and then do something according to it.) I cannot depent on screen sleep because user may have disabled it or its value may be greater than timeout of my application.
is there any information like (last user response time ) in android operation system ? and how can i get it?
last user response time = the last interraction time between the user and the phone.
p.s.:i am targetting android 1.6
No, there is no way to tell when was the last time the user interacted with your application in the SDK. You'll have to do something by yourself.
High level explanation of a simple solution:
Assuming you use some base activity inherited by all activities, you can log the current time in your BaseActivity.onPause method. Save it in the app preferences or in a database. When your initial activity starts (onResume) read the same value and compare it the current time.
You can also use Activity.onUserInteraction but saving to preferences/database everytime this is called will considerably slow down your app / feel less responsive!
Hello
In my android application i would like to get Time since when the app is opened.
Initially what i tried was getting the time when the app is loaded from the server and then taking the difference with the current time from the device.But by doing that if the user changes the time then i willnot be getting the actual time.
Its not posiible to hit the server again for the same.
Is there any way to achieve this in android?
Please share your valuable suggestions.
Thanks in advance:)
Try the "SystemClock" class, "uptimeMillis()" method.
Store the result in a variable when the app starts.
Echoing what I said for your other question, you first need to become familiar with the activity lifecycle and understand the novel meanings (almost meaninglessness) of common words like "open" and "start" in the life of an android app.
There isn't any way you can prevent the user from changing the system time - you just don't have the right to do that to users. Normally this should be a rare event, unless you do something that makes them want to, such as lock them out of a free version of your app after so many minutes. (However if the phone is on a mobile network, presumably the mobile network occasionally adjusts its time to correct for errors in the device's oscillator, or administrative time changes)
What you can do is check the system time on every entry point to your application. If it ever goes backwards, well... something is going on. If the clock has been set back, you could assume no time between the calls with the negative time difference and resume your time meter from there, at least keeping all the previous used time in your record.
It may be that there are cpu cycle counters which you could query and correlate to system time, but this may be highly device specific and may in fact be resettable. And it may get weird if the cpu frequency is demand throttled.
You might be able to set a countdown timer as a bound on the maximum possible time between entry points at which you could meter. I don't know if these work reliably across system time changes or not - ideally they would. Testing or reading the source will reveal.
Use elapsedRealtime in your onCreate() store it. More reliable.