Skip to content

后台任务

源:Android Foreground Service | iOS Background Modes

后台任务用于执行长时间运行的操作,如音乐播放、导航、下载等。本文展示如何跨平台实现后台任务。

平台差异对比

平台原生 API限制权限要求
AndroidForeground Service必须显示通知FOREGROUND_SERVICE
iOSBackground 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>