首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Android RemoteServiceExeption: Context.startForegroundService()当时没有调用Service.startForeground()

Android RemoteServiceExeption: Context.startForegroundService()当时没有调用Service.startForeground()
EN

Stack Overflow用户
提问于 2022-01-27 14:33:18
回答 1查看 3.8K关注 0票数 4

我知道,关于这个错误已经有很多问题了。但我尝试了很多解决方案,但对我来说没有什么效果。我的应用程序中有一个带有计时器的通知服务,crashlytics报告了数以百计的崩溃(Android8-12),如下所示:

ForegroundServiceDidNotStartInTimeException:

代码语言:javascript
运行
复制
Fatal Exception: android.app.ForegroundServiceDidNotStartInTimeException
Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{cac9d0b u0 com.malmatech.eggtimer/.NotificationUtil}

android.app.ActivityThread.throwRemoteServiceException (ActivityThread.java:2134)
android.app.ActivityThread.access$2900 (ActivityThread.java:309)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:2363)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loopOnce (Looper.java:226)
android.os.Looper.loop (Looper.java:313)
android.app.ActivityThread.main (ActivityThread.java:8582)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:563)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1133)

和RemoteServiceException:

代码语言:javascript
运行
复制
Fatal Exception: android.app.RemoteServiceException
Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{d760a21 u0 com.malmatech.eggtimer/.NotificationUtil}

android.app.ActivityThread$H.handleMessage (ActivityThread.java:2313)
android.os.Handler.dispatchMessage (Handler.java:107)
android.os.Looper.loop (Looper.java:213)
android.app.ActivityThread.main (ActivityThread.java:8178)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:513)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1101)

我检查了我的代码,并搜索了网络,但没有发现任何东西,也没有在我自己的设备或模拟器上得到这些异常.

只有在计时器运行且应用程序关闭时,才会显示通知。在我的onPause() TimerActivity中,我启动了服务:

代码语言:javascript
运行
复制
if (timerState == TimerState.Running){
    timer.cancel()
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        MyContext.getContext().startForegroundService(Intent(this, NotificationUtil::class.java))
    } else {
        startService(Intent(this, NotificationUtil::class.java))
    }
}

在onResume()中,我停止服务:

代码语言:javascript
运行
复制
try {
    MyContext.getContext().stopService(
        Intent(
            MyContext.getContext(),
            NotificationUtil::class.java
        )
    )
} catch (ex: Exception) {
    ex.printStackTrace()
}

这里是我的服务类,我删除了一些不相关的代码,但是管理通知的所有内容都应该包括在内。

代码语言:javascript
运行
复制
class NotificationUtil : Service() {
override fun onBind(intent: Intent?): IBinder? {
    return null
}

var eggCount = 1
private var secondsRemaining: Long = 0
private lateinit var timer: CountDownTimer
// some more, irrelevant for question

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    showNotification()
    log("onStartCommand executed with startId: $startId")
    if (intent != null) {
        val action = intent.action
        log("using an intent with action $action")
    } else {
        log("with a null intent. It has been probably restarted by the system.")
    }
    // by returning this we make sure the service is restarted if the system kills the service
    return START_STICKY
}

override fun onCreate() {
    super.onCreate()

    //irrelevant Code - getting an array from SharedPreferences and setting up textToSpeech

    showNotification()
    startTimer()
}

override fun onDestroy() {
    super.onDestroy()
    hideNotification()
    timer.cancel()
}

