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

时间:2018-08-01 07:45:49

标签: android intentservice jobintentservice

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

Android 8及更高版本:

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

Android 7及更低版本: 工作完成后,像Intent Service一样的JobIntentService不会停止。

我已在服务中实现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();
            }
        }
    }
}

3 个答案:

答案 0 :(得分:6)

  

嗯...,这是一个很大的理论...!它不可能将所有内容都放在这里。我将尽我所能,这将使您的一些概念变得清晰。


我已经失去了整整2年的阅读google文档的时间... use-less ...用no proper documentationno proper sample codes for its developers .. !!所以我在stack-overflow的每篇文章中都提到了这一点,因为这将有助于节省其他人的时间。


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

提示1:

  

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

前台服务:

如果您需要ALL THE TIME RUNNING PROCESS; WHICH WILL NEVER END... ONCE IT IS STARTED,则将其用于服务中,该服务将从其START_STICKY返回OnStartCommand。还是不建议您使用它,就像您想不惜一切代价实施它一样...然后您将不得不使用带有setOngoing(true)的通知,该最终用户将无法清除您的通知,它将保留永远存在....

使用前台服务:

接收者也受到限制;从Oreo开始,您不能通过在清单中声明它并仅通过使其成为接收者来使用所有接收者和意图操作...我建议仅使用BootComplete许可并使用单个{{1 }}会收到receiver的意图,如果在O之下,则调用boot_completed,然后在O之上调用前景服务。现在,从该前景服务中,您将为所有对象实现运行时接收器,并在Ondestroy方法中取消注册。我从未找到用于实现运行时接收器的官方示例代码,但经过数月的艰苦努力,我终于成功实现了它。是的,由于google,这不是一个聪明的工作

何时使用前台服务:

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

提示2:

  

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

**服务的质量为:**

只需做一个很小的工作...然后退出...它必须由S JobIntentService退出...同样,如果多次调用topSelf() ...作为相同的服务线程可以运行不止一次...如果您想让服务执行大量工作,请再次使用... Services can cause data-loss ...但是不建议再次使用,我已经建议何时使用它在提示1中。

** Intentservice的质量为:**

做一个运行时间相对较长的任务,它有START_STICKY,如果您一次又一次调用相同的property of execution serially only,则所有调用都将保留在intentService中,并将被执行{{ 1}}完成queue之后。如上所述,服务中的情况并非如此。它本身就结束了...无需由开发人员结束。.

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

一旦他们one by one,Android便可以阻止他们在将来调用,而不会在崩溃时通知您。需要使用one by onecrashed来处理它们。再次...如果为try-catch-exception,则为avoid crash you are implementing threads within services ...

**然后是什么以及如何实施:**

使用try-catch-exception:-

  1. 易于使用
  2. 使用简单的JobService
  3. 可以运行更长或更短的时间... will not save your application from being crashing
  4. FireBaseJobScedular(例如vivo,mi,oppo,one + 3,...)需要EVEN ALL THE TIME RUNNING TASK对其进行更改,并命名为FunTouchOs,ColorOs,OxygenOs
  5. 只需要将电池设置更改为“请勿优化此应用”
  6. 是的,google正式支持它,建议使用它
  7. 它创建EVEN SUPPORTED BY NON STANDARD COMPANIES的实例并在其中运行,而且显然非标准公司也不会限制google应用执行其任务。
  8. stock-android上工作..,即使我已经在GooglePlyService上进行了测试,并且在Android 5.0以下版本中都可以作为Oreo的任务来工作。
  9. 我还是建议使用Android PAlarmManager,好像您要将应用程序上载到minsdk above 16一样,现在是强制性的,而且早已听到您的消息。和target sdk 26
  10. 只需将您的google play绑定到清单中并使用compile sdk 26的单行权限
  11. 只需安排它……它就会在每个制造商的市场上每个设备上启动……甚至在JobServicereceive_boot_complete
  12. 它最大限度地减少了很多代码和cold boot
  13. 任务完成后,您可以hot boot表示任务已完成,它将结束JobService。

为什么要提出建议,因为我you can focus on actual tasks是一家return false公司,并且在许多类型的android手机制造商中都经历过CTO引起的问题...不是UNKNOwn,所以我们不得不经历。自从过去18年以来一直保持开发人员的身份,我现在也主要编写代码...在所有开发项目中,其开发策略只由我自己考虑。

  

更正我...也...您没有提到foreground service,   Apple and ios与...有关,而您确实想要在   what your tasks ...让我知道...,很荣幸能为您提供帮助。这是一个一般性的理论答案,而不是您想要的。...但是要给您实际的答案,我需要确切的项目范围。

答案 1 :(得分:0)

我认为您只需要这么多的代码。创建一个新的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" />

答案 2 :(得分:0)

工作完成后,不会像Intent Service一样工作的JobIntentService

问题出在您的扩展类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,您不必理会它,而只是发送一个传递null值的新FixedGenericWorkItem对象。您可能会发现在后续调用中将空值传递给onHandleWork。

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