后台任务
源:Android Foreground Service | iOS Background Modes
后台任务用于执行长时间运行的操作,如音乐播放、导航、下载等。本文展示如何跨平台实现后台任务。
平台差异对比
| 平台 | 原生 API | 限制 | 权限要求 |
|---|---|---|---|
| Android | Foreground Service | 必须显示通知 | FOREGROUND_SERVICE |
| iOS | Background Modes | 严格的后台执行限制 | Info.plist 配置 |
| Desktop | - | 无限制 | - |
标准代码块
kotlin
expect object BackgroundTaskManager {
fun startForegroundService(title: String, message: String)
fun stopForegroundService()
}kotlin
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationCompat
actual object BackgroundTaskManager {
fun startForegroundService(context: Context, title: String, message: String) {
val intent = Intent(context, MyForegroundService::class.java).apply {
putExtra("title", title)
putExtra("message", message)
}
context.startForegroundService(intent)
}
actual fun startForegroundService(title: String, message: String) {
// 需要 Context 实现
}
actual fun stopForegroundService() {
// 通过 Service.stopSelf() 实现
}
}
class MyForegroundService : Service() {
companion object {
private const val CHANNEL_ID = "foreground_service_channel"
private const val NOTIFICATION_ID = 1
}
override fun onCreate() {
super.onCreate()
createNotificationChannel()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val title = intent?.getStringExtra("title") ?: "Service"
val message = intent?.getStringExtra("message") ?: "Running..."
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.build()
startForeground(NOTIFICATION_ID, notification)
return START_STICKY
}
private fun createNotificationChannel() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
"Foreground Service",
NotificationManager.IMPORTANCE_LOW
)
val manager = getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(channel)
}
}
override fun onBind(intent: Intent?) = null
}kotlin
actual object BackgroundTaskManager {
actual fun startForegroundService(title: String, message: String) {
// iOS 后台任务需要在 AppDelegate 中配置
}
actual fun stopForegroundService() {
}
}kotlin
actual object BackgroundTaskManager {
actual fun startForegroundService(title: String, message: String) {}
actual fun stopForegroundService() {}
}AndroidManifest.xml 配置
xml
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<application>
<service
android:name=".MyForegroundService"
android:foregroundServiceType="dataSync"
android:exported="false" />
</application>iOS Info.plist 配置
xml
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>location</string>
<string>fetch</string>
</array>