1.服务是什么(Service)
Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可通过绑定到服务与之进行交互,甚至是执行进程间通信 (IPC)。例如,
服务可在后台处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序进行交互
。
2.前台服务(ForegroundService)是什么?
前台服务执行一些用户能注意到的操作
。例如,音频应用会使用前台服务来播放音频曲目。前台服务必须显示通知。即使用户停止与应用的交互,前台服务仍会继续运行。
最常见的表现形式就是
音乐播放服务
,应用程序后台运行时,用户可以通过通知栏,知道当前播放内容,并进行暂停、继续、切歌等相关操作。
3.为什么用前台服务
后台运行的Service系统优先级相对较低,当系统内存不足时,在后台运行的Service就有可能被回收,
为了保持后台服务的正常运行及相关操作,可以选择将需要保持运行的Service设置为前台服务,从而使APP长时间处于后台或者关闭(进程未被清理)时,服务能够保持工作
。
4.前台服务使用
4.1定义前台服务
class ForegroundService : Service() {
companion object{
private const val TAG = "ForegroundService"
override fun onCreate() {
super.onCreate()
Log.d(TAG,"OnCreate")
override fun onBind(intent: Intent?): IBinder? {
Log.d(TAG,"onBind")
return null
override fun onUnbind(intent: Intent?): Boolean {
Log.d(TAG,"onUnbind")
return super.onUnbind(intent)
override fun onRebind(intent: Intent?) {
super.onRebind(intent)
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(TAG,"onStartCommand")
return super.onStartCommand(intent, flags, startId)
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy")
2022-01-16 09:46:27.430 22461-22461/com.yifan.service D/ForegroundService: OnCreate
2022-01-16 09:46:27.430 22461-22461/com.yifan.service D/ForegroundService: onStartCommand
4.2在AndroidManifest.xml注册服务
<service android:name=".ForegroundService" />
需要在Android 9(API级别28)或者以上使用前台服务需要请求FOREGROUND_SERVICE权限,FOREGROUND_SERVICE这个安装权限,因此系统自动授权给请求的APP;
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application ...>
<service android:name=".ForegroundService" />
</application>
</manifest>
需要在Android 9(API级别28)或者以上使用前台服务需要请求FOREGROUND_SERVICE权限,若没有请求FOREGROUND_SERVICE权限,系统会抛出SecurityException异常;
4.3创建服务通知内容,例如音乐播放,蓝牙设备正在连接等
companion object{
//通知ID
private const val NOTIFICATION_ID = 1111
//唯一的通知通道的ID
private const val notificationChannelId = "notification_channel_id_01"
* 开启前台服务并发送通知
private fun startForegroundWithNotification(){
//8.0及以上注册通知渠道
createNotificationChannel()
val notification: Notification = createForegroundNotification()
//将服务置于启动状态 ,NOTIFICATION_ID指的是创建的通知的ID
startForeground(NOTIFICATION_ID, notification)
//发送通知到状态栏
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(NOTIFICATION_ID, notification);
* 创建通知渠道
private fun createNotificationChannel(){
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
//Android8.0以上的系统,新建消息通道
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
//用户可见的通道名称
val channelName: String = "Foreground Service Notification"
//通道的重要程度
val importance: Int = NotificationManager.IMPORTANCE_HIGH
//构建通知渠道
val notificationChannel: NotificationChannel = NotificationChannel(notificationChannelId,
channelName, importance)
notificationChannel.description = "Channel description"
//LED灯
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.RED
notificationChannel.vibrationPattern = longArrayOf(0,1000,500,1000)
notificationChannel.enableVibration(true)
//向系统注册通知渠道,注册后不能改变重要性以及其他通知行为
notificationManager.createNotificationChannel(notificationChannel)
* 创建服务通知
private fun createForegroundNotification(): Notification {
val builder: NotificationCompat.Builder = NotificationCompat.Builder(applicationContext, notificationChannelId)
//通知小图标
builder.setSmallIcon(R.mipmap.ic_launcher_round)
//通知标题
builder.setContentTitle("苏宁窖藏")
//通知内容
builder.setContentText("苏宁是国内优秀的跨国企业?")
//设置通知显示的时间
builder.setWhen(System.currentTimeMillis())
//设定启动的内容
val activityIntent: Intent = Intent(this, MainActivity::class.java)
activityIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent: PendingIntent = PendingIntent.getActivity(this,
1,activityIntent, PendingIntent.FLAG_UPDATE_CURRENT)
builder.setContentIntent(pendingIntent)
//设置通知优先级
builder.priority = NotificationCompat.PRIORITY_DEFAULT
//设置为进行中的通知
builder.setOngoing(true)
//创建通知并返回
return builder.build()
注意事项:
创建和管理通知渠道,从Android8.0开始,需要为发送的美中不同类型的通知创建一个渠道,如果在Android8.0及以上在未指定通知频道的情况下发送通知,通知不会显示,会记录错误;
创建通知渠道的步骤:
1)通过一个唯一的channel ID ,对用户可见的channel name,通知重要程度importance level构建一个通知渠道;
2)可选的使用setDescription()指定用户在系统设置页面看到的关于通知的相关描述;
3)通过createNotificationChannel()注册通知渠道。
* 创建通知渠道
private fun createNotificationChannel(){
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
//唯一的通知通道的ID
val notificationChannelId = "notification_channel_id_01"
//Android8.0以上的系统,新建消息通道
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
//用户可见的通道名称
val channelName: String = "Foreground Service Notification"
//通道的重要程度
val importance: Int = NotificationManager.IMPORTANCE_HIGH
//构建通知渠道
val notificationChannel: NotificationChannel = NotificationChannel(notificationChannelId,
channelName, importance)
notificationChannel.description = "Channel description"
//LED灯
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.RED
notificationChannel.vibrationPattern = longArrayOf(0,1000,500,1000)
notificationChannel.enableVibration(true)
//向系统注册通知渠道,注册后不能改变重要性以及其他通知行为
notificationManager.createNotificationChannel(notificationChannel)
importance level主要有七种层次:
- IMPORTANCE_DEFAULT: 默认notification importance,可以在任何地方显示,有声音。
- IMPORTANCE_HIGH:可以在任何地方显示,有声音.
- IMPORTANCE_LOW:可以在任何地方显示,没有声音.
- IMPORTANCE_MAX:重要程度最高,可以在任何地方显示,有声音,可以在用户当前屏幕上显示通知,可以使用full screen intents.比如来电。
- IMPORTANCE_MIN:无声音,不会出现在状态栏中。
- IMPORTANCE_NONE:在任何地方都不会显示,被阻塞。
- IMPORTANCE_UNSPECIFIED:表示用户没有表示重要性的值。这个值是为了持久的首选项,并且永远不应该与实际的通知相关联。
4.4在Application或需要开启服务的地方调用
//启动服务
if(!ForegroundService.Companion.serviceIsLive){
mForegroundService = Intent(this, ForegroundService::class.java)
mForegroundService.putExtra("Foreground", "This is a foreground service.");
// Android 8.0使用startForegroundService在前台启动新服务
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
startForegroundService(mForegroundService)
}else{
startService(mForegroundService)
}else{
Toast.makeText(this, "前台服务正在运行中...", Toast.LENGTH_SHORT).show();
Android 8.0使用startForegroundService()在前台启动新服务
4.5在Application或其他地方停止服务
//停止服务
mForegroundService = Intent(this, ForegroundService::class.java);
stopService(mForegroundService)
4.6启动前台服务时创建通知
ForegroundService
override fun onCreate() {
super.onCreate()
//标记服务启动
serviceIsLive = true
val notification: Notification = createForegroundNotification()
//将服务置于启动状态 ,NOTIFICATION_ID指的是创建的通知的ID
startForeground(NOTIFICATION_ID, notification)
4.7停止服务,关闭通知
ForegroundService
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy")
stopForeground(true)
ForegroundService.serviceIsLive = false;
4.8完成整前台服务类
class ForegroundService : Service() {
companion object{
private const val TAG = "ForegroundService"
var serviceIsLive: Boolean = false
private const val NOTIFICATION_ID = 1111
//唯一的通知通道的ID
private const val notificationChannelId = "notification_channel_id_01"
override fun onCreate() {
super.onCreate()
Log.d(TAG,"OnCreate")
startForegroundWithNotification()
override fun onBind(intent: Intent?): IBinder? {
Log.d(TAG,"onBind")
return null
override fun onUnbind(intent: Intent?): Boolean {
Log.d(TAG,"onUnbind")
return super.onUnbind(intent)
override fun onRebind(intent: Intent?) {
super.onRebind(intent)
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(TAG,"onStartCommand")
//数据获取
val data: String? = intent?.getStringExtra("Foreground") ?: ""
Toast.makeText(this, data, Toast.LENGTH_SHORT).show()
return super.onStartCommand(intent, flags, startId)
* 开启前景服务并发送通知
private fun startForegroundWithNotification(){
//8.0及以上注册通知渠道
createNotificationChannel()
val notification: Notification = createForegroundNotification()
//将服务置于启动状态 ,NOTIFICATION_ID指的是创建的通知的ID
startForeground(NOTIFICATION_ID, notification)
//发送通知到状态栏
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(NOTIFICATION_ID, notification);
* 创建通知渠道
private fun createNotificationChannel(){
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
//Android8.0以上的系统,新建消息通道
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
//用户可见的通道名称
val channelName: String = "Foreground Service Notification"
//通道的重要程度
val importance: Int = NotificationManager.IMPORTANCE_HIGH
//构建通知渠道
val notificationChannel: NotificationChannel = NotificationChannel(notificationChannelId,
channelName, importance)
notificationChannel.description = "Channel description"
//LED灯
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.RED
notificationChannel.vibrationPattern = longArrayOf(0,1000,500,1000)
notificationChannel.enableVibration(true)
//向系统注册通知渠道,注册后不能改变重要性以及其他通知行为
notificationManager.createNotificationChannel(notificationChannel)
* 创建服务通知
private fun createForegroundNotification(): Notification {
val builder: NotificationCompat.Builder = NotificationCompat.Builder(applicationContext, notificationChannelId)
//通知小图标
builder.setSmallIcon(R.mipmap.ic_launcher_round)
//通知标题
builder.setContentTitle("苏宁窖藏")
//通知内容
builder.setContentText("苏宁是国内优秀的跨国企业?")
//设置通知显示的时间
builder.setWhen(System.currentTimeMillis())
//设定启动的内容
val activityIntent: Intent = Intent(this, MainActivity::class.java)
activityIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent: PendingIntent = PendingIntent.getActivity(this,
1,activityIntent, PendingIntent.FLAG_UPDATE_CURRENT)
builder.setContentIntent(pendingIntent)
builder.priority = NotificationCompat.PRIORITY_DEFAULT
//设置为进行中的通知
builder.setOngoing(true)
//创建通知并返回
return builder.build()
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy")
stopForeground(true)
ForegroundService.serviceIsLive = false;
- Android8.0及以上通知需要添加通知渠道,否则无法显示;
- Android9.0前台服务通知需要添加<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>权限;
- Android 8.0使用startForegroundService在前台启动新服务;
Android8.0后台执行限制
为提高设备性能,系统会限制未在前台运行的应用的某些行为。具体而言:
- 在后台运行的应用对后台服务的访问受到限制
- 应用无法使用其清单注册大部分隐式广播
默认情况下,这些限制仅适用于针对O的应用。不过用户可以从Settings屏幕为任意应用启用这些限制,即使应用并不是以O为目标平台。
Android8.0还对特定函数做出了如下变更:
- 如果针对Android8.0的应用尝试在不允许创建其后台服务的情况下使用startService()函数,则该函数将引发一个IllegalStateException.
- Context.startForegroundService()函数将启动一个前台服务。即使应用在后台运行,系统也允许其调用Context.startForegroundService().不过,应用必须在创建服务后的5秒内调用改服务的startForegroun()函数,否则将报ANR(Application Not Responding)错误。
Android通知栏前台服务 - 几圈年轮 - 博客园
Android8.0使用通知创建前台服务_Haienzi的博客-CSDN博客_android 创建前台服务
Foreground services | Android Developers
1.服务是什么(Service)Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可通过绑定到服务与之进行交互,甚至是执行进程间通信 (IPC)。例如,服务可在后台处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序进行交互。2.前台服务(ForegroundService)是什么?前台服务执行一些用户能注意到的操作。例如,音频应用会使用前台服务来播放音频曲目。前台服务必须显示通知
代码可以直接运行,实现了android平台服务的前台化,并以Notification显示到右下脚。代码可以在任何版本API运行。考虑了各种版本的API情况。内部使用了发射机制。
简略说下服务前台化的好处:即提高了服务的优先级别,普通服务是默认后台运行的。当android系统发现内存不够时,极易自动killed掉你的服务。如果,改用前台则不易被killed,当然,内存极度低时同样会killed。
本代码来源于对android的apidemos的研究。
本文档主要讲解锁屏的启动流程,锁屏的灭屏上锁,锁屏的亮屏解锁逻辑。
此文档适合SystemUI的初学者,能让SystemUI初学者立刻马上接手SystemUI锁屏模块。
有助于SytemUI锁屏的开发。
SystemUI锁屏初学者
SytemUI锁屏模块的开发与应用。
IntentService具有以下特点:
(1) IntentService自带一个工作线程,当我们的Service需要做一些可能会阻塞主线程的工作的时候可以考虑使用IntentService。
(2) 我们需要将要做的实际工作放入到IntentService的onHandleIntent回到方法中,当我们通过startService(intent)启动了Int...
Android前台Service 是指一个能够在Notification栏中显示通知的Service。通过前台Service,在后台运行时,用户可以看到一个通知,以此提示用户该服务正在运行。前台Service在Android系统中用于一些比较重要的服务,比如音乐播放器、即时通讯、闹钟、导航等等。在应用程序需要长时间后台运行时,可使用前台Service。
在使用前台Service时,需要在Service中创建并设置Notification通知。其中,Notification通知是用户与Service进行交互的唯一方式,当通知被点击时,可以通过Intent来启动或停止Service。
对于一些比较耗电的服务,如GPS定位、音乐播放器等,使用前台Service可以避免在后台运行时被系统杀死,从而保证服务持续稳定运行,提高用户体验。
但是需要注意,虽然前台Service可以提高进程的优先级,但是在使用时需注意不要过度使用,因为长时间占用内存、耗电量过大,也会对用户造成不良影响。因此,在使用前台Service时,需权衡其重要性和对系统资源的影响,以达到合理使用的目的。