Android O - Old Start Foreground Service Still Working

Minimal android foreground service killed on high-end phone

A service started by startForeground belongs to the second most important group visible process:


  1. A visible process is doing work that the user is currently aware of,
    so killing it would have a noticeable negative impact on the user
    experience. A process is considered visible in the following
    conditions:

  2. It is running an Activity that is visible to the user on-screen but not in the foreground (its onPause() method has been called). This
    may occur, for example, if the foreground Activity is displayed as a
    dialog that allows the previous Activity to be seen behind it.

  3. It has a Service that is running as a foreground service, through Service.startForeground() (which is asking the system to treat the
    service as something the user is aware of, or essentially visible to
    them).

  4. It is hosting a service that the system is using for a particular feature that the user is aware, such as a live wallpaper, input method
    service, etc.

The number of these processes running in the system is less bounded
than foreground processes, but still relatively controlled. These
processes are considered extremely important and will not be killed
unless doing so is required to keep all foreground processes running
.

That being said, you can never be sure that your service is not killed at any time. E.g. memory pressure, low battery etc. See who-lives-and-who-dies.


For how to handle it, basically you answered the question yourself. The way to go is START_STICKY:

For started services, there are two additional major modes of
operation they can decide to run in, depending on the value they
return from onStartCommand(): START_STICKY is used for services that
are explicitly started and stopped as needed, while START_NOT_STICKY
or START_REDELIVER_INTENT are used for services that should only
remain running while processing any commands sent to them
. See the
linked documentation for more detail on the semantics.

As a general guideline you should do as little as possible in the background (ore foreground) service, i.e. only do the location tracking and keep everything else in your foreground activity. Only the tracking should require very little configuration an can be loaded quickly. Also the smaller your service is the less likely it is to be killed. Your activity will be restored by the system in the state that is was before it went into background, as long as it is not killed as well. A "cold-start" of the foreground activity on the other hand should not be a problem.

I don't consider that as ugly, because this guarantees that the phone always provides the best experience to the user. This is the most important thing it has to do. That some devices close services after 30 minutes (possibly without user interaction) is unfortunate.

So, as you stated, you have to

Persist everything in the service in e.g. a Room database. Every
variable, every custom class, every time any of them changes and then
start the service with START_STICKY.

See creating a never ending service

Implicit question:

Depending on how long it takes for Android to re-create the
service after killing it, a large portion of locations may be lost.

This usually takes only a really short time. Especially because you can use the Fused Location Provider Api for the location updates, which is an independent system service and very unlikely to be killed. So it mainly depends on the time you need to recreate the service in onStartCommand.

Also take note that from Android 8.0 onwards you need to use a
forground service because of the background location
limits.


Edit:
As recently covered in the news:
Some manufacturers may give you a hard time to keep your service running. The site https://dontkillmyapp.com/ keeps track of the manufacturers and possible mitigations for your device. Oneplus is currently (29.01.19) one of the worst offenders.

When releasing their 1+5 and 1+6 phones, OnePlus introduced one of the
most severe background limits on the market to date, dwarfing even
those performed by Xiaomi or Huawei. Not only did users need to enable
extra settings to make their apps work properly, but those settings
even get reset with firmware update so that apps break again and users
are required to re-enable those settings on a regular basis.

Solution for users

Turn off System Settings > Apps > Gear Icon > Special Access > Battery
Optimization.

sadly there is

No known solution on the developer end

How to start a Foreground Service in Oreo and up after boot complete?

Use startForegroundService() to start the foreground service.

Foreground notification service not working in one plus devices

So I solved this question just one hour ago:

Manifest

<application
android:name=".AppNotification"
android:allowBackup="true"
android:icon="@mipmap/pro_icon"
android:label="@string/app_name"
android:roundIcon="@mipmap/pro_icon"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<service
android:name=".services.TrackingBackgroundService"
android:enabled="true"
android:exported="true" />

Application - creating a notification channel

public class AppNotification extends Application {

public static final String CHANNEL_ID = "AppNotificationChannel";
private void CreateNotificationChannel() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"App Notification",
NotificationManager.IMPORTANCE_HIGH
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}

}

Activity

first you need to ask to the user to disable battery optimizations :

Intent intent = new Intent();
String packageName = this.getPackageName();
PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
if (pm.isIgnoringBatteryOptimizations(packageName))
intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
else {
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
}

then you need to start the service like this to handle different versions:

public void startService() {
Intent serviceIntent = new Intent(InitSkipperActivity.this, TrackingBackgroundService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent);
} else {
startService(serviceIntent);
}
}

Service

public class TrackingBackgroundService extends Service {

@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onCreate() {
super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent notificationIntent = new Intent(this, TrackingActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("title")
.setContentText("content")
.setSmallIcon(R.mipmap.pro_icon)
.setPriority(5)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);

return START_STICKY;
}

}

After this you need to test your service with the android profiler:

My app was with an abnormal CPU usage and on Oppo, OnePlus and Xiaomi and Samsung when I was offline tracking was using
50 to 60% CPU. found it was some threads that I called interrupt but were still running

after learning to use, start recording pieces of your app and analized them, you have 2 good options to start:

  • Sample Java Methods

  • Trace Java Methods

The Android Logcat its good to see the BG detect of oneplus trying to delete your service and if needed your app.

P.S: BGDetect eliminates without fear. I need to put my tracking performance both online and offline to an average of 20% to 30% in app and 15% to 20% on sleep before OnePlus and Oppo stop killing me without giving me the chance of rebooting my service.

As you probably already noticed when these OS want to kill something they start from the app an not from the service, keep in mind: DO NOT BOUND an app to a SERVICE if you do this I do not know why but the OS is even more relentless.

BG-Detect is too much -> they should've given the android devs the warning when reimplemented the function

P.P.S
It's too much, but I take my hat OnePlus BugHunters, its damm well implemented.

Hope I could help.

tested on OP3 Oreo 8.0.1

Editted

OnePlus on reboot sets your app to optimized again. Am testing to fix the ussue



Related Topics



Leave a reply



Submit