「一文搞懂 Android Service从入门到实战」前言什么是 ServiceService 是 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 基本实现classMyStartedService:Service(){companionobject{constvalACTION_STARTcom.example.service.ACTION_STARTconstvalACTION_STOPcom.example.service.ACTION_STOPfunstartService(context:Context){valintentIntent(context,MyStartedService::class.java).apply{actionACTION_START}// Android 8.0 需要使用 startForegroundServiceif(Build.VERSION.SDK_INTBuild.VERSION_CODES.O){context.startForegroundService(intent)}else{context.startService(intent)}}funstopService(context:Context){valintentIntent(context,MyStartedService::class.java)context.stopService(intent)}}overridefunonCreate(){super.onCreate()Log.d(MyService,onCreate: 服务创建)}overridefunonStartCommand(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: 会重新传递之前的 IntentreturnSTART_STICKY}overridefunonBind(intent:Intent?):IBinder?{returnnull// Started Service 不需要绑定}overridefunonDestroy(){super.onDestroy()Log.d(MyService,onDestroy: 服务销毁)}}2.2 启动和停止服务// 启动服务MyStartedService.startService(this)// 停止服务MyStartedService.stopService(this)// 在 Service 内部自己停止stopSelf()2.3 onStartCommand 返回值详解返回值行为START_STICKY服务被杀死后自动重启但 Intent 为 nullSTART_NOT_STICKY服务被杀死后不会自动重启START_REDELIVER_INTENT服务被杀死后会重新传递之前的 Intent三、Bound Service绑定式服务3.1 基本实现classMyBoundService:Service(){// Binder 对象用于返回服务实例privatevalbinderLocalBinder()innerclassLocalBinder:Binder(){fungetService():MyBoundServicethisMyBoundService}overridefunonBind(intent:Intent?):IBinder{Log.d(MyBoundService,onBind: )returnbinder}// 服务提供的方法fungetData():String服务返回的数据funexecuteTask(taskName:String):String{return任务 [$taskName] 执行完成}}3.2 绑定和解绑classMyActivity:AppCompatActivity(){privatevarmyService:MyBoundService?nullprivatevarisBoundfalseprivatevalserviceConnectionobject:ServiceConnection{overridefunonServiceConnected(name:ComponentName?,service:IBinder?){valbinderserviceasMyBoundService.LocalBinder myServicebinder.getService()isBoundtrueLog.d(MyActivity,服务已连接)}overridefunonServiceDisconnected(name:ComponentName?){myServicenullisBoundfalseLog.d(MyActivity,服务已断开)}}overridefunonStart(){super.onStart()// 绑定服务Intent(this,MyBoundService::class.java).also{intent-bindService(intent,serviceConnection,Context.BIND_AUTO_CREATE)}}overridefunonStop(){super.onStop()// 解绑服务if(isBound){unbindService(serviceConnection)isBoundfalse}}funonCallServiceMethod(){if(isBoundmyService!null){valresultmyService!!.executeTask(测试任务)Log.d(MyActivity,result)}}}3.3 ServiceConnection 回调回调触发时机onServiceConnected服务成功绑定时调用onServiceDisconnected服务意外断开连接时调用如被系统杀死四、Foreground Service前台服务4.1 基本实现classMyForegroundService:Service(){companionobject{constvalCHANNEL_IDforeground_service_channelconstvalNOTIFICATION_ID1funstartService(context:Context){valintentIntent(context,MyForegroundService::class.java)if(Build.VERSION.SDK_INTBuild.VERSION_CODES.O){context.startForegroundService(intent)}else{context.startService(intent)}}funstopService(context:Context){context.stopService(Intent(context,MyForegroundService::class.java))}}overridefunonCreate(){super.onCreate()createNotificationChannel()}overridefunonStartCommand(intent:Intent?,flags:Int,startId:Int):Int{// 启动前台服务必须startForeground(NOTIFICATION_ID,createNotification(服务运行中...))// 开始后台任务startBackgroundTask()returnSTART_STICKY}overridefunonBind(intent:Intent?):IBinder?nulloverridefunonDestroy(){super.onDestroy()stopForeground(STOP_FOREGROUND_REMOVE)}privatefuncreateNotificationChannel(){if(Build.VERSION.SDK_INTBuild.VERSION_CODES.O){valchannelNotificationChannel(CHANNEL_ID,前台服务通知,NotificationManager.IMPORTANCE_LOW).apply{description前台服务通知}valnotificationManagergetSystemService(NotificationManager::class.java)notificationManager.createNotificationChannel(channel)}}privatefuncreateNotification(content:String):Notification{// 创建通知...returnNotificationCompat.Builder(this,CHANNEL_ID).setContentTitle(前台服务).setContentText(content).setSmallIcon(R.drawable.ic_notification).setOngoing(true).build()}}4.2 前台服务通知构建privatefuncreateNotification(content:String,isPlaying:Boolean):Notification{valintentIntent(this,MainActivity::class.java)valpendingIntentPendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENTorPendingIntent.FLAG_IMMUTABLE)valstopIntentIntent(this,MyForegroundService::class.java).apply{actionACTION_STOP}valstopPendingIntentPendingIntent.getService(this,1,stopIntent,PendingIntent.FLAG_UPDATE_CURRENTorPendingIntent.FLAG_IMMUTABLE)returnNotificationCompat.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() │ │ │ └─────────────────────────────────────────────────────────────┘六、IntentService6.1 已废弃的 IntentService// IntentService 已在 Android 11 (API 30) 废弃// 推荐使用 Kotlin 协程 WorkManager// 旧的 IntentService 写法仅供参考Deprecated(Use WorkManager or Kotlin Coroutines instead)classMyIntentService:IntentService(MyIntentService){overridefunonHandleIntent(intent:Intent?){// 在子线程执行后台任务Log.d(MyIntentService,处理任务:${intent?.action})}}6.2 现代替代方案// 使用 Kotlin 协程的替代方案classMyCoroutineService:Service(){privatevalscopeCoroutineScope(Dispatchers.DefaultSupervisorJob())overridefunonStartCommand(intent:Intent?,flags:Int,startId:Int):Int{intent?.action?.let{action-scope.launch{// 在 Default 线程池执行processTask(action)}}returnSTART_NOT_STICKY}privatesuspendfunprocessTask(action:String){// 协程中执行后台任务delay(1000)Log.d(MyCoroutineService,任务完成:$action)}overridefunonBind(intent:Intent?):IBinder?nulloverridefunonDestroy(){super.onDestroy()scope.cancel()}}// 或者使用 WorkManager推荐用于后台任务classMyWorker(context:Context,params:WorkerParameters):CoroutineWorker(context,params){overridesuspendfundoWork():Result{// 在后台线程执行Log.d(MyWorker,执行工作...)returnResult.success()}}七、注意事项与最佳实践7.1 内存泄漏防护classMyBoundService:Service(){privatevalbinderLocalBinder()// 使用 WeakReference 保存 Activity 引用privatevaractivityRef:WeakReferenceActivity?nullfunsetActivity(activity:Activity){activityRefWeakReference(activity)}innerclassLocalBinder:Binder(){fungetService():MyBoundServicethisMyBoundService}}7.2 前台服务权限!-- Android 9 (API 28) 需要声明权限 --uses-permissionandroid:nameandroid.permission.FOREGROUND_SERVICE/!-- Android 14 (API 34) 需要声明具体类型 --uses-permissionandroid:nameandroid.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: BroadcastReceiverclassMyService:Service(){privatevalreceiverobject:BroadcastReceiver(){overridefunonReceive(context:Context?,intent:Intent?){when(intent?.action){ACTION_UPDATE-{valprogressintent.getIntExtra(progress,0)// 更新 UI}}}}overridefunonCreate(){super.onCreate()registerReceiver(receiver,IntentFilter(ACTION_UPDATE))}overridefunonDestroy(){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 │ │ │ └────────────────────────────────────────────────────────────┘