Work Manager on chinese ROMs like Xiaomi and oppo, when under battery optimization, increase the scheduled delay of work by several hours
Asked Answered
P

5

6

Work Manager on Chinese ROMs like Xiaomi and Oppo, when under battery optimization, increase the scheduled delay of work by several hours., however, I have noticed some apps are able to have scheduled jobs run quietly flawlessly even under battery optimization. There is one difference I noticed is that they show a notification every time the job runs, so would that be responsible for keeping the app alive by the battery optimizer?

And I also noticed, that after I force stopped that app, after 24 hours it started working again, but how is that possible? Can anyone shed any light on what is going on behind the scenes, and what method they would be using?

Let me know if there are any more details required.

Pivoting answered 25/1, 2020 at 5:7 Comment(2)
Can you please check the behavior of your app in the Android emulator with a standard ROM to see how it behaves? This can allow to see if there's any problem in your app or if the issue is really with these OEM's ROMsNorther
It works fine with stock android and also when battery optimization is disabled, the jobs execute as wanted.Pivoting
P
3

So, turns out the solution to keep the jobs running on time is to enable auto-start and disable battery optimization for the devices. Guiding your users to do so is inconvenient but as of now, this is what can be done!

Pivoting answered 28/7, 2020 at 8:21 Comment(0)
O
6

Xiomi MiUi 11 (chinese version of firmware) Work Manager very badly by default and runs in random order several times and after a few hours it just stops working.Further nothing happens. To solve the problem, I took 2 steps

1. Settings->Battery & perfomance -> App battery saver -> Select you application -> No restrictions

2. Settings -> Apps -> Permissions -> Autostart -> Add your application to autostart

After I added to Autostart and No restrictions battery. I rebooted the device and it worked correctly with Work Manager. I think that on Chinese devices that have heavily modified android, it is only possible to manually add launch permissions.

Oletta answered 19/10, 2020 at 9:28 Comment(2)
Yes, that is the solution I have been using.Pivoting
Is there a robust way to do this programmatically, or atleast guide the users to the respected screens so they can do the needful.Emotive
P
3

So, turns out the solution to keep the jobs running on time is to enable auto-start and disable battery optimization for the devices. Guiding your users to do so is inconvenient but as of now, this is what can be done!

Pivoting answered 28/7, 2020 at 8:21 Comment(0)
G
3

This is the more elaborate response. As mentioned by the others, yes work manager doesn't work properly. It may do the work with a delay. some times 15 minutes and in some cases 10 to 12 hours. There is no workaround for that. But, if you want to do a task on a specific hour and date, there is a way to do that. you should use an alarm manager, with a broadcast receiver and a foreground service.

So this is the IntentService class:

public class NotificationService extends IntentService {


//In order to send notification when the app is close
//we use a foreground service, background service doesn't do the work.

public NotificationService() {
    super("NotificationService");
}

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

@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);

    return START_STICKY;
}

@Override
protected void onHandleIntent(@Nullable Intent intent) {

    sendNotification(intent);
}

private void sendNotification(Intent intent){

    Context context = NotificationService.this;

    PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent, 0);


    Notification.Builder builder = new Notification.Builder(context)
            .setTicker("Notification")
            .setContentTitle("Important Message")
            .setContentText("This is an example of a push notification using a Navigation Manager")
            .setSmallIcon(R.drawable.ic_add)
            .setContentIntent(pIntent);

    NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
    {
        String channelId = "Your_channel_id";
        NotificationChannel channel = new NotificationChannel(
                channelId,
                "Reminder to remind to review your notes",
                NotificationManager.IMPORTANCE_HIGH);
        channel.setDescription("Hello Dear friends"); //this is to test what this is
        notificationManager.createNotificationChannel(channel);
        builder.setChannelId(channelId);
    }


    Notification notification = builder.build();
    notification.flags = Notification.FLAG_AUTO_CANCEL;



    notificationManager.notify(0, notification);

}}

this is the Receiver class:

public class AlarmReceiver extends BroadcastReceiver {


@Override
public void onReceive(Context context, Intent intent) {

    Log.d("SHIT","YESSSS");
    Intent service = new Intent(context, NotificationService.class);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(service);
    } else {
        context.startService(service);
    }

}}

