在 Android 四大组件(Activity、Service、BroadcastReceiver、ContentProvider)中,Service 是负责后台执行长时间运行操作的核心组件。它没有可视化界面,却支撑着音乐播放、文件下载、数据同步等核心场景的实现。
一、初识 Service
Service 是 Android 中用于在后台执行耗时操作的组件,它运行在应用进程的主线程(UI 线程)中,并非独立的后台线程。
核心特点有:
- 无界面:无法直接与用户交互,需通过广播、Binder、EventBus 等方式与其他组件通信;
- 主线程运行:所有生命周期方法(onCreate、onStartCommand 等)均在主线程执行,耗时操作必须手动开子线程;
- 后台存活:即使启动 Service 的 Activity 销毁,Service 仍可继续运行(取决于启动方式);
- 需注册:必须在
AndroidManifest.xml中注册(四大组件唯一例外是 BroadcastReceiver 可动态注册)。
二、Service 基础使用
Service 有两种核心启动方式:startService(启动式)和 bindService(绑定式),两者的使用场景和生命周期完全不同。
1. 创建基础 Service
先定义一个自定义 Service,重写核心生命周期方法:
Kotlin
class MyService : Service() {
// Binder对象,用于绑定式Service与客户端通信
private val binder = LocalBinder()
inner class LocalBinder : Binder() {
fun getService(): MyService = this@MyService
}
// 生命周期方法:Service创建时调用(仅一次)
override fun onCreate() {
super.onCreate()
Log.d("MyService", "onCreate 执行,线程:${Thread.currentThread().name}")
// 注意:此处是主线程,耗时操作需开子线程
Thread {
// 模拟耗时操作(如下载、数据处理)
Thread.sleep(5000)
Log.d("MyService", "耗时操作执行完成")
}.start()
}
// 启动式Service核心方法:每次调用startService都会执行
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d("MyService", "onStartCommand 执行,startId:$startId")
// 返回值决定Service被系统杀死后的重启策略:
// START_STICKY:被杀后重启,intent为null
// START_NOT_STICKY:被杀后不重启
// START_REDELIVER_INTENT:被杀后重启,重新传递最后一个intent
return START_STICKY
}
// 绑定式Service核心方法:首次bindService时执行
override fun onBind(intent: Intent): IBinder {
Log.d("MyService", "onBind 执行")
return binder
}
// 解绑时执行(所有绑定都解绑后触发)
override fun onUnbind(intent: Intent?): Boolean {
Log.d("MyService", "onUnbind 执行")
return super.onUnbind(intent)
}
// Service销毁时执行:释放资源的核心位置
override fun onDestroy() {
super.onDestroy()
Log.d("MyService", "onDestroy 执行")
}
}
2. 注册Service
在 AndroidManifest.xml 中注册:
XML
<manifest ...>
<application ...>
<!-- 注册Service -->
<service
android:name=".MyService"
android:exported="false" /> <!-- exported=false:仅本应用可用 -->
</application>
</manifest>
3. startService(启动式)
核心特点
- 与调用者(如 Activity)解耦,调用者销毁后 Service 仍运行;
- 多次调用
startService只会重复执行onStartCommand,不会重复创建; - 必须手动停止 Service,否则会一直运行。
Kotlin
// Activity中启动Service
val startIntent = Intent(this, MyService::class.java)
startService(startIntent) // Android 8.0+ 后台启动需用startForegroundService
// 停止Service(两种方式)
// 方式1:外部调用stopService
val stopIntent = Intent(this, MyService::class.java)
stopService(stopIntent)
// 方式2:Service内部调用stopSelf(推荐,可指定startId停止)
stopSelf() // 停止当前Service
stopSelf(startId) // 停止指定startId的Service(多任务场景)
4. bindService(绑定式)
核心特点
- 与调用者绑定,调用者(如 Activity)销毁后,Service 会自动解绑;
- 支持调用者与 Service 双向通信(通过 Binder);
- 多次绑定同一 Service 只会执行一次
onBind。
Kotlin
class MainActivity : AppCompatActivity() {
private var myService: MyService? = null
private var isBound = false
// ServiceConnection:绑定回调(核心)
private val serviceConnection = object : ServiceConnection {
// 绑定成功时回调(运行在主线程!)
override fun onServiceConnected(className: ComponentName, service: IBinder) {
Log.d("MainActivity", "onServiceConnected 线程:${Thread.currentThread().name}")
val binder = service as MyService.LocalBinder
myService = binder.getService()
isBound = true
// 调用Service的方法(通信示例)
myService?.let {
Log.d("MainActivity", "已绑定Service,可调用其方法")
}
}
// 绑定意外断开时回调(正常解绑不会触发)
override fun onServiceDisconnected(className: ComponentName) {
Log.d("MainActivity", "onServiceDisconnected 执行")
isBound = false
}
}
// 绑定Service
fun bindService(view: View) {
val bindIntent = Intent(this, MyService::class.java)
bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE)
// BIND_AUTO_CREATE:绑定后自动创建Service(无需先start)
}
// 解绑Service(必须在Activity销毁前执行,否则内存泄漏)
fun unbindService(view: View) {
if (isBound) {
unbindService(serviceConnection)
isBound = false
}
}
override fun onDestroy() {
super.onDestroy()
// 页面销毁时确保解绑
if (isBound) {
unbindService(serviceConnection)
isBound = false
}
}
}
两种方式主要有以下的区别:
| 维度 | startService | bindService |
|---|---|---|
| 关联关系 | 与调用者解耦 | 与调用者绑定 |
| 通信能力 | 仅单向(调用者→Service) | 双向(调用者↔Service) |
| 生命周期 | onCreate→onStartCommand→onDestroy | onCreate→onBind→onUnbind→onDestroy |
| 停止方式 | stopService/stopSelf | unbindService(所有绑定解绑后) |
| 适用场景 | 无交互的后台任务(如下载) | 需交互的后台任务(如音乐播放控制) |
三、 Service 生命周期
官方图:

