小米和OPPO等中国ROM的工作管理器,在电池优化时,将预定的工作延迟增加几个小时

Posted

技术标签:

【中文标题】小米和OPPO等中国ROM的工作管理器,在电池优化时,将预定的工作延迟增加几个小时【英文标题】:Work Manager on chinese ROMs like Xiaomi and oppo, when under battery optimization, increase the scheduled delay of work by several hours 【发布时间】:2020-05-11 08:59:03 【问题描述】:

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

我还注意到,在我强制停止该应用程序后,24 小时后它又开始工作了,但这怎么可能呢?任何人都可以了解幕后发生的事情以及他们将使用什么方法吗?

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

【问题讨论】:

您能否使用标准 ROM 检查您的应用在 android 模拟器中的行为,看看它的行为如何?这可以让您查看您的应用是否有任何问题,或者问题是否真的出在这些 OEM 的 ROM 上 它适用于股票 android,并且当电池优化被禁用时,作业按需要执行。 【参考方案1】:

小米 MiUi 11(中国版固件)默认工作管理器非常糟糕,并且以随机顺序运行多次,几个小时后它就停止工作。进一步没有任何反应。为了解决这个问题,我采取了两个步骤

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 之后。我重新启动了设备,它与工作管理器一起正常工作。我认为在对android进行大量修改的中国设备上,只能手动添加启动权限。

【讨论】:

是的,这就是我一直在使用的解决方案。【参考方案2】:

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

【讨论】:

【参考方案3】:

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

这就是 IntentService 类:

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


这是接收器类:

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


当然,您必须在清单中声明您的服务和广播接收器。 这就像一个魅力。

【讨论】:

【参考方案4】:

过去最好在here 和here 提出类似的问题。

WorkManager 的问题跟踪器上也有人问过这个问题:are the Chinese manufacturers (Huawei, Oppo, Xiaomi...) supported?

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

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

发给 OEM(在本例中为小米)以避免此类重大更改。 到 Google,在CTS 中添加测试并避免 OEM 的这些行为。请打开一个问题here 向 Google 记录问题。

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

【讨论】:

我知道,我已经查看了堆栈溢出的答案,但没有找到答案,所以对此感到满意,但是同样的行为应该会影响每个应用程序,有一个名为 life360 的应用程序和一个名为找到我的朋友,通过正常的电池限制设置和禁用自动启动,他们能够按预期定期运行,所以我只是想知道他们如何克服限制。 该应用可能默认被 OEM 列入白名单。这通常适用于市场上最常用的应用程序,例如 WhatsApp 等。正如我所写,WorkManager 在这些情况下无能为力。唯一的选择是让用户手动将您的应用添加到白名单。 Google 可以做的(并且已经在做)是向 OEM 解释为什么不实施这种行为很重要。 好的,我一直在尝试从工作中启动一个前台服务,然后从该服务中安排另一个工作并停止它,看起来它现在正在工作,几乎和其他应用程序一样。 我认为如果有一些前台工作已经完成,OEM 会认为这很重要并防止延迟暂停。【参考方案5】:

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

【讨论】:

是的,我读过这篇文章,但正如我提到的 life360 和 Find My friends 之类的应用程序能够在中文 Rom 上完成预定的工作,这才是真正让我感到困惑的地方。 OEM 默认将某些应用列入白名单。 我检查了应用程序的设置信息,它也在电池优化模式下工作,或者这个白名单实际上是在哪里完成的? 我有一个应用程序以某种方式设法按时发送通知。我不知道它是怎么做到的。虽然它不是一个著名的应用程序

以上是关于小米和OPPO等中国ROM的工作管理器,在电池优化时,将预定的工作延迟增加几个小时的主要内容,如果未能解决你的问题,请参考以下文章

不让小米和OPPO独美,vivo出击欧洲市场

oppo和小米手机后台定位服务不工作

在小米 android 11 设备上,我们的 android 应用程序的忽略电池优化权限被拒绝

偷偷超了华为和小米,他才是真正的人生大赢家!

用android的GCM 网络管理来优化电池使用时间

用android的GCM 网络管理来优化电池使用时间