一、Service 的核心特性
- 无界面:在后台独立运行,不与用户直接交互。
- 生命周期可控:通过
startService()
或bindService()
管理。 - 主线程运行:默认运行在主线程,耗时操作需自行启动子线程。
- 优先级较高:相比普通线程,Service 更不易被系统回收。
二、Service 生命周期
1. 启动服务(Started Service)
- 启动方式:
startService(intent)
- 生命周期方法:
onCreate()
:首次创建时调用。onStartCommand(intent, flags, startId)
:每次通过startService()
启动时调用。onDestroy()
:服务终止时调用。
- 终止方式:
stopSelf()
或stopService(intent)
。
2. 绑定服务(Bound Service)
- 启动方式:
bindService(intent, connection, flags)
- 生命周期方法:
onCreate()
onBind(intent)
:返回IBinder
对象供客户端交互。onUnbind(intent)
:所有客户端解绑时调用。onDestroy()
- 终止方式:当所有客户端解绑后,系统自动销毁。
3. 混合模式
服务可同时被启动和绑定,需处理两种生命周期叠加的情况。
三、Service 类型与实现
1. 普通 Service
示例代码:
kotlin
class MyService : Service() {
override fun onBind(intent: Intent): IBinder? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// 执行后台任务(需自行启动线程)
Thread {
// 模拟耗时操作
Thread.sleep(5000)
stopSelf() // 任务完成后停止服务
}.start()
return START_STICKY // 服务被杀死后自动重启
}
}
启动与停止:
kotlin
// 启动服务
val intent = Intent(this, MyService::class.java)
startService(intent)
// 停止服务
stopService(intent)
2. 前台服务(Foreground Service)
- 特点:在状态栏显示持续通知,避免被系统杀死。
- 适配要求:Android 8.0+ 需创建通知渠道。
示例代码:
kotlin
class ForegroundService : Service() {
override fun onBind(intent: Intent): IBinder? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// 创建通知渠道(Android 8.0+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
"foreground_channel",
"前台服务",
NotificationManager.IMPORTANCE_LOW
)
getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
}
// 构建通知
val notification = NotificationCompat.Builder(this, "foreground_channel")
.setContentTitle("前台服务运行中")
.setContentText("正在执行重要任务...")
.setSmallIcon(R.drawable.ic_notification)
.build()
// 启动为前台服务
startForeground(1, notification)
return START_STICKY
}
}
3. 绑定服务(Bound Service)
通过 IBinder
实现与客户端的交互。
示例代码:
kotlin
class BoundService : Service() {
private val binder = LocalBinder()
inner class LocalBinder : Binder() {
fun getService(): BoundService = this@BoundService
}
override fun onBind(intent: Intent): IBinder = binder
fun performTask(data: String) {
// 执行任务
}
}
绑定与解绑:
kotlin
class MainActivity : AppCompatActivity() {
private var boundService: BoundService? = null
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
boundService = (service as BoundService.LocalBinder).getService()
}
override fun onServiceDisconnected(name: ComponentName?) {
boundService = null
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 绑定服务
bindService(
Intent(this, BoundService::class.java),
connection,
Context.BIND_AUTO_CREATE
)
}
override fun onDestroy() {
super.onDestroy()
// 解绑服务
unbindService(connection)
}
}
四、替代方案(旧版 IntentService 的替代)
1. WorkManager
- 用途:处理延迟任务,兼容 Android 4.0+,自动适配后台限制。
- 示例:kotlin
class MyWorker(appContext: Context, params: WorkerParameters) : Worker(appContext, params) { override fun doWork(): Result { // 执行后台任务 return Result.success() } } // 调度任务 val request = OneTimeWorkRequest.Builder(MyWorker::class.java).build() WorkManager.getInstance(context).enqueue(request)
2. JobIntentService(Android 8.0+)
- 用途:替代
IntentService
,兼容旧版本。 - 示例:kotlin
class MyJobIntentService : JobIntentService() { override fun onHandleWork(intent: Intent) { // 执行任务 } companion object { fun enqueueWork(context: Context, intent: Intent) { enqueueWork( context, MyJobIntentService::class.java, 1001, intent ) } } }
五、注意事项
- 主线程阻塞:Service 默认运行在主线程,需手动启动子线程执行耗时操作。
- 后台限制:
- Android 8.0+:限制后台服务,优先使用前台服务或
WorkManager
。 - Android 10+:禁止后台启动 Activity,需用户交互触发。
- Android 8.0+:限制后台服务,优先使用前台服务或
- 服务保活:避免滥用前台服务,尊重用户隐私和系统资源。
- 跨进程通信:通过
Messenger
或AIDL
实现(需声明<service android:process=":remote">
)。
六、完整示例:音乐播放服务
kotlin
class MusicService : Service() {
private val mediaPlayer: MediaPlayer by lazy { MediaPlayer() }
override fun onBind(intent: Intent): IBinder? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
when (intent?.action) {
"PLAY" -> playMusic()
"STOP" -> stopMusic()
}
return START_STICKY
}
private fun playMusic() {
if (!mediaPlayer.isPlaying) {
mediaPlayer.apply {
setDataSource("/sdcard/music.mp3")
prepare()
start()
}
}
}
private fun stopMusic() {
mediaPlayer.stop()
stopSelf()
}
override fun onDestroy() {
mediaPlayer.release()
super.onDestroy()
}
}
启动服务:
kotlin
val intent = Intent(this, MusicService::class.java).apply {
action = "PLAY"
}
startService(intent)
通过合理使用 Service,可实现高效的后台任务管理,但需遵循 Android 平台的最佳实践,确保应用性能和用户体验。