JobIntentService - onHandleWork 并不总是被调用?
JobIntentService - onHandleWork is not always called?
我有主屏幕小部件,它有一个简单的 AppWidgetProvider
和 JobIntentService
,我可以在其中完成所有工作。
问题是 - 它的工作有点随机。有时它会,有时它不会 - 最奇怪的是,我可以在日志中看到,在每个小部件上更新 JobIntentService
的 enqueueWork
方法总是被调用,但 onHandleWork
方法只是有时被调用。
(我发现与电池优化有很强的相关性,但不是 100%。如果我打开“自动管理应用程序”,那么它 99% 可靠地工作。如果打开,就像掷硬币一样. 有时会,有时不会。Best to ilustrate behavior would be this short simple video
这是我的代码(小部件提供程序):
public class MyWidgetProvider extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.v("aaa", "onUpdate");
// super.onUpdate(context, appWidgetManager, appWidgetIds);
// update in my own Service (to avoid ANR)
Intent intent = new Intent(context, MyJobIntentService.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
MyJobIntentService.enqueueWork(context, intent);
}
@Override
public void onReceive(Context context, Intent intent) {
Log.v("aaa", "onReceive");
super.onReceive(context, intent);
}
}
这是我的服务 (JobIntentService),我负责所有工作:
public class MyJobIntentService extends JobIntentService {
public static final int JOB_ID = 1;
public static void enqueueWork(Context context, Intent work) {
Log.v("aaa", "enqueueWork: ");
enqueueWork(context, MyJobIntentService .class, JOB_ID, work);
}
@Override
protected void onHandleWork(Intent intent) {
Log.v("aaa", "onHandleWork: ");
}
}
这就是发生在我身上的同一件事。我发现在 android 文档中,它说:
When running as a pre-O service, the act of enqueueing work will
generally start the service immediately, regardless of whether the
device is dozing or in other conditions. When running as a Job, it
will be subject to standard JobScheduler policies for a Job with a
JobInfo.Builder.setOverrideDeadline(long) of 0: the job will not run
while the device is dozing, it may get delayed more than a service if
the device is under strong memory pressure with lots of demand to run
jobs.
这意味着在AndroidO及以上设备中,不保证jobIntentService立即启动,而是根据设备情况延迟启动。但是,一些 phone 制造商故意取消这项工作以延长电池寿命(例如 OnePlus)。所以这个工作永远不会被调用。
我使用的解决方法是创建一个 LOW_IMPORTANCE 前台服务并使用以下方式调用它:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(startIntent);
} else {
context.startService(startIntent);
}
但缺点是通知显示时间很短,直到工作完成。
也许 google 应该对设备制造商如何管理后台应用程序施加一些限制。
我有主屏幕小部件,它有一个简单的 AppWidgetProvider
和 JobIntentService
,我可以在其中完成所有工作。
问题是 - 它的工作有点随机。有时它会,有时它不会 - 最奇怪的是,我可以在日志中看到,在每个小部件上更新 JobIntentService
的 enqueueWork
方法总是被调用,但 onHandleWork
方法只是有时被调用。
(我发现与电池优化有很强的相关性,但不是 100%。如果我打开“自动管理应用程序”,那么它 99% 可靠地工作。如果打开,就像掷硬币一样. 有时会,有时不会。Best to ilustrate behavior would be this short simple video
这是我的代码(小部件提供程序):
public class MyWidgetProvider extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.v("aaa", "onUpdate");
// super.onUpdate(context, appWidgetManager, appWidgetIds);
// update in my own Service (to avoid ANR)
Intent intent = new Intent(context, MyJobIntentService.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
MyJobIntentService.enqueueWork(context, intent);
}
@Override
public void onReceive(Context context, Intent intent) {
Log.v("aaa", "onReceive");
super.onReceive(context, intent);
}
}
这是我的服务 (JobIntentService),我负责所有工作:
public class MyJobIntentService extends JobIntentService {
public static final int JOB_ID = 1;
public static void enqueueWork(Context context, Intent work) {
Log.v("aaa", "enqueueWork: ");
enqueueWork(context, MyJobIntentService .class, JOB_ID, work);
}
@Override
protected void onHandleWork(Intent intent) {
Log.v("aaa", "onHandleWork: ");
}
}
这就是发生在我身上的同一件事。我发现在 android 文档中,它说:
When running as a pre-O service, the act of enqueueing work will generally start the service immediately, regardless of whether the device is dozing or in other conditions. When running as a Job, it will be subject to standard JobScheduler policies for a Job with a JobInfo.Builder.setOverrideDeadline(long) of 0: the job will not run while the device is dozing, it may get delayed more than a service if the device is under strong memory pressure with lots of demand to run jobs.
这意味着在AndroidO及以上设备中,不保证jobIntentService立即启动,而是根据设备情况延迟启动。但是,一些 phone 制造商故意取消这项工作以延长电池寿命(例如 OnePlus)。所以这个工作永远不会被调用。
我使用的解决方法是创建一个 LOW_IMPORTANCE 前台服务并使用以下方式调用它:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(startIntent);
} else {
context.startService(startIntent);
}
但缺点是通知显示时间很短,直到工作完成。
也许 google 应该对设备制造商如何管理后台应用程序施加一些限制。