and this is where I set the the Alarm on a specific date:

 private void setNotificationAlarm(){
    //Alarm Manager

    Calendar time = Calendar.getInstance();

    time.set(Calendar.HOUR_OF_DAY,16);//set the alarm time
    time.set(Calendar.MINUTE, 50);
    time.set(Calendar.SECOND,0);
    AlarmManager am =( 
    AlarmManager)getContext().getSystemService(Context.ALARM_SERVICE);
    Intent i = new Intent(getActivity(), AlarmReceiver.class);
    i.setAction("android.intent.action.NOTIFY");
    PendingIntent pi = PendingIntent.getBroadcast(getContext(), 0, i, 
   PendingIntent.FLAG_ONE_SHOT);
   // am.setRepeating(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), 1000 * 60 * 10, 
  pi); // Millisec * Second * Minute



    if (Build.VERSION.SDK_INT >= 23){
        
  am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pi);


    }

    else{
        am.set(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pi);
    }

}

And of course you have to declare your Service and BroadcastRecevier in the manifest. This works like a charm.

Grube answered 9/8, 2020 at 11:37 Comment(1)
you won't believe I had a terrible experience with Alarm Manager. No matter what I did, it never got triggered on some Chinese devices while it worked 100% on my Samsung and some other devices. I resorted to using WorkManger.. it seemed it worked for more devices but some don't still get itHellas
N
1

Similar questions have best asked in the past here and here.

This has been also asked on WorkManager's issue tracker: are the Chinese manufacturers (Huawei, Oppo, Xiaomi...) supported?

To summarize: this is a known issue with some Android OEM that heavily modify this part of Android for battery optimization. There's nothing that WorkManager can do to solve this issue.

Aside having you application added to the whitelist, you can really only report the issue:

  • to the OEM (Xiaomi in this case) to avoid this kind of breaking changes.
  • to Google, to add a test in the CTS and avoid these behaviours by the OEMs. Please open an issue here to document the problem to Google.

You can take a look at the exact instruction to add to your app in a whitelist for the different devices on the amazing website don't kill my app, also I've seen this library on github that can be useful to simplify the process for your users.

Norther answered 25/1, 2020 at 9:10 Comment(4)
I know, I have gone through the stack overflow answers and didn't find the answers so was content with it, but this same behavior should affect every app, there is this app called life360 and one named find my friends, with normal battery restriction settings and disabled autostart they are able to run periodically as intended, so I was just wondering how could they have overcome the limitation.Pivoting
The app maybe whitelisted by the OEMs by default. That is usually true for the most used app in a market, like WhatsApp and similar. As I wrote, there's nothing that WorkManager can do in these cases. Only option is to have the user to manually add your app to the whitelist. What Google can do (and it's already doing) is to explain to the the OEMs why it is important to not implement this kind of behavior.Norther
Okay, i had been experimenting with starting a foreground service from work and then scheduling another work from the service and stopping it, seems like it's working now, nearly as well as the other app.Pivoting
I think if there's some foreground work done, the OEM considers that important and prevents delayed suspensions.Pivoting
S
0

This is a known issue and, as commented in this other bug on Google's issuetracker, there's not much that WorkManager can do in these cases.if a device manufacturer has decided to modify stock Android to force-stop the app, WorkManager will stop working (as will JobScheduler, alarms, broadcast receivers, etc.). There is no way to work around this. Some device manufacturers do this, unfortunately, so in those cases WorkManager will stop working until the next time the app is launched. Also you can try with the StartForgoundService() and until and unless your work is not done you need to show notification in forground.

Submersible answered 25/1, 2020 at 5:14 Comment(4)
Yes, I have read this, but as I mentioned apps like life360 and Find My friends, are able to get the scheduled job done on Chinese Roms, that's what's actually confusing me.Pivoting
Some apps are whitelisted by default by the OEMs.Norther
I checked the settings info of the app and it was also working under battery optimization mode, or where actually is this whitelisting done?Pivoting
I have an application that somehow managed to send notification on time. I don't know how is it doing this. It's not a famoud app thoughGrube

© 2022 - 2024 — McMap. All rights reserved.