小米和 oppo 等中国 ROM 上的工作管理器,在电池优化下,将计划的工作延迟增加几个小时

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

小米和 Oppo 等中国 ROM 上的工作管理器,在电池优化下,将工作的计划延迟增加几个小时。但是,我注意到一些应用程序能够安静地安排工作 运行即使在电池优化下也能完美运行。 我注意到的一个区别是每次作业 运行s 时它们都会显示通知,那么电池优化器是否负责让应用程序保持活动状态?

而且我还注意到,我强行关闭那个应用程序后,24 小时后它又开始工作了,但这怎么可能呢?任何人都可以阐明幕后发生的事情,以及他们将使用什么方法吗?

如果需要更多详细信息,请告诉我。

这是一个已知问题,正如 Google 的问题跟踪器上的另一个错误中所评论的那样,WorkManager 在这些方面无能为力 cases.if 设备制造商已决定修改库存Android 要强制停止应用程序,WorkManager 将停止工作(JobScheduler、警报、广播接收器等也会停止工作)。没有办法解决这个问题。不幸的是,一些设备制造商会这样做,因此在这些情况下,WorkManager 将停止工作,直到应用程序下次启动。您也可以尝试使用 StartForgoundService() 直到并且除非您的工作未完成,否则您需要在前台显示通知。

过去曾问过类似问题 and here

这也在 WorkManager 的问题跟踪器上被问到:are the Chinese manufacturers (Huawei, Oppo, Xiaomi...) supported?

总而言之:这是一些 Android OEM 的已知问题,他们大量修改 Android 的这一部分以进行电池优化。 WorkManager 无法解决此问题

除了将您的应用程序添加到白名单之外,您实际上只能报告问题:

  • OEM(本例中为小米)避免此类重大更改。
  • 到Google,在CTS and avoid these behaviours by the OEMs. Please open an issue here中添加一个测试来记录问题到Google。

您可以在令人惊叹的网站 don't kill my app, also I've seen this library on github 上查看将不同设备添加到白名单中的应用程序的确切说明,这有助于简化用户的流程。

因此,保持作业 运行 准时的解决方案是为设备启用自动启动并禁用电池优化。 指导您的用户这样做很不方便,但截至目前,这是可以做到的!

这是更详尽的回应。 正如其他人所提到的,是的,工作经理无法正常工作。它可能会延迟完成工作。有时 15 分钟,有时 10 到 12 小时。没有解决方法。 但是,如果您想在特定的时间和日期执行任务,有一种方法可以做到。您应该使用带有广播接收器和前台服务的警报管理器。

所以这是 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);

}}

这是接收器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);
    }

}}

这是我在特定日期设置闹钟的地方:

 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);
    }

}

当然,您必须在清单中声明您的服务和广播接收者。 这很有魅力。

Xiomi MiUi 11(中文版固件)默认情况下 Work Manager 非常糟糕,随机运行几次,几个小时后它就停止了 working.Further 没有任何反应。为了解决这个问题,我采取了2个步骤

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

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

我添加到AutostartNo restrictions battery之后。我重新启动了设备,它与 Work Manager 一起正常工作。我认为在重度修改的中国设备上android,只能手动添加启动权限。