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.
Related
I am testing now open camera in foreground service in Android 11 and I have problem with new Android 11 restrictions: https://developer.android.com/guide/components/foreground-services
Pseudo code:
//Service1 is started by JobScheduler.
class Service1 extends Service {
...
startForeground(ID_OF_SERVICE1_NOTIFICATION, getService1Notification())
...
//Run another foreground service with open camera
Intent i = new Intent(getApplicationContext(), Service2.class)
ContextCompat.startForegroundService(context, i)
...
}
class Service2 extends Service {
...
startForeground(ID_OF_SERVICE2_NOTIFICATION, getService2Notification(), ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST);
openCamera() // <-- Policy exception
...
}
Class Service1 is started by JobScheduler with startForeground() and show notification to user. Service1 can start (ContextCompat.startForegroundService()) Service2 with startForeground() and show notification to user too. Service2 opens camera. The user sees notification all the time.
manifest edited:
<service android:name=".service.Service2"
android:foregroundServiceType="camera|microphone"
android:stopWithTask="false"/>
Edited starForeground() in Service2 with flag FOREGROUND_SERVICE_TYPE_MANIFEST: (a special value indicates to use all types set in manifest file)
The result from Logcat:
Foreground service started from background can not have location/camera/microphone access: service com.example.test/.service.Service2
Tried also FOREGROUND_SERVICE_TYPE_CAMERA|FOREGROUND_SERVICE_TYPE_MICROPHONE.
I would like to keep the automation in starting the camera for user.
Is there any way?
As far as I know, since android 11 there is no way to automatically start the camera from a foreground service, if the app was not visible to the user since the start of the app process. The user must interact with the application in order to be able to use the camera. According to the docs, these are the ways for an app to be considered interacted with, without actually opening an activity:
The service is started by a system component.
The service is started by interacting with app widgets.
The service is started by interacting with a notification. [note: Interacting! It is not enough to display the notification]
The service is started as a PendingIntent that is sent from a different, visible app.
The service is started by an app that is a device policy controller that is running in device owner mode.
The service is started by an app which provides the VoiceInteractionService. The service is started by an app that has the START_ACTIVITIES_FROM_BACKGROUND privileged permission.
I have an android application that uses Geofence and I'm having a hard time overcoming Doze mode. My manifest has the WAKE_LOCK permission and seven setNotificationResponsiveness to 0 for each region. I even changed PendingIntent to BroadcastReceiver but the app literally sleeps or is dead after a while with the deleted smartphone screen. I've already tried using LocationRequest
LocationRequest.setFastestInterval(1000);
LocationRequest.setInterval(2000);
Even so, I did not succeed. Has anyone managed to keep the application running with the Doze?
I faced the issues in My Chatting application and Location Tracking applications, While in doze mode we will not get any push, or we will not get any network connection or location details and most of the background operation will be blocked because of battery optimization, We can solve by 2 ways.
Priority push message(I used in my chatting application) - If you send normal push it will not reach the app until the mobile come to normal, If you send priority push it will reach the app you can do some process within few seconds, but this also have some limitation.
Foreground service, - For your scenario this is the best solution, You should have on service and that service should run as Foreground service so that you can get the Location information all time even in Doze mode.
WAKE_LOCK permission in the manifest is not enough for use a Wake Lock , you need to acquire and release the lock in your code, but starting with Android 6 Doze mode it goes to deep sleep also with an acquired wake_lock.
The way that works for me also with Doze mode :
In the Main Activity onStop I acquire a Partial WakeLock and I start a Service with STARTFOREGROUND_ACTION intent, the Service calls startForeground and shows a Notification.
On Activity onResume the WakeLock is released, the Service stops with STOPFOREGROUND_ACTION intent and the Service itself calls stopForeground & stopSelf.
I ended up putting my application to receive push messages. Apparently the app is no longer being killed by the operating system.
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.
I'm testing Activity Recognition API in 2 apps : Google sample code and implementation of this code in my app.
The problem is both apps keeps getting activity recognition fine but after a few hours the intent service stops and i'm not getting any activity recognition from both of them.
Any idea why the intent service stops even though i've tested geofencing api with intent service and it's working forever without stopping?
Your IntentService might "stop", I would say "fall asleep" because of:
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.
Basically it should be the case for most of the devices with API >= 20.
Please find more here.
Unfortunately, you can only request activity updates and it is impossible to force ActivityRecognitionApi to continuously give current activity even if it is "still" for some mysterious "extended period of time".
In my opinion, it would much more convenient if this feature of ActivityRecognitionApi was configurable.
Even registering broadcast receiver in Manifest file,you need to register in dynamically in Oreo+ otherwise it will not work. Try this.Add this code in main activity or in startCommand in Service.It worked for me.I have tested this code on Android 10 too..worked perfectly.You need not to register broadcast receiver in Manifest file.
#Override
protected void onStart() {
super.onStart();
IntentFilter intentFilter=new IntentFilter(Constants.BROADCAST_DETECTED_ACTIVITY);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(broadcastReceiver,intentFilter);
}
I have a service which has to monitor which application is in the foreground and based on the application do some functionality.
I can get the list of foreground applications, using ActivityManager.getRunningAppProcesses(). But with this I cannot monitor when the foreground application changes.
ex. when Application 1 which was foreground goes to background and a new Application 2 comes to foreground, the service should be notified about this.
Are there any Broadcasting happening in Android, so that my service can register to that and when there is a change in foreground application, the service gets a notification and can do the functionality as required.