onCreate:Service 首次创建时执行,无论启动多少次,仅执行一次;onStartCommand:每次调用startService都会执行;onBind:首次调用bindService时执行,多次绑定仅执行一次;onDestroy:Service 销毁时执行,需在此释放资源(如关闭线程、取消广播监听);
所有的生命周期方法都运行在主线程中。
四、主流Service保活方案
Android 系统会根据进程优先级 回收内存,Service 所在进程默认是「服务进程」(优先级第 3),容易被杀死。进程保活的核心思路是:提升进程优先级 + 被杀后重启。
Android 进程优先级(从高到低):
前台进程(Foreground):用户正在交互的 Activity / 前台 Service;
可见进程(Visible):用户可见但不交互的组件(如悬浮窗);
服务进程(Service):运行后台 Service 的进程;
后台进程(Background):用户退出的 Activity 进程;
空进程(Empty):无活跃组件的进程。
1. 前台Service(官方推荐)
将 Service 提升为前台进程,系统几乎不会杀死。需显示一个前台通知。
Kotlin
override fun onCreate() {
super.onCreate()
// 构建前台通知
val notification = NotificationCompat.Builder(this, "service_channel")
.setContentTitle("前台服务运行中")
.setContentText("正在执行后台任务")
.setSmallIcon(R.mipmap.ic_launcher)
.build()
// 启动前台Service(id不能为0)
startForeground(1, notification)
}
2. 使用 onStartCommand 返回值
onStartCommand 返回的重启策略,当系统因内存不足杀死 Service 所在进程后,AMS 会检查该 Service 的「重启策略」,决定是否重建 Service、重建时是否传递原 Intent:
Kotlin
override fun onStartCommand(...): Int {
return START_STICKY
}
Service被杀后重建,但不能防杀
3. WorkManager
利用系统调度任务,定期检查 Service 是否存活,若被杀则重启:
Kotlin
WorkManager.getInstance(context)
.enqueue(OneTimeWorkRequest.from(MyWorker::class.java))
4. 双进程守护
两个进程的 Service 互相监听,一个被杀后另一个重启对方。核心是利用 Service 的 onDestroy 或广播监听进程状态。
Service保活的核心是提高进程优先级,最可靠的方式是前台Service,通过 startForeground 提升优先级。能交给系统调度的,就交给 WorkManager ;真正需要长期、实时运行的任务,才使用前台 Service,并明确告知用户其存在和价值。