「一文搞懂 Android Service:从入门到实战」 前言:什么是 Service? Service 是 Android 四大组件之一,用于在后台执行长时间运行的操作。与 Thread 的区别是:Service 运行在主线程,但可以在后台执行任务,且生命周期受系统管理。
┌─────────────────────────────────────────────────────────────┐ │ Android 组件对比 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ Activity 界面组件,用户可感知 │ │ Service 后台组件,用户通常不直接感知 │ │ BroadcastReceiver 广播组件,响应系统/应用广播 │ │ ContentProvider 数据组件,提供数据共享接口 │ │ │ │ Service 与 Thread 的区别: │ │ ├── Service 生命周期受系统管理 │ │ ├── Service 可以在应用切换到后台时继续运行 │ │ ├── Service 可以绑定到多个组件 │ │ └── Thread 生命周期与创建它的组件无关 │ │ │ └─────────────────────────────────────────────────────────────┘一、Service 三种类型 1.1 类型概览 ┌─────────────────────────────────────────────────────────────┐ │ Service 三种类型 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ Started Service(启动式服务) │ │ ├── 通过 startService() 启动 │ │ ├── 独立运行,不与调用者绑定 │ │ ├── 需要手动停止(stopSelf/stopService) │ │ └── 生命周期:onCreate → onStartCommand → onDestroy │ │ │ │ Bound Service(绑定式服务) │ │ ├── 通过 bindService() 绑定 │ │ ├── 与调用者生命周期绑定 │ │ ├── 所有客户端解绑后自动销毁 │ │ └── 生命周期:onCreate → onBind → onUnbind → onDestroy │ │ │ │ Foreground Service(前台服务) │ │ ├── 必须调用 startForeground() │ │ ├── 显示持续通知,用户可见 │ │ ├── 用户主动停止才会销毁 │ │ └── 适用:音乐播放、导航、下载等 │ │ │ └─────────────────────────────────────────────────────────────┘二、Started Service(启动式服务) 2.1 基本实现 class MyStartedService: Service ( ) { companion object { const val ACTION_START= "com.example.service.ACTION_START" const val ACTION_STOP= "com.example.service.ACTION_STOP" fun startService ( context: Context) { val intent= Intent ( context, MyStartedService:: class . java) . apply { action= ACTION_START} // Android 8.0+ 需要使用 startForegroundService if ( Build. VERSION. SDK_INT>= Build. VERSION_CODES. O) { context. startForegroundService ( intent) } else { context. startService ( intent) } } fun stopService ( context: Context) { val intent= Intent ( context, MyStartedService:: class . java) context. stopService ( intent) } } override fun onCreate ( ) { super . onCreate ( ) Log. d ( "MyService" , "onCreate: 服务创建" ) } override fun onStartCommand ( intent: Intent? , flags: Int, startId: Int) : Int{ Log. d ( "MyService" , "onStartCommand: startId= $ startId " ) when ( intent? . action) { ACTION_START-> { // 执行后台任务 startBackgroundTask ( ) } ACTION_STOP-> { stopSelf ( ) } } // 返回值说明: // START_STICKY: 服务被杀死后会自动重启(不带 Intent) // START_NOT_STICKY: 服务被杀死后不会自动重启 // START_REDELIVER_INTENT: 会重新传递之前的 Intent return START_STICKY} override fun onBind ( intent: Intent? ) : IBinder? { return null // Started Service 不需要绑定 } override fun onDestroy ( ) { super . onDestroy ( ) Log. d ( "MyService" , "onDestroy: 服务销毁" ) } } 2.2 启动和停止服务 // 启动服务 MyStartedService. startService ( this ) // 停止服务 MyStartedService. stopService ( this ) // 在 Service 内部自己停止 stopSelf ( ) 2.3 onStartCommand 返回值详解 返回值 行为 START_STICKY服务被杀死后自动重启,但 Intent 为 null START_NOT_STICKY服务被杀死后不会自动重启 START_REDELIVER_INTENT服务被杀死后会重新传递之前的 Intent
三、Bound Service(绑定式服务) 3.1 基本实现 class MyBoundService: Service ( ) { // Binder 对象,用于返回服务实例 private val binder= LocalBinder ( ) inner class LocalBinder: Binder ( ) { fun getService ( ) : MyBoundService= this @MyBoundService } override fun onBind ( intent: Intent? ) : IBinder{ Log. d ( "MyBoundService" , "onBind: " ) return binder} // 服务提供的方法 fun getData ( ) : String= "服务返回的数据" fun executeTask ( taskName: String) : String{ return "任务 [ $ taskName ] 执行完成" } } 3.2 绑定和解绑 class MyActivity: AppCompatActivity ( ) { private var myService: MyBoundService? = null private var isBound= false private val serviceConnection= object : ServiceConnection{ override fun onServiceConnected ( name: ComponentName? , service: IBinder? ) { val binder= serviceas MyBoundService. LocalBinder myService= binder. getService ( ) isBound= true Log. d ( "MyActivity" , "服务已连接" ) } override fun onServiceDisconnected ( name: ComponentName? ) { myService= null isBound= false Log. d ( "MyActivity" , "服务已断开" ) } } override fun onStart ( ) { super . onStart ( ) // 绑定服务 Intent ( this , MyBoundService:: class . java) . also { intent-> bindService ( intent, serviceConnection, Context. BIND_AUTO_CREATE) } } override fun onStop ( ) { super . onStop ( ) // 解绑服务 if ( isBound) { unbindService ( serviceConnection) isBound= false } } fun onCallServiceMethod ( ) { if ( isBound&& myService!= null ) { val result= myService!! . executeTask ( "测试任务" ) Log. d ( "MyActivity" , result) } } } 3.3 ServiceConnection 回调 回调 触发时机 onServiceConnected服务成功绑定时调用 onServiceDisconnected服务意外断开连接时调用(如被系统杀死)
四、Foreground Service(前台服务) 4.1 基本实现 class MyForegroundService: Service ( ) { companion object { const val CHANNEL_ID= "foreground_service_channel" const val NOTIFICATION_ID= 1 fun startService ( context: Context) { val intent= Intent ( context, MyForegroundService:: class . java) if ( Build. VERSION. SDK_INT>= Build. VERSION_CODES. O) { context. startForegroundService ( intent) } else { context. startService ( intent) } } fun stopService ( context: Context) { context. stopService ( Intent ( context, MyForegroundService:: class . java) ) } } override fun onCreate ( ) { super . onCreate ( ) createNotificationChannel ( ) } override fun onStartCommand ( intent: Intent? , flags: Int, startId: Int) : Int{ // 启动前台服务(必须) startForeground ( NOTIFICATION_ID, createNotification ( "服务运行中..." ) ) // 开始后台任务 startBackgroundTask ( ) return START_STICKY} override fun onBind ( intent: Intent? ) : IBinder? = null override fun onDestroy ( ) { super . onDestroy ( ) stopForeground ( STOP_FOREGROUND_REMOVE) } private fun createNotificationChannel ( ) { if ( Build. VERSION. SDK_INT>= Build. VERSION_CODES. O) { val channel= NotificationChannel ( CHANNEL_ID, "前台服务通知" , NotificationManager. IMPORTANCE_LOW) . apply { description= "前台服务通知" } val notificationManager= getSystemService ( NotificationManager:: class . java) notificationManager. createNotificationChannel ( channel) } } private fun createNotification ( content: String) : Notification{ // 创建通知... return NotificationCompat. Builder ( this , CHANNEL_ID) . setContentTitle ( "前台服务" ) . setContentText ( content) . setSmallIcon ( R. drawable. ic_notification) . setOngoing ( true ) . build ( ) } } 4.2 前台服务通知构建 private fun createNotification ( content: String, isPlaying: Boolean) : Notification{ val intent= Intent ( this , MainActivity:: class . java) val pendingIntent= PendingIntent. getActivity ( this , 0 , intent, PendingIntent. FLAG_UPDATE_CURRENTor PendingIntent. FLAG_IMMUTABLE) val stopIntent= Intent ( this , MyForegroundService:: class . java) . apply { action= ACTION_STOP} val stopPendingIntent= PendingIntent. getService ( this , 1 , stopIntent, PendingIntent. FLAG_UPDATE_CURRENTor PendingIntent. FLAG_IMMUTABLE) return NotificationCompat. Builder ( this , CHANNEL_ID) . setContentTitle ( "🎵 音乐播放" ) . setContentText ( content) . setSmallIcon ( R. drawable. ic_notification) . setContentIntent ( pendingIntent) . addAction ( R. drawable. ic_stop, "停止" , stopPendingIntent) . setOngoing ( true ) . setSilent ( true ) . build ( ) } 五、Service 生命周期 5.1 生命周期图 ┌─────────────────────────────────────────────────────────────┐ │ Started Service 生命周期 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ startService() ──▶ onCreate() ──▶ onStartCommand() │ │ │ │ │ ▼ │ │ 服务运行中... │ │ │ │ │ ▼ │ │ stopSelf() / stopService() │ │ │ │ │ ▼ │ │ onDestroy() │ │ │ └─────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ Bound Service 生命周期 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ bindService() ──▶ onCreate() ──▶ onBind() │ │ │ │ │ ▼ │ │ 服务运行中... │ │ │ │ │ 所有客户端 unbindService() │ │ │ │ │ ▼ │ │ onUnbind() │ │ │ │ │ ▼ │ │ onDestroy() │ │ │ └─────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ Foreground Service 生命周期 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ startForegroundService() ──▶ onCreate() ──▶ onStartCommand│ │ │ │ │ ▼ │ │ startForeground() │ │ │ │ │ ▼ │ │ 服务持续运行... │ │ (用户可见通知) │ │ │ │ │ ▼ │ │ stopForeground() + stopSelf() │ │ │ │ │ ▼ │ │ onDestroy() │ │ │ └─────────────────────────────────────────────────────────────┘5.2 混合使用:Started + Bound ┌─────────────────────────────────────────────────────────────┐ │ 同时使用两种绑定方式 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ startService() ──▶ onCreate() ──▶ onStartCommand() │ │ │ │ │ │ │ │ │ │ │ bindService() ──▶ onBind() │ │ │ │ │ │ │ ▼ │ │ │ 服务运行中... │ │ │ │ │ │ │ unbindService() ──▶ onUnbind() │ │ │ │ │ │ └────── stopSelf() / stopService() │ │ │ │ │ │ │ ▼ │ │ └──────────────────────────▶ onDestroy() │ │ │ └─────────────────────────────────────────────────────────────┘六、IntentService 6.1 已废弃的 IntentService // IntentService 已在 Android 11 (API 30) 废弃 // 推荐使用 Kotlin 协程 + WorkManager // 旧的 IntentService 写法(仅供参考) @Deprecated ( "Use WorkManager or Kotlin Coroutines instead" ) class MyIntentService: IntentService ( "MyIntentService" ) { override fun onHandleIntent ( intent: Intent? ) { // 在子线程执行后台任务 Log. d ( "MyIntentService" , "处理任务: ${ intent? . action } " ) } } 6.2 现代替代方案 // 使用 Kotlin 协程的替代方案 class MyCoroutineService: Service ( ) { private val scope= CoroutineScope ( Dispatchers. Default+ SupervisorJob ( ) ) override fun onStartCommand ( intent: Intent? , flags: Int, startId: Int) : Int{ intent? . action? . let { action-> scope. launch { // 在 Default 线程池执行 processTask ( action) } } return START_NOT_STICKY} private suspend fun processTask ( action: String) { // 协程中执行后台任务 delay ( 1000 ) Log. d ( "MyCoroutineService" , "任务完成: $ action " ) } override fun onBind ( intent: Intent? ) : IBinder? = null override fun onDestroy ( ) { super . onDestroy ( ) scope. cancel ( ) } } // 或者使用 WorkManager(推荐用于后台任务) class MyWorker ( context: Context, params: WorkerParameters) : CoroutineWorker ( context, params) { override suspend fun doWork ( ) : Result{ // 在后台线程执行 Log. d ( "MyWorker" , "执行工作..." ) return Result. success ( ) } } 七、注意事项与最佳实践 7.1 内存泄漏防护 class MyBoundService: Service ( ) { private val binder= LocalBinder ( ) // 使用 WeakReference 保存 Activity 引用 private var activityRef: WeakReference< Activity> ? = null fun setActivity ( activity: Activity) { activityRef= WeakReference ( activity) } inner class LocalBinder: Binder ( ) { fun getService ( ) : MyBoundService= this @MyBoundService } } 7.2 前台服务权限 <!-- Android 9 (API 28) 需要声明权限 --> < uses-permissionandroid: name= " android.permission.FOREGROUND_SERVICE" /> <!-- Android 14 (API 34) 需要声明具体类型 --> < uses-permissionandroid: name= " android.permission.FOREGROUND_SERVICE_SPECIAL_USE" /> 7.3 服务保活 ┌─────────────────────────────────────────────────────────────┐ │ 服务保活注意事项 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ⚠️ Android 6.0+ 后台限制: │ │ ├── 系统会杀死后台运行过久的服务 │ │ ├── 使用前台服务确保重要任务执行 │ │ └── 可以使用 WorkManager 安排延迟任务 │ │ │ │ ⚠️ Android 8.0+ 后台限制: │ │ ├── 不能在后台启动服务(使用 startForegroundService) │ │ └── 必须在 5 秒内调用 startForeground() │ │ │ │ ⚠️ Android 12 (API 31) 限制: │ │ ├── 不能在后台启动前台服务 │ │ └── 需要用户授权 FOREGROUND_SERVICE 权限 │ │ │ │ ✅ 推荐做法: │ │ ├── 优先使用 WorkManager 处理后台任务 │ │ ├── 音乐播放等使用前台服务 + 通知 │ │ └── 考虑使用 Jetpack WorkManager 替代 IntentService │ │ │ └─────────────────────────────────────────────────────────────┘7.4 Service 与 Activity 通信 // 方式 1: Bound Service + Binder // 见 Bound Service 示例 // 方式 2: BroadcastReceiver class MyService: Service ( ) { private val receiver= object : BroadcastReceiver ( ) { override fun onReceive ( context: Context? , intent: Intent? ) { when ( intent? . action) { "ACTION_UPDATE" -> { val progress= intent. getIntExtra ( "progress" , 0 ) // 更新 UI } } } } override fun onCreate ( ) { super . onCreate ( ) registerReceiver ( receiver, IntentFilter ( "ACTION_UPDATE" ) ) } override fun onDestroy ( ) { super . onDestroy ( ) unregisterReceiver ( receiver) } } // 方式 3: LocalBroadcastManager(已废弃,使用 LiveData/Flow) // 推荐使用 LiveData 或 Flow 进行 Service 与 Activity 通信 总结 ┌────────────────────────────────────────────────────────────┐ │ Android Service 全景图 │ ├────────────────────────────────────────────────────────────┤ │ │ │ 三种类型: │ │ ├── Started Service - startService() 独立运行 │ │ ├── Bound Service - bindService() 生命周期绑定 │ │ └── Foreground - startForeground() 用户可见 │ │ │ │ 生命周期回调: │ │ ├── onCreate() 服务创建(只调用一次) │ │ ├── onStartCommand() 处理启动请求(可多次调用) │ │ ├── onBind() 绑定服务 │ │ ├── onUnbind() 解绑服务 │ │ └── onDestroy() 服务销毁 │ │ │ │ 返回值含义: │ │ ├── START_STICKY 被杀死 后自动重启 │ │ ├── START_NOT_STICKY 被杀死 后不重启 │ │ └── START_REDELIVER 被杀死 后重传 Intent │ │ │ │ 现代替代: │ │ ├── IntentService → WorkManager + Coroutines │ │ ├── 后台服务 → Jetpack WorkManager │ │ └── 线程处理 → Kotlin Coroutines │ │ │ │ 注意事项: │ │ ├── 前台服务需要权限和通知渠道 │ │ ├── 注意内存泄漏,使用 WeakReference │ │ ├── Android 8.0+ 后台启动服务限制 │ │ └── 优先使用现代方案(协程/WorkManager) │ │ │ └────────────────────────────────────────────────────────────┘