Android Oreo JobIntentService 继续在 Android 7 及更低版本的后台运行,并在 Android 8 及以上版本中经常崩溃



我最近将所有服务都替换为前台服务和JobIntentService,因为在奥利奥及以上版本中有一些后台执行限制(https://developer.android.com/about/versions/oreo/background)。根据文档,JobIntentService 的行为类似于 Android 7 及更低版本的 Intent Service,类似于 Android 8 及更高版本的 JobScheduler。我注意到Google提供的新JobIntentService存在问题。

Android 8 及以上版本:

在 android 8 及更高版本中不断发生崩溃。这里有一张票提到了 https://issuetracker.google.com/issues/63622293 相同的问题,我添加了几个极客建议的临时修复程序。

Android 7及以下版本:JobIntentService,就像Intent Service一样,一旦工作完成,就不会停止。

我已经在一个服务中实现了JobIntentService,每当用户执行某些操作时都会触发。

法典

public class SampleJobIntentService extends FixedJobIntentService {
public static void postData(Context context, String data) {
Intent intent = new Intent(context, SampleJobIntentService.class);
intent.setAction(INITIAL_ACTION);
intent.putExtra(SAMPLE_ID, data);
SampleJobIntentService.enqueueWork(context,intent);
}
public static void enqueueWork(Context context, Intent work) {
SampleJobIntentService.enqueueWork(context, SampleJobIntentService.class, JOB_ID, work);
@Override
protected void onHandleWork(@NonNull Intent intent) {
if (intent != null) {
SampleRequest sampleRequest = requests.get(intent.getAction());
if (sampleRequest != null) {
try {
// perform some networking operations
} catch (Exception ex) {
Log.d("Error for intent ");
}
Log.i("send action ");
} else
Log.e("action not found for ");
}
}
}

为了避免JobIntentService崩溃,我从 https://issuetracker.google.com/issues/63622293 中获取了一些参考

资料
public abstract class FixedJobIntentService extends JobIntentService {
@Override
GenericWorkItem dequeueWork() {
try {
return new FixedGenericWorkItem(super.dequeueWork());
} catch (SecurityException ignored) {
doStopCurrentWork();
}
return null;
}
private class FixedGenericWorkItem implements GenericWorkItem {
final GenericWorkItem mGenericWorkItem;
FixedGenericWorkItem(GenericWorkItem genericWorkItem) {
mGenericWorkItem = genericWorkItem;
}
@Override
public Intent getIntent() {
if (mGenericWorkItem != null) {
return mGenericWorkItem.getIntent();
}
return null;
}
@Override
public void complete() {
try {
if (mGenericWorkItem != null) {
mGenericWorkItem.complete();
}
} catch (IllegalArgumentException ignored) {
doStopCurrentWork();
}
}
}
}

嗯...,这是一个很大的理论...!!它无法全部放在这里。我会尽力让你的一些概念清楚。


我已经失去了阅读谷歌文档的 2 年......哪些是use-less...带着no proper documentationno proper sample codes for its developers..!!所以我在stack-overflow上的每篇帖子中都提到了这一点,因为它将有助于节省他人的时间..!!


看起来你是一个优秀的程序员;只需要一些hints to your posted question

提示-1 :

您 :- 我最近将所有服务替换为前台服务,并且 工作意向服务

前台服务:

如果您需要ALL THE TIME RUNNING PROCESS; WHICH WILL NEVER END... ONCE IT IS STARTED它用于从其OnStartCommand返回START_STICKY的服务中。再次不建议使用,就好像您想不惜一切代价实现它一样......然后,您将不得不使用带有setOngoing(true)的通知 哪个最终用户将无法滑动您的通知,它将永远保留在那里......

前台服务的使用:

对接收者也有限制;以上Oreo以后,你不能通过在清单中声明它和只制作一个接收者来使用所有的接收者和意图行为......我建议只使用BootComplete权限并使用单个receiver,该接收boot_completed意图,并在低于 O 的情况下调用service,并在 O 以上调用前台服务。现在,从该前台服务中,您可以为所有服务实现运行时接收器,并在 Ondestroy 方法中取消注册它。我从来没有找到实现运行时接收器的官方示例代码,最后我通过几个月的努力成功实现了它......是的,由于谷歌,这不是一个聪明的工作

何时使用前台服务:

仅当您要实现广播接收器时。如果您不想实现任何广播接收器;远离。

提示-2 :

您 :- 我最近将所有服务替换为前台服务,并且JobIntentService

** 服务质量有其:**

只是做一个非常小的工作...然后退出...它必须由 StopSelf()退出...同样,Services can cause data-loss如果多次调用...由于同一个服务线程可以运行多次... 同样,如果您希望服务完成大量工作...使用START_STICKY...但同样不建议这样做,我已经建议何时在提示 1 中使用它。

** 意图服务具有:*的质量*

做一个相对较长的任务,它已经property of execution serially only如果你一次又一次地调用同一个intentService,那么所有的调用都将保持在一个queue中,并在完成one by oneone by one执行。如上所述,在服务中并非如此。它自己结束...无需由开发人员结束它..!!

** 所有:*的独特品质*

一旦他们被crashedandroid可以阻止他们将来打电话而不通知你,因为它使应用程序崩溃avoid crashtry-catch-exception。再。。。如果you are implementing threads within services那么try-catch-exceptionwill not save your application from being crashing...

** 那么到底是什么以及如何实现它,然后:**

使用FireBaseJobScedular:-

  1. 易于使用
  2. 使用简单的作业服务
  3. 可以运行更长或更短时间的任务...EVEN ALL THE TIME RUNNING TASK
  4. EVEN SUPPORTED BY NON STANDARD COMPANIES像vivo,mi,oppo,one+3,...它需要stock-android对其进行更改并给出诸如FunTouchOs,ColorOs,OxygenO之类的名称
  5. 只需将电池设置更改为"不优化此应用程序">
  6. 是的,谷歌正式支持它并建议使用它
  7. 它创建GooglePlyService实例并在其中运行,显然非标准公司也不会限制谷歌应用程序执行其任务。
  8. 适用于Oreo..,即使我已经在Android P上对其进行了测试,并且在 Android 5.0 版本以下作为AlarmManager任务工作。
  9. 我仍然建议使用minsdk above 16target sdk 26好像如果您想将应用程序上传到google play它现在是强制性的,并且您会听到该消息。 和compile sdk 26.
  10. 只需在清单中绑定您的JobService并使用单行权限receive_boot_complete
  11. 只需安排它...它将在每个制造商的市场上的每台设备上启动......即使在cold boothot boot
  12. 它最大限度地减少了很多很多代码和you can focus on actual tasks
  13. 任务完成后,您可以return false指示任务已完成,它将结束作业服务。

为什么我建议,因为我是一家UNKNOwn良好的公司CTO,并且经历了许多类型的Android手机制造商foreground service引起的问题......这不是Apple and ios,所以我们不得不体验它。在过去的 18 年里一直是开发人员,我今天也主要编码......在所有的开发项目中,其发展战略都只是我自己考虑的。

纠正我...太。。。由于您没有提到what your tasksproject与...以及您到底想在foreground service and intent-service......让我知道...,我很高兴能帮助你。这是一个一般的理论答案,而不是你想要的。但是为了给你实际的答案,我需要确切的项目范围。

JobIntentService,就像Intent Service一样,一旦工作完成,它就不会停止

问题出在您的扩展类 FixedJobIntentService dequeueWork 方法中。

尝试将其更改为如下所示的内容

GenericWorkItem superValue = super.dequeueWork();
if (superValue != null) {
return new FixedGenericWorkItem(superValue);
}
return null;

查看 JobIntentSerivce 代码,工作项处理器逻辑如下,即直到队列中没有剩余的工作项,所有项目都会被处理(即为每个项目调用 onHandleWork)

while ((work = dequeueWork()) != null) {
if (DEBUG) Log.d(TAG, "Processing next work: " + work);
onHandleWork(work.getIntent());
if (DEBUG) Log.d(TAG, "Completing work: " + work);
work.complete();
}

实现中的问题是在处理第一个工作项后,super.dequeueWork() 返回 null,您没有处理它,只是发送一个新的 FixedGenericWorkItem 对象传递 null 值。您可能会观察到在后续调用中将空值传递给您的 onHandleWork。

希望这有助于解决您的问题。

我认为你只需要这么多代码。创建一个新的类 MyJobIntentService 并编写大量代码并调用 postData() 来启动您的服务。

public class MyJobIntentService extends JobIntentService {
public static void postData(Context context, String data) {
final Intent intent = new Intent(context, MyJobIntentService.class);
intent.setAction(INITIAL_ACTION);
intent.putExtra(SAMPLE_ID, data);
enqueueWork(context, MyJobIntentService.class, 1000, intent);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
Ln.d("Cancelled service");
super.onDestroy();
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
if (intent != null) {
final SampleRequest sampleRequest = requests.get(intent.getAction());
if (sampleRequest != null) {
try {
// perform some networking operations
} catch (Exception ex) {
Log.d("Error for intent ");
}
Log.i("send action ");
} else {                
Log.e("action not found for ");
}
}
}
}

并确保在清单文件中添加您的服务

<service
android:name="service.MyJobIntentService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE" />

最新更新