在onStartCommand中,传递的Intent为空的原因

106
除了系统通过像START_STICKY这样的标志重新启动服务之外,在传递给onStartCommand(Intent, int, int)的Intent为空的其他原因吗?
另外,当系统重新启动服务时,Intent.getAction()方法有时会返回NULL...但Intent不为NULL,只有getAction()为空。
我在此处也提出了这个问题,但还没有收到答案。
更新:在我的服务中,Mark Murphy建议我在onStartCommand()回调中返回START_REDELIVER_INTENT而不是START_STICKY,以便在重新启动后发送整个intent。
我最初没有这样做,因为我担心如果服务正在尝试执行某些操作,那么在执行该操作的过程中重新启动服务...它会认识到它开始执行该操作吗?我想这是我需要负责的逻辑 :)

17
请不要在问题中编辑答案,而是添加一个答案并接受它,这样您的问题就不会继续显示在未回答的问题集中了--谢谢。 - Dale Wilson
2
对于有类似问题的人,我想提醒一下。我发现当我在onStartCommand()中得到“intent为null”的错误时,通常是由于此之前LogCat显示了某些其他的错误所致。我不知道为什么会这样,但这是我观察到的,并且很容易忽略它。 - Piotr Chojnacki
2
@DaleWilson 我想这个问题还没有真正解决。除非我得到一个明确的答案,解释为什么Intent为空或如何避免使用START_REDELIVER_INTENT而不出现空Intent(后来我了解到这不是我需要的,但仍然可以解决一些人的问题,因此我留下了我的编辑),否则我无法接受答案。 - rf43
1
@DDoSAttack 不太重要。在我的情况下,例如,在某个活动中出现了“NullPointerException”。后来是其他错误。但在这两种情况下,我的堆栈跟踪显示,当此错误发生时正在运行的服务具有“意图”,该“意图”为空,就像您的情况一样。我想了很长时间出了什么问题,当我决定向上滚动堆栈跟踪时,它似乎在顶部某处出现了真正的错误。解决了这个问题后,“null”“intent”的问题也消失了。 - Piotr Chojnacki
@PiotrChojnacki 完全正确 +1。我向上滚动并找到了另一个导致进程被杀死的错误。 - likejudo
显示剩余2条评论
2个回答

53

我惊讶地发现没有讨论即将到来的标志。我将使用以下方式在日志中监控此内容:

if (null == intent || null == intent.getAction ()) {
        String source = null == intent ? "intent" : "action";
        Log.e (TAG, source + " was null, flags=" + flags + " bits=" + Integer.toBinaryString (flags));
        return START_STICKY;
}

更新: 标志位为0,因此没有可操作的内容。我保留了null检查,并且没有丧失功能。

编辑: 好吧,我在文档的START_STICKY中找到了它!“如果没有任何待处理的启动命令要传递给服务,则会使用空意图对象调用它,因此您必须注意检查此项。”

http://developer.android.com/reference/android/app/Service.html


8
在 Kotlin 中,Intent 被标记为非空(not-null),如果 Intent 为空,则会导致应用程序崩溃。在以下代码中,Intent 参数被标记为非空,并且在接收到空的 Intent 时会导致应用程序崩溃:override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {} - Muhammad Naderi
@MuhammadNaderi 你可以直接将 Intent? 作为意图。这对我有用。但是当然,你需要正确处理空意图。 - Patrick Boos
@PatrickBoos “但是你需要正确处理空意图”;你的意思是什么?怎么做?谢谢。 - Dr.jacky
1
我的意思是在你的代码中只需将 onStartCommand(intent: Intent?, ...) 进行修改,它应该可以工作。然后,不要使用 intent!!,而是正确地检查 intent 是否为空。 - Patrick Boos

1

在您的回调函数中返回START_REDELIVER_INTENT

    public int onStartCommand(Intent intent, int flags, int startId) {

        // your service code here

        return android.app.Service.START_REDELIVER_INTENT; // make sure restart delivers the intent
    }

这是一个意外的默认设置,大多数情况下你不想要 START_STICKY,而是要选择 START_REDELIVER_INTENTSTART_REDELIVER_INTENT 是期望的行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接