To overcome the android OREO (targetSdkVersion 27) background service limitation, I have created a foreground service with Notification. Notification is showing in notification bar and so far the service is running. I have put my code related to Activity Recognition and Location Tracking using FusedLocationClient in the foreground service class. The ActivityRecognition and Location Tracking are working as expected when the phone is active or the screen is on. But they don’t work when the screen is off or in Doze mode. I am not sure whether I am misunderstanding the Android documentation that there should not have any limitation while using Foreground Service with visible Notification.
My primary target is to get user Activity Status and Location record on maximum 1/2 minutes interval. But my current foreground service provides location and activity fewer times and it only returns when the device screen is ON.
By the way, my foreground service is not a bound service and I start the service using following code:
Intent startIntent = new Intent(_context, ForegroundLocationService.class);
ContextCompat.startForegroundService(_context.getApplicationContext(),startIntent);
I am calling above code using a helper class which is called from MainApplication (extends Application) class, not from any activity class.
So, in OREO what else I have to do to achieve my target, please suggest me.
This only happens on Android Oreo. I'm using Play Services 11.4.2.
I'm registering geofences using the GeofencingClient and the addGeofences method with a pendingIntent to an IntentService that is handling geofence transitions.
It looks like the intent sent by the play services is blocked by the OS in certain conditions.
The system logs the following:
Background start not allowed: service Intent { cmp=my.app.id/my.package.struct.GeofenceTransIntentService (has extras) } to my.app.id/my.package.struct.GeofenceTransIntentService from pid=-1 uid=10154 pkg=my.app.id
as soon as I add a geofence in the following situations:
when I add it after the device boots
when I add it after the app was swiped
In both occasions the app is actually already running in the background (since I'm able to run the code that adds the geofence) because I listen to the PROVIDERS_CHANGED, BOOT_COMPLETED.
This is caused by the new Android Oreo background service limitations.
You have to change the PendingIntent from using a Service to using a BroadcastReceiver.
See this CodeLab for further information and example code.
In addition to switching to a BroadcastReceiver as mentioned in the accepted answer, I'd like to point out that although you will still receive BOOT_COMPLETED, you will not be able to receive PROVIDERS_CHANGED any longer.
PROVIDERS_CHANGED is an implicit broadcast and is not in the list of broadcast exceptions.
BOOT_COMPLETED is in the list of broadcast exceptions which is why you'll still receive it.
If you want to learn about an alternative approach to get the hook when location services is toggled, please see my answer to a related question for more details.
I have been trying to do something similar to truecaller app, where my app is supposed to show a screen after a call gets hung up. Was achieving this by registering android.intent.action.PHONE_STATE implicit broadcast in the manifest file.
But it is not working if I change the app to target Android O, because of the Android O broadcast limitation, and I'm trying to figure out an alternative solution to this use case.
Alternative solutions suggested in android docs: Job scheduler or register a service with context.
Job scheduler: Because of the Job scheduler optimizations there will be some delay to receive the callback. So it will affect the user experience if our app screen is shown a few min after the phone call and polling to check for new call logs every few seconds causes battery drain issue.
Register service with context in Java: I want the behavior to work even if the app is not active or alive. This will not work if the system kills the Service.
Register a Foreground Service: This requires a notification to be shown to the user all the time, which would be spam the user, and running a service 24/7 consumes lots of resources which defeats the whole purpose of broadcast limitation.
Please suggest an alternate solution so that the user experience remains the same.
Thanks in advance
Eventually, the action was added to the "Implicit Broadcast Exceptions" list so you can add ACTION_PHONE_STATE_CHANGED to your manifest and it will work:
https://developer.android.com/guide/components/broadcast-exceptions
ACTION_CARRIER_CONFIG_CHANGED,
TelephonyIntents.ACTION_*_SUBSCRIPTION_CHANGED,
"TelephonyIntents.SECRET_CODE_ACTION", ACTION_PHONE_STATE_CHANGED,
ACTION_PHONE_ACCOUNT_REGISTERED, ACTION_PHONE_ACCOUNT_UNREGISTERED
OEM
telephony apps may need to receive these broadcasts.
You have only one solution, use a foreground service and register the broadcast receiver in the service.
As there is NO proper solution to read the PHONE_STATE from Android O. The best alternative we can go for is to trigger a job on new call log entry from the content provider. By this, the behaviour is maintained of showing a screen(with a few sec of delay) after the call ends.
NOTE : The disadvantage is we cannot get the state of the phone call(Ringing or off_the_hook etc.,). The call back will only be received after the new call log has been added to the System DB.
For me, and my production app, the solution would be to avoid targeting api 25 and above, until a better workaround/api comes up.
If your app targets level 24 or below, you're not affected by the new Implicit Broadcast Limitations and your app can still listen to PHONE_STATE broadcasts even when your app is not running.
An app targeting lower APIs can still be downloaded and installed normally on new Android versions, the only reason to update your sdkTarget value is if your app requires usage of new APIs.
There seems to be an broadcast exception for ACTION_NEW_OUTGOING_CALL but not one for incoming call (or when call ends). It seems like a bug to have one for outgoing but not one for incoming. There's been a bug report filed in google issue tracker. Hopefully their answer will clarify what we should be doing.
I'll update this answer if/when the bug tracker gets updated.
As mentioned here: https://issuetracker.google.com/37273064#comment4, ACTION_PHONE_STATE_CHANGED (android.intent.action.PHONE_STATE) will be whitelisted for the Android O release. Though they may be replaced with a different mechanism in a future release.
I am Trying to make an app which app will be called if a particular thing triggered. In my App this thing is sms.. When a new Sms Receiving I Read its contents and i Look for a Specific Content If it presents an alarm will goes on.
If the App is opened its just working fine. The receiver triggers good... but when i clear recent apps receiver not triggering. I searched a lot here.. and Most of us saying that when an app in STOPPED_STATE it wont receive any notification that the particular thing happened.
I have an android device Hauwei and android version 4.4.4 and when i clear my recent application it completely destroy my app. the receiver stopped working.
I have tried to make an service and return start_sticky and for me its only possible with foreground process not for background tasks. But i don't want to push a notification which says myApplication running in your device.
Now What i want is I need A receiver which should receive SMS_RECEIVED even if the app is closed (here I am not talking about the STOPPED_STATE OF THE APP).
After clearRecentApps myApp is in STOPPED_STATE (i can see it in settings myApps FORCE_STOP button disabled). but at the same time WATSAPP , FACEBOOK AND CLASSOFCLANS are not it STOPPED_STATE( in settings those FORCE_STOP BUTTONS ARE ENABLED ONLY). without any foreground notifications.
How do they doing... Please help me guys... this taking lot of days for me..
If i am wrong let me Know. Iam New to android.. Any Help would be appreciated..
This may be a work around but to keep your service running even when your app is closed, you have to start your service again in your service's onDestroy() method.
#Override
public void onDestroy() {
super.onDestroy();
startService(new Intent(this, YourServiceClass.class));
}
In the demo video provided by google, it is said that you don't need to keep a service running to receive updates on activity recognition. But all code examples I could find show that you need to register ActivityRecognition in MainActivity for it to work.
How can I make Activity Recognition independent of application lifecycle?
For e.g. If a user is jogging, show him a notification to record his walk?
Can it work similar to a broadcast receiver which is called as soon a user is connected to wifi?
As an example you could subscribe to ActivityRecognition events when your phone booted successfully. You only need to do it once. After that the PendingIntent is called in the specified interval and you do not need to have a service running all the time in the background.