A Started Service runs in the background indefinitely, even if the activity that started it is destroyed.
class DownloadService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val url = intent?.getStringExtra("URL") ?: return START_NOT_STICKY
thread {
downloadFile(url)
stopSelf()
}
return START_STICKY // Restart if killed
}
private fun downloadFile(url: String) {
// Download logic
sendBroadcast(Intent("DOWNLOAD_COMPLETE"))
}
override fun onBind(intent: Intent?): IBinder? = null
}
// Start service
startService(Intent(this, DownloadService::class.java).apply {
putExtra("URL", "https://example.com/file.zip")
})
class MusicService : Service() {
private val binder = LocalBinder()
private var mediaPlayer: MediaPlayer? = null
inner class LocalBinder : Binder() {
fun getService(): MusicService = this@MusicService
}
override fun onBind(intent: Intent?): IBinder = binder
fun playMusic(song: Int) {
mediaPlayer = MediaPlayer.create(this, song)
mediaPlayer?.start()
}
fun stopMusic() {
mediaPlayer?.stop()
mediaPlayer?.release()
mediaPlayer = null
}
}
// Activity binding
class MainActivity : AppCompatActivity() {
private var musicService: MusicService? = null
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
musicService = (service as MusicService.LocalBinder).getService()
}
override fun onServiceDisconnected(name: ComponentName?) {
musicService = null
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
bindService(Intent(this, MusicService::class.java), connection, Context.BIND_AUTO_CREATE)
}
}
class ForegroundLocationService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification = NotificationCompat.Builder(this, "location")
.setContentTitle("Location Tracking")
.setContentText("Tracking your location in background")
.setSmallIcon(R.drawable.ic_location)
.setOngoing(true)
.build()
startForeground(1002, notification)
// Start location updates
return START_STICKY
}
}
// AndroidManifest.xml
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<service android:name=".ForegroundLocationService"
android:foregroundServiceType="location" />
WorkManager is the recommended solution for deferrable background work that needs guaranteed execution.
// Define worker
class SyncWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
override fun doWork(): Result {
return try {
// Sync data to server
syncData()
Result.success()
} catch (e: Exception) {
Result.retry()
}
}
}
// Schedule one-time work
val syncRequest = OneTimeWorkRequestBuilder<SyncWorker>()
.setConstraints(Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build())
.setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS)
.build()
WorkManager.getInstance(this).enqueue(syncRequest)
// Observe work status
WorkManager.getInstance(this).getWorkInfoByIdLiveData(syncRequest.id)
.observe(this) { info ->
when (info?.state) {
WorkInfo.State.SUCCEEDED -> println("Sync successful")
WorkInfo.State.FAILED -> println("Sync failed")
}
}
// Periodic work
val periodicSync = PeriodicWorkRequestBuilder<SyncWorker>(15, TimeUnit.MINUTES)
.build()
WorkManager.getInstance(this).enqueue(periodicSync)
val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
val job = JobInfo.Builder(123, ComponentName(this, MyJobService::class.java))
.setMinimumLatency(1000) // 1 second delay
.setOverrideDeadline(5000) // Must run within 5 seconds
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setRequiresCharging(false)
.build()
jobScheduler.schedule(job)