I'm making an app that tracks user activity in the background using ActivityRecognition API, and if the user remains in the same place for specified period of time(e.g. 1 hour), then system pushes notification telling user to take a walk. I have implemented activity recognition, but only for the cases when the app is opened. Obviously, the Google API Client needs to keep connected in order to send activity updates. My questions is - for activity tracking in background, what would be a better solution:
1) To implement AlarmManager in the main activity (or separate activity) that once in 30 seconds wakes the activity, connects Google API Client to Play Services, then sends PendingIntent to IntentService for activity analysis
2) Create a separate Service (not IntentService) to continuously run on background (separate thread), that will keep API Client connected, and send activity updates to IntentService. Hence, the system would have 2 services: 1) Service to keep API client connected to Play Services and send regular activity updates to IntentService for analysis; 2) IntentService for receiving activity updates form Service, and analyse the data.
3) Some other solution (offered by you guys)
Comments: My tutor suggested me to use AlarmManager, but you usually use it for things like network updates, hence the interval is generally more than 10 minutes whereas I need 30 sec - 1 min. So I am hesitant to use it.
I also have seen many similar questions on here before, but I haven't found any clear answer.
Actually, a connected GoogleApiClient is only required for requesting and removing activity updates - you do not need a connected GoogleApiClient to receive activity updates.
The requestActivityUpdates() documentation actually specifically mentions working in the background:
A common use case is that an application wants to monitor activities in the background and perform an action when a specific activity is detected. To do this without needing a service that is always on in the background consuming resources, detected activities are delivered via an intent. The application specifies a PendingIntent callback (typically an IntentService) which will be called with an intent when activities are detected. The intent recipient can extract the ActivityRecognitionResult using extractResult(android.content.Intent). See the documentation of PendingIntent for more details.
I would recommend a different approach. The problem with the Google Activity recognition API is that you cannot be confident about it reporting a certain event until its confidence level is >75. To have a confidence level of >75, you need to increase the detection level, which in turn can consume a lot of battery. I’d recommend trying some free SDKs like Atooma, tranql or Neura (you can find them online). These give you much better insights about your users and, in some cases, consume only around 1% of your battery life
Related
Let's say I want to build an app which requests current location periodically (e.g., every 10 minutes, this number should be configurable) and submits to a server.
I'm aware that Foreground Service and WorkManager are normally suggested for this kind of scenario. However which is would suit more? Below are my thoughts and doubts.
WorkManager - is mainly for deferrable background work whose execution is guaranteed. However I know that from Android 8 (API 26) background location was introduced and that restrict location to be updated only a few times every hour https://developer.android.com/about/versions/oreo/background-location-limits. Thus this perhaps doesn't meet the periodical updates as per the requirement.
ForegroundService - is perfect for something that runs and needs to make users aware of. It's recommended for this kinda scenario (location tracking) for privacy purpose. Google also creates a sample app to promote this practice https://github.com/android/location-samples/tree/master/LocationUpdatesForegroundService.
From the above analysis, it seems ForegroundService is the one. However I also found that WorkManager has a built-in support to use Worker in conjunction with ForegroundService via androidx.work.impl.foreground.SystemForegroundService https://developer.android.com/topic/libraries/architecture/workmanager/advanced/long-running#long-running-kotlin
That makes me confused as to what should I use and what Google really recommend for this specific scenario.
Anyone has any idea?
If you want to communicate somehow with the service then use foreground service and if you want to have some processed input based on something else you did in that work manager then choose work manager.
Work manager doesn't have option to redeliver intents and all other commands like start sticky etc...
Since work manager is more suitable for syncing data with db, processing a file etc..
If you were to ask me, I'd choose foreground service since you can add a type location to the xml tag when you register it in the manifest.
Both of these solutions don't survive OEMs aggressive battery restrictions since WorkManager's work can be deferred and if I want instant execution combined with wake locks I can easily do it in the foreground service since it also has a binder option that works well for UI sync.
I am designing an application which will collect different data from a lot of sensors and store them in a db, continuously. Sensors that I am using are like Google Play's fused location provider and activity detection. (There is some UI as well, but the UI will barely be launched, so almost everything is happening in the background)
I got two different ways to do this:
1) Start a longliving Service
So I would start a long-living service (with the STICKY flag), that would run in the background. The service would just register for periodic location and activity updates and - in between the updates - just do nothing.
Pros: App is only initialized once
Cons: Service is running 24x7
2) Register PendingIntent and use shortlived IntentService
Now Google Play's Location provider support registration of PendingIntent instead of callback [see here](https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderApi#requestLocationUpdates(com.google.android.gms.common.api.GoogleApiClient%2C%20com.google.android.gms.location.LocationRequest%2C%20android.app.PendingIntent) which is even recommended for background tasks.
Pros: The app can get 'shut down' between sensor events
Cons: Each IntentService might re-start the app if it was shut down inbetween, which probably has quite an overhead (initialize db, read shared prefs, initialize all classes, ...)
So my question is: Is it still recommended to use many short lived IntentServices for this kind of app? I haven't done any measurements yet, but I am worried, that each IntentService (and they will be launched quite often), re-starts my app, so that I end up spending more CPU time on initialization, etc. then just having a long-lived service lying dormant.
Anybody has experience with this?
My goal
Get user location updates for quite long time (e.g. 8 hours) with quite high frequency (e.g. every 30 seconds) even when the application is not running in foreground (meaning the activity where the location tracking was started might be destroyed).
Issue
I've found many articles regarding location tracking in Android apps.
The newer ones usually explain how to use Google Play Services' location APIs.
The problem is that in most cases, they demonstrate getting location updates in co-operation with Activity and LocationListener. For example in Google's tutorial. It's obvious this is not what I need. The only approach for long-running background location updates was based on periodical starting (via AlarmManager) of a service that run until it got accurate enough location update. However, this approach doesn't seem right for the frequency I need.
So, I ended up with custom idea how to solve the topic, but your critique would be welcomed. Here it is:
Idea of a possible solution
MainActivity - used just for starting/stopping the tracking by starting/stopping the MonitoringService
MonitoringService - a foreground service, where the whole connecting to LocationServices from Google Play services happens. Also, once connected a requestLocationUpdates method is called, but its variant with PendingIntent object. The pending intent contains intent invoking MyWakefulBroadcastReceiver class. Also, the service holds a partial wake_lock to prevent the device going to sleep and interrupting receiving of the location updates. Here, I'm not sure if holding the wake lock really helps.
MyWakefulBroadcastReceiver - extends WakefulBroadcastReceiver, just starts LocationProcessingIntentService via the startWakefulService
LocationProcessingIntentService - processes the location update passed via intent to it. Network communication performed here. Therefore, it is done in separate service and not directly in the MonitoringService
Currently, I have the solution described above implemented without acquiring the partial wake lock in the MonitoringService. When connected to debugger in Android Studio, I see the processing of the location updates work. However, I'm not sure what it will do after e.g. 4 hours of running without being connected to laptop (like it is for the debugging purposes)
Questions
Is this approach OK from architecture/performance/battery life point of view?
Should I use the wake lock for being sure the device won't go to sleep?
If answer to 2. is yes, do I still need to use WakefulBroadcastReceiver for starting the IntentService processing the location updates?
Any other recommendations?
What you have is mostly fine. You don't need the MonitoringService. The PendingIntent will wake your BroadcastReceiver, regardless of the state of your app. You don't need a permanent wake-lock. Just use the PendingIntent in your setup Activity to requestLocationUpdates.
Remember that the location services are already running in the background (as long as the user has enabled location services), so you don't need to run your permanent wake-lock service also (you can wake-lock after BroadcastReceiver#onReceive(), but don't forget to release the wake-lock after processing).
The only time you might have to worry about the PendingIntent not waking your BroadcastReceiver is if the user force-stops your app. In that case, you could choose to respect the user's decision. You can also explore using intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); which should wake your BroadcastReceiver from the stopped state, but I haven't tested this flag in this scenario.
Which one is best for continuous/time-wise server updates.
Some developers use AlarmManager followed by PendingIntent and some also use Looper with Handler.
So can anyone please explain me that which is best for continuous network updates and why.
Which one is best for continuous/time-wise server updates?
depends if your app suppose to run in background / foreground at that time:
let's say you are scheduling Runnable via handler to 15 minutes from now.
if the user will "close" all running activities, the system will probably kill your process if it not running any foreground services/activities after a while to reclaim memory.
in that case - your Runnable will never be executed.
if you want to continuously poll for server updates even when the user navigates away from your app - this option is obviously not good for you.
if you choose to update server like that - at least do it from a started Service context- that way your Handler reference will stay allocated even when user navigates from one screen to another...
on the other hand - providing pending intent to AlarmManager insures that no mater if your process is alive or not - the intent provided to the AlarmManager will wake up your app (and the Service / Activity / broadcast) you provided with the pending intent.
about your question - I think that none of the two are good solution to get server updates:
the user probably have 10-20 applications (such Facebook/Twitter/Whattsap/Viber/Google+...) installed on his device which getting updates from server.
imagine that each one of them wake up in some different time interval, opens internet connections, consuming lot's of precious battery life and band-width. that's crazy! your device will never "sleep", all process will be opened all the time, internet cellular radio transmission also. the battery will rich to 0% very fast!
the right think to do is to use the GCM API. it requires also server side implementation, but the general idea is that the responsibility to wake up your application when there is a new data passes to the server's side, and by that -the android application don't need to poll for updates. it just get notified (and wake up if the process not alive) when the server notified you.
in case you'll wonder - this is how it works - How does push notification technology work on Android?
I advice you to read about it - http://developer.android.com/google/gcm/index.html
I am new to Android, and I need some advices for start up.
I want to build an application, which will show up, when the user gets into some hot situation.
By hot situation I mean:
the GPS/cell coordinates are in known zone;
known Bluetooth device detected;
known Wi-Fi network detected;
weather info has change;
I see something running in background and when one of the clauses hit, it will trigger and open the app.
How to get started?
How do I make sure my app won't be shut down?
As I read somewhere that Android OS will terminate apps if memory out occurs or consumes too much, and my app would consume a lot, making repeated measures/checks to see if situation changed.
Regards,
Pentium10
You need to use a Service for the part of your application that runs in the background.
You might find the Application Fundamentals document in the Android Developer Documentation helpful. It says this about Services:
A service doesn't have a visual user interface, but rather runs in the background for an indefinite period of time. For example, a service might play background music as the user attends to other matters, or it might fetch data over the network or calculate something and provide the result to activities that need it.
In you case you might find the LocationManager Service helpful. It is a system Service which will you can use to notify your application based on GPS position.
However, I think you'll have to write your own Services to monitor Wi-fi, Bluetooth and weather.
You can use the AlarmManager Service to get your Service to perform particular tasks at certain intervals.
It depends on how & where you want to deploy your application. In my experience it boils down to
you create an application for a specific use case where battery drain matters less than accurate results (showcase situations, prototyping, ...)
you want to distribute the application to users.
In case 1) just create one service that aggressively polls the sensors / web services. Use the AlarmManager to send a REFRESH intent (AlarmService.setRepeating(...) ).
That REFRESH intent will restart the synchronization service everytime, even if it was killed by the system. onStart() will be called everytime the REFRESH intent is emitted. You can do heavyweight setup logic in onCreate() as this will be called everytime the service is created after it was destroyed. WARNING: This will possibly drain the battery very quickly.
In case 2) I would create several services and let the user configure different polling intervals for each service to limit battery drain. I can see for example that bluetooth should be polled more regulary than GPS as it is more likely that a bluetooth device suddenly appears than a user moving extremely fast.
Weather sounds extremely expensive (network lookup, possibly triggering a network connection!)
Please do not try to be too persistent with your app in case 2). It usually makes a lot of sense for a phone to kill memory / power draining services.