android crash后服务会停止吗,firebase - 由于后台执行限制,FirebaseMessagingService在Android O上崩溃 - 堆栈内存溢出...

@KaMyLL是对的。 我的应用程序遇到了同样的问题,可以通过用JobIntentService替换IntentService(我们已经在onTokenRefresh()启动onTokenRefresh()来解决它。

因为我发现JobScheduler和JobIntentService文档有点令人困惑,我想用一些代码片段来解决所有问题。 我希望这能使每个人都清楚这个问题。

是什么导致了这个问题?

由于Android 8的新背景执行限制 ,当应用程序可能处于后台时,您不应再启动后台服务:

当应用程序位于前台时,它可以自由地创建和运行前台和后台服务。 当应用程序进入后台时,它有一个几分钟的窗口,在该窗口中仍然允许创建和使用服务。 在该窗口的末尾,该应用程序被视为空闲。 此时,系统会停止应用程序的后台服务,就像应用程序已调用服务的Service.stopSelf()方法一样。

并且:

在许多情况下,您的应用可以使用JobScheduler作业替换后台服务。

因此,对于Android 7.x及更低版本,当应用程序处于后台时使用startService()(据我所知)没问题。 但在Android 8中,这会导致崩溃。 因此,您现在应该使用JobScheduler 。 JobScheduler和IntentService之间的行为差​​异是立即执行IntentService。 另一方面,不能保证立即执行排入JobScheduler的作业。 Android操作系统将确定何时有一个好的时间点,以便更节能。 所以可能会有延迟。 到目前为止,我不知道这需要多长时间。 因此,一种解决方案可能是检查操作系统版本并使用if-else分支您的代码。 幸运的是,支持库帮助我们以更优雅的方式解决这个问题,而无需复制任何代码: JobIntentService ,它基本上是为您做的。

如何重现这个问题?

上面的第一个引用声明该应用程序仍然“有一个几分钟的窗口,它仍然允许创建和使用服务。” ,因此,为了重现和调试问题(使用Firebase中的onTokenRefresh()示例),您可以在使用startService()启动服务之前设置断点。 关闭应用程序并在那里等待5-10分钟。 继续执行,您将看到此问题的IllegalStateException 。 能够将问题重现为基础,以确保我们的修复能够真正解决问题。

如何将我的IntenService迁移到JobIntentService?

我使用FirebaseInstanceIdService.onTokenRefresh()作为示例:

a)将BIND_JOB_SERVICE权限添加到您的服务:

android:exported="false"

android:permission="android.permission.BIND_JOB_SERVICE"/>

b)不是从IntentService扩展,只需从android.support.v4.app.JobIntentService扩展,将onHandleIntent(Intent)方法重命名为onHandleWork(Intent) ,并添加一个enqueueWork(Context,Intent)方便的函数:

public class FcmRegistrationJobIntentService extends JobIntentService

{

// Unique job ID for this service.

static final int JOB_ID = 42;

// Convenience method for enqueuing work in to this service.

public static void enqueueWork(Context context, Intent work) {

enqueueWork(context, FcmRegistrationJobIntentService.class, JOB_ID, work);

}

@Override

protected void onHandleWork(@NonNull Intent intent) {

// the code from IntentService.onHandleIntent() ...

}

}

c)使用enqueueWork()方便的函数启动作业:

public class ComfyFirebaseInstanceIdService extends FirebaseInstanceIdService {

@Override

public void onTokenRefresh() {

Intent intent = new Intent(this, FcmRegistrationJobIntentService.class);

// startService(intent);

FcmRegistrationJobIntentService.enqueueWork(this, intent);

}

}

我希望这个例子很有帮助。 至少在执行了这些步骤之后,我无法再在我的Android 8设备上重现该问题,并且它继续使用我的Android 7设备。

更新

在不推荐使用FirebaseInstanceIdService我们应该从代码中删除它,并使用FirebaseMessagingService onNewToken代替。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值