Android

Handling Long running Background Services and Constraints


Introduction of running background services

Understanding Long Running Background Services There are services in Android which run for a long time in the background which are Data Synching, Location Update or Reminders. Challenges: These services tend to consume a lot of battery, can induce loads of CPU and become restricted due to Doze mode and background from Android 8.0 (Oreo) and above.

Why we need

Requirements for handling: It means organizing through alarmmanager or jobscheduler as well as WorkManager in order to have efficient performance without neglecting the limitations of OS.

 Example

Using AlarmManager we enable the scheduling of operations at a certain time or in some interval to perform tasks or to trigger an event at a certain point of time. 

Usage: Set Exact Alarms: Of all services, it is preferred to use AlarmManager.setExact() or setExactAndAllowWhileIdle() for critical activities. 

  class AlarmUtil(private val context: Context) { fun scheduleRepeatingAlarm(requestCode: Int) { // Change minutes here.. val intervalMillis = 2 * 68 * 68 * 1000L // 2 hours in milliseconds // 45 * 60 * 1000L // 45 minutes in milliseconds /* Trigger after app launch */ val triggerAtMillis = System.currentTimeMillis() + 2 * 60 * 1000L alarmManager.setExactAndAllowWhileIdle( AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent ) // Schedule repeating alarms alarmManager.setRepeating( AlarmManager.RTC_WAKEUP, triggerAtMillis, intervalMillis, pendingIntent ) }} 

Repeating Alarms: For time-based tasks, however, these are limited by the operating system for battery optimization for recurrent tasks. Constraints with AlarmManager: From Android 6.0 (Marshmallow release), alarms are suppressed during Doze mode but their delivery is deferred. For the important tasks during the Doze state, use the setAndAllowWhileIdle() and setExactAndAllowWhileIdle()). Android 10+ demands separate permission for exact alarms, especially for all the alarms having the significant impact over the battery. 

 const val NOTIFICATION_CHANNEL_ID = "NOTIFICATION_CHANNEL_ID"class AlarmReceiver : BroadcastReceiver() { companion object { // Add any companion object members if needed } private const val PREFS_NAME = "alarm_prefs" private const val KEY_NOTIFICATION_COUNT = "notification_count" override fun onReceive(context: Context, intent: Intent) { // Increment and store the count val count = incrementNotificationCount(context) // Set current periodic time val currentTime = getCurrentTime() // Increment wake-up count incrementWakeUpCount(context) AlarmUtil(context).startForegroundService(context) }} 

Background service state &  Using AlarmManager for Long-Running Services

 

class BackgroundService : Service() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { // Example usage val count = getWakeUpCount(context = this) Log.d(tag = "WakeUpCount", msg = "App has woken up $count times") // Toast.makeText(this, "WakeUpTime ---> $count", Toast.LENGTH_SHORT).show() bluetoothScanningInteractor.startScanning() intent?.action?.let { action -> log("Using an intent with action $action") when (action) { Actions.START.name -> startService() Actions.STOP.name -> stopService() else -> log("This should never happen. No action in the received intent.") } } ?: log("Received a null intent. It has probably been restarted by the system.") return Service.START_STICKY } private fun incrementWakeUpCount(context: Context) { val sharedPreferences = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE) val currentCount = sharedPreferences.getInt("wake_up_count", 0) sharedPreferences.edit().putInt("wake_up_count", currentCount + 1).apply() }} 

Business Management: The Best Practices and Constraints Management

 

  • Minimizing Battery Impact: Use AlarmManager sparingly and only a highly precise AlarmManager for really important operations. 
  • Depend on standard constraints, for instance, available network or charging state to defer non-emergent procedures.
  • Combining with JobScheduler or WorkManager: Another feature of WorkManager is for example the chaining of tasks and constraint operations. 
  • Turn to the use of JobScheduler from API level 21 in the situations when the execution timing should be more fine-grained with battery and network charging taking into consideration.
  • Testing on Multiple Devices and API Levels: Also guarantee the functionality within devices and API levels since the manufacturers introduce several background restrictions.
  • Unfortunately, this way requires usage of shooting notifications in AlarmManager and background services framework for testing purpose.
  • Resource Utilization Monitoring: There should be creation of policies on battery and CPU usage of background services.
  • Regular Audits: For example, it is advisable to check from time to time what background services are managed in applications to adhere to recommendations.
  • Training and Knowledge Sharing: Organise sessions to explain how AlarmManager works and how to deal with Android background limitations.

Conclusion

Having well defined protocols with regard to potential long lived background services with AlarmManager benefits the development group by more efficient use of resources and longer battery life, resulting in the increased reliability of the applications. Reliability means that background services perform similarly across all Android devices and OS versions and practices are consistent and accompanied by knowledge sharing.

Ready to transform your business with our technology solutions? Contact Us today to Leverage Our Android Expertise.


NodeJS

Related Center Of Excellence