将 Context.startForegroundService(Intent) 而不是 Context.startService(Intent) 用于前台服务有啥好处吗?
Posted
技术标签:
【中文标题】将 Context.startForegroundService(Intent) 而不是 Context.startService(Intent) 用于前台服务有啥好处吗?【英文标题】:Are there any benefits to using Context.startForegroundService(Intent) instead of Context.startService(Intent) for foreground services?将 Context.startForegroundService(Intent) 而不是 Context.startService(Intent) 用于前台服务有什么好处吗? 【发布时间】:2018-01-13 11:29:59 【问题描述】:我在the docs 中读到Context.startForegroundService()
有一个隐含的承诺,即启动的服务将调用startForeground()
。但是,由于 android O 对后台和前台服务进行了更改,与使用旧的 startService()
方法相比,它是否有任何其他性能改进,或者它只是未来的最佳实践?
【问题讨论】:
【参考方案1】:这既不是性能改进,也不是好处,也不是最佳实践。
从 API 26 开始,系统只是不允许后台应用创建后台服务。
所以,如果您的应用在后台(如果它也在前台,欢迎您这样做),您必须使用@ 987654321@ 而不是之前的startService(Intent)
。服务必须在启动后的前 5 秒内调用startForeground(int, Notification)
,否则系统将停止服务。
还应该提到的是,有信息表明从后台应用程序使用startService(Intent)
启动服务的旧方法在当前版本的 Android Oreo 上仍然有效,但很快就会修复。
因此,从 API 26 开始,您希望在启动前台服务时使用新的 Context.startForegroundService(Intent)
方法而不是 startService(Intent)
。
【讨论】:
there is information that old way with starting a service with startService(Intent) from a bacjground app still works
有来源吗?
是否意味着我必须检查API是否>= 26,如果是,则调用startForegroundService()
,否则调用startService()
?
@scarface 是的,你必须检查它,否则尝试从后台应用程序调用startService()
方法时会抛出异常。但我相信你可以避免手动代码来检查你是否使用标准的 Android compat
lib。
问题是那 5 秒是很短的一段时间。如果系统很忙,应该调用 startForeground 的 Service 对象可能不会被调用超过 5 秒,并且它偶尔会(并非总是)使应用程序崩溃。谷歌方面的设计非常糟糕,目前尚不清楚如何解决。有什么想法吗?
@OlegGryb 您是否尝试在 Android 错误跟踪器中找到您的问题的答案,或者可能在那里发布错误以查看 Android 团队可以针对此特定问题提供什么建议?【参考方案2】:
正如我在here 中解释的那样,startForegroundService 有一个严重的问题,这将不可避免地导致不频繁的 ANR。由于无法在应用级别解决此问题,因此不应使用 startForegroundService。我切换到JobScheduler and JobService 模型来实现相同的功能。
到目前为止,后一种模型运行良好,我再也没有在 Play 商店中看到应用程序崩溃。不过,新模型完全不同,我花了两天时间基于 startForegroundService 重构现有代码,但它确实得到了回报。
【讨论】:
以上是关于将 Context.startForegroundService(Intent) 而不是 Context.startService(Intent) 用于前台服务有啥好处吗?的主要内容,如果未能解决你的问题,请参考以下文章
Javascript 将正则表达式 \\n 替换为 \n,将 \\t 替换为 \t,将 \\r 替换为 \r 等等