fun showNotification(done: Boolean = false) {
    val nBuilder = NotificationCompat.Builder(applicationContext, "menu_timer")
        .setSmallIcon(R.drawable.ic_notification_res_specific)
        .setOngoing(true)
        .setAutoCancel(true)
        .setDefaults(0)
        .setContentIntent(
            getPendingIntentWithStack(
                applicationContext,
                TimerActivity::class.java
            )
        )
        .setPriority(PRIORITY_MAX)
        .setVisibility(VISIBILITY_PUBLIC)
        .setNotificationSilent()

    if (!done) {

        //irrelecantCode, setting ginishedStr and finishedIndividualString

        nBuilder.setContentTitle(getString(R.string.eggTimerRunning))
        if (eggCount > 1) {
            nBuilder.setStyle(
                NotificationCompat.BigTextStyle().bigText(
                    getString(R.string.remainingTimeNotification) + " $finishedStr\n" + getString(
                        R.string.nextEggNotification
                    ) + " $finishedIndividualString"
                )
            )
                .setContentText(
                    getString(R.string.remainingTimeNotification) + " $finishedStr\n" + getString(
                        R.string.nextEggNotification
                    ) + " $finishedIndividualString"
                )
        } else {
            nBuilder.setStyle(
                NotificationCompat.BigTextStyle()
                    .bigText(getString(R.string.remainingTimeNotification) + " $finishedStr")
            )
                .setContentText(getString(R.string.remainingTimeNotification) + " $finishedStr")
        }
    } else {
        nBuilder.setContentTitle(getString(R.string.eggTimerDone))
            .setStyle(
                NotificationCompat.BigTextStyle().bigText(getString(R.string.BonAppetite))
            )
            .setContentText(getString(R.string.BonAppetite))
    }

    //irrelevant code

    val nManager =
        applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    nManager.createNotificationChannel("menu_timer", "Timer App Timer", true)

    nManager.notify(135678, nBuilder.build())

    val notification: Notification = nBuilder.build()
    startForeground(135678, notification)
}


private fun hideNotification() {
    val nManager =
        applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    nManager.cancel(135678)
}

private fun startTimer() {
    timer = object : CountDownTimer(secondsRemaining * 1000, 1000) {
        override fun onFinish() = onTimerFinished()

        override fun onTick(millisUntilFinished: Long) {
            secondsRemaining = millisUntilFinished / 1000
            showNotification()
        }
    }.start()
}

private fun onTimerFinished(ring: Boolean = true) {
    if (ring) {
        //irrelevant code, ring and vibrate if timer is finished
    }
    showNotification(true)
}

@TargetApi(26)
private fun NotificationManager.createNotificationChannel(
    channelID: String,
    channelName: String,
    playSound: Boolean
) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channelImportance = if (playSound) NotificationManager.IMPORTANCE_DEFAULT
        else NotificationManager.IMPORTANCE_LOW
        val nChannel = NotificationChannel(channelID, channelName, channelImportance)
        nChannel.enableLights(true)
        nChannel.lightColor = Color.BLUE
        this.createNotificationChannel(nChannel)
    }
}

private fun <T> getPendingIntentWithStack(
    context: Context,
    javaClass: Class<T>
): PendingIntent {
    val resultIntent = Intent(context, javaClass)
    resultIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP

    val stackBuilder = TaskStackBuilder.create(context)
    stackBuilder.addParentStack(javaClass)
    stackBuilder.addNextIntent(resultIntent)

    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        stackBuilder.getPendingIntent(0, PendingIntent.FLAG_IMMUTABLE)
    } else {
        stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
    }
}
}

提前谢谢你,我试着修复了几个星期,但很难修复它,因为一切都适合我自己。

EN

Stack Overflow用户

回答已采纳

发布于 2022-02-08 13:41:49

因此,我几乎解决了这个问题,不再每周发生数百起事故,而是每两天只发生一次。

在启动前台服务时,解决方案是这样的:只需等待主线程中的主活套,然后启动它。更常见的是,服务需要启动之前的5s现在已经足够了。

代码语言:javascript
运行
复制
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    Handler(Looper.getMainLooper()).post{
        MyContext.getContext().startForegroundService(Intent(this, NotificationUtil::class.java))
    }
} else {
            startService(Intent(this, NotificationUtil::class.java))
}
票数 4
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70880379

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档