问答中心分类: ANDROIDAndroid 8.0:java。lang.IllegalStateException:不允许启动服务意图
0
匿名用户 提问 18小时 前

在应用程序启动时,应用程序启动应该执行某些网络任务的服务。

原因:java。lang.IllegalStateException:不允许启动

据我所知,它与:后台执行限制

如果

在不允许的情况下“-它实际上是什么意思?以及如何修复它。我不想将我的服务设置为“前台”

Tim 回复 18小时 前

这意味着当你的应用程序在后台时,你无法启动服务

Tim 回复 18小时 前

你可能需要在运行时请求权限.

Tim 回复 18小时 前

试试firebase作业调度器。

Tim 回复 18小时 前

这与运行时权限无关

Tim 回复 18小时 前

使用startForegroundService()而不是startService().

Tim 回复 18小时 前

您可以尝试使用targetSdkVersion 25,但可以使用compileSdkVersion 26进行编译。通过这种方式,您可以使用Android 8和最新支持库中的新类,但您的应用程序将不受后台执行限制。

Tim 回复 18小时 前

@KacperDziubek应该会奏效,但这是一个临时解决方案,因为它将被要求在2018年秋季针对SDK26。

Tim 回复 18小时 前

@是的,这是真的。我写这篇评论时,还没有宣布Google Play将不允许更新SDK 26以下的应用。

Tim 回复 18小时 前

检查这个答案堆栈溢出。com/a/52236155/6401241

Tim 回复 18小时 前

我在安卓8上遇到了一个例外,即使我将target和编译sdk减少到25(或23)。在重写我的应用程序之前,我还能做什么其他的临时解决方案来在我的安卓8手机上工作吗?(我必须做一些认真的重写,但与此同时,我们需要这些应用。)

Tim 回复 18小时 前

我不知道那个项目到底是怎么回事,但我删除了它,重新创建了整个项目,现在它开始工作了。真可怜。

Tim 回复 18小时 前

我有一个类似的问题,通过在起始意图中添加“setComponent(MYSERVICE)”解决了这个问题。但我没有用API级别28测试它。

Tim 回复 18小时 前

后台操作建议使用Android O及以上JobScheduler。堆栈溢出。com/a/54570275/5217859

17 Answers
0
Sagar Kacha 回答 18小时 前

我找到了解决办法。对于8.0之前的设备,您只需使用startService(),但对于7.0之后的设备,您必须使用startForgroundService().以下是启动服务的代码示例。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(new Intent(context, ServedService.class));
    } else {
        context.startService(new Intent(context, ServedService.class));
    }

在服务类中,请添加以下代码以通知:

@Override
public void onCreate() {
    super.onCreate();
    startForeground(1,new Notification());
}

其中O是Android版本26。
如果你不想让你的服务在前台运行,而是想让它在后台运行,发布Android O后,你必须将服务绑定到如下连接:

Intent serviceIntent = new Intent(context, ServedService.class);
context.startService(serviceIntent);
context.bindService(serviceIntent, new ServiceConnection() {
     @Override
     public void onServiceConnected(ComponentName name, IBinder service) {
         //retrieve an instance of the service here from the IBinder returned 
         //from the onBind method to communicate with 
     }

     @Override
     public void onServiceDisconnected(ComponentName name) {
     }
}, Context.BIND_AUTO_CREATE);
Simon Hutton 回复 18小时 前

前台服务是用户将知道并需要通知的东西。如果运行时间太长,它也会出错。因此,如果应用程序已经在后台运行,那么这并不是一个真正合适的答案。

jayeffkay 回复 18小时 前

有一个ContextCompat.startForegroundService(...)在可替代使用的支持库中。

JacksOnF1re 回复 18小时 前

这不是解决办法。

Choletski 回复 18小时 前

安卓应用程序。RemoteServiceException:上下文。startForegroundService()当时未调用服务。startForeground()

Vratislav Jindra 回复 18小时 前

我也同意这不是一个解决方案。这是一个解决办法,也很有帮助,但奥利奥的背景限制是有原因的。以这种方式绕过这些限制肯定不是正确的方法(即使它有效)。最好的方法是使用JobScheduler(参考公认的答案)。

Vishal Patoliya ツ 回复 18小时 前

安卓应用程序。RemoteServiceException:startForeground:java的错误通知。lang.RuntimeException:服务通知的通道无效:通知(通道=null pri=0 contentView=null振动=null声音=null默认值=0x0标志=0x40颜色=0x00000000 vis=PRIVATE)

heeleeaz 回复 18小时 前

如果你必须显示一个空的前台通知,我认为这不会是一个好的用户体验。考虑到你必须Android 8.0引入了新方法startForegroundService(),在前台启动新服务。系统创建服务后,应用程序有五秒钟的时间调用服务的startForeground()方法,以显示新服务的用户可见通知。如果应用程序在时间限制内未调用startForeground(),系统将停止服务并声明该应用程序为ANR。

yUdoDis 回复 18小时 前

谢谢,这解决了我的问题。尽管我们也应该像其他答案中所解释的那样,研究如何使用JobIntentService!

Prizoff 回复 18小时 前

看来new Notificaction()安卓8.1不起作用;您应该创建通知通道:stackoverflow。com/a/47533338/1048087

Prizoff 回复 18小时 前

此外,来自文档:针对API构建的应用程序。版本代码。P或更高版本必须请求权限清单。准许为了使用这个API,我们需要一个服务。

Pierre 回复 18小时 前

我是否可以做一个检查,看看这个应用程序是否在前台?如果没有,不启动服务?

Prasad Pawar 回复 18小时 前

你不能从后台启动服务,startForegroundService()在Oreo和Pie中被破坏。此外,我还面临一些设备上的JobScheduler崩溃。Workmanager在后台使用作业调度程序,所以这不是我的解决方案。有谁有更好的解决方案吗?

VSim 回复 18小时 前

我发现它比作业调度器好得多。这太复杂了,而且我甚至不确定它是否能满足我的要求。我只想要一个在后台运行并接收某种系统通知的小服务。作业调度器可能会这样做,但会引入额外的延迟。前台服务OTOH只是向用户发出一个简短的非侵入性通知。我可以接受。

scarface 回复 18小时 前

这是否意味着我必须检查API>=26,如果是,则调用startForegroundService(),否则请致电startService()?

Tamim Attafi 回复 18小时 前

这种方法会给你一个错误:startForeground:java的错误通知。lang.RuntimeException:服务通知的通道无效:null

Autumn_Cat 回复 18小时 前

我想这要视情况而定。例如,如果使用套接字,解决方法就是解决方案

0
Murat Karagöz 回答 18小时 前

允许的情况是一个临时白名单,其中后台服务的行为与Android O之前相同。

在某些情况下,后台应用程序会被放置在临时白名单上几分钟。当一个应用程序在白名单上时,它可以不受限制地启动服务,并且其后台服务被允许运行。当应用程序处理用户可见的任务时,会将其置于白名单上,例如:

  • 处理高优先级Firebase云消息(FCM)消息。
  • 接收广播,例如SMS/MMS消息。
  • 从通知中执行挂起事件。
  • 在VPN应用程序升级到前台之前启动VPN服务。

资料来源:https://developer.android.com/about/versions/oreo/background.html
因此,换句话说,如果您的后台服务不符合白名单要求,您必须使用新的作业调度器.它基本上与后台服务相同,但它会定期被调用,而不是在后台连续运行。
如果您使用的是IntentService,则可以更改为JobIntentService。见@kosev’s回答如下.

Alex Radzishevsky 回复 18小时 前

在我收到GCM“high”prio的信息后,我想开始服务,但我遇到了一个故障。我仍然使用GCM:“com.google.android.gms:play services GCM:11.4.2”,而不是“com”。谷歌。firebase:firebase消息:11.4.2’。但我不确定这是否重要。。

Melllvar 回复 18小时 前

“它基本上与后台服务相同,但它会定期被调用,而不是在后台连续运行。”-我不确定你说的是什么意思,因为Android服务从来没有连续运行过。它们启动、运行,然后关闭。

Cord Rehn 回复 18小时 前

是吗FirebaseInstanceIdService以及它的onTokenRefresh方法一个高优先级FCM消息?

Abhinav Upadhyay 回复 18小时 前

@phnmnn不,GCMTaskService并不真正遵循FCM,因此它们不起作用。

Abhinav Upadhyay 回复 18小时 前

@CordRehn是的,FirebaseInstanceIdService会有用的,不用担心。遵循以下文件:在这里

kosev 回复 18小时 前

使用新JobScheduler最简单的方法是通过JobIntentService。看看我的答案。

android developer 回复 18小时 前

你不应该使用WorkManager(这里:开发商安卓com/topic/libraries/architecture/workmanager)而不是JobScheduler或其他?我是说:尤图。be/IrKoBFLwTN0

Diego dos Santos 回复 18小时 前

+1.考虑到“接收广播”是一个白名单的情况,用这个类“不再普遍有用”的理由来否定WakefulBroadcastReceiver对我来说没有意义,因为它也是一个广播接收器。弃用说明如下:开发商安卓com/reference/android/support/v4/content/…

makovkastar 回复 18小时 前

我有一个应用程序,它不做列表中要列入白名单的任何事情,而且在后台调用startServices()时仍然不会抛出任何异常。请检查我的问题:堆栈溢出。com/questions/52316856/…

Gerry 回复 18小时 前

这很好,但我以前被误导过。我真的必须使用JobScheduler吗?所有人都在谈论startForegroundService/startForeground吗?

0
kosev 回答 18小时 前

最好的方法是使用JobIntentService使用Oreo的新JobScheduler或旧服务(如果不可用)。
在你的舱单上声明:

<service android:name=".YourService"
         android:permission="android.permission.BIND_JOB_SERVICE"/>

在您的服务中,您必须用onHandleWork替换onHandleIntent:

public class YourService extends JobIntentService {

    public static final int JOB_ID = 1;

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, YourService.class, JOB_ID, work);
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        // your code
    }

}

然后,您可以从以下内容开始服务:

YourService.enqueueWork(context, new Intent());
Dr.jacky 回复 18小时 前

@拉尔夫加布开发商安卓com/about/versions/oreo/…

Malik Motani 回复 18小时 前

如何在静态方法中调用非静态方法?你能解释一下吗?

hgoebl 回复 18小时 前

@麦迪enqueueWork(...)也是一种静态方法。

TheLearner 回复 18小时 前

你会把你的服务打到哪里。排队工作(上下文,new Intent())?从广播接收器?

TALE 回复 18小时 前

我不认为这是最简单的解决方案。请参阅下面我对WorkManager的评论。它在适当的时候使用JobIntentService,但它的锅炉板要少得多。

0
Harini S 回答 18小时 前

如果服务正在后台线程中通过扩展IntentService,你可以替换IntentService具有JobIntentService这是作为Android支持库的一部分提供的
使用JobIntentService是的,它表现为IntentService在pre-O设备和O及更高版本上,它将其作为作业进行调度
JobScheduler也可用于定期/按需工作。但是,请确保将向后兼容性作为JobSchedulerAPI仅在API 21中提供

kilokahn 回复 18小时 前

JobIntentService的问题在于,Android可以随意安排您的工作,而且与IntentService不同,如果不进行一些修补,它无法隐式启动。看见堆栈溢出。com/questions/52479262/…

0
P.K 回答 18小时 前

是的,那是因为你不能再在API 26的后台启动服务了。所以你可以在API 26上启动前台服务。
你必须使用

ContextCompat.startForegroundService(...)

并在处理泄漏时发布通知。

Ricardo A. 回复 18小时 前

OP明确表示,他不想成为前景。这应该作为评论或更完整答案的一部分。