Search code examples
androidserviceforeground-service

Is Foreground Service the only option for running a single method?


I have an app that I have created where I want the app to run a single method when the the time reaches 00:00 (basically the next day).

For context, my app saves a csv file for each day. I've research around on how to make apps run in the background and foreground services was the the one that I found, but I feel like it is too overkill as my app will only run one method, once, each day (the method in question is the one that creates the csv file).

Is foreground services my only option or are there other ways to do this?


Solution

  • For these kind of tasks which runs on specific dates or time or run the task periodically on the bases of date or time. It is recommended to use AlarmManager. Here is the implementation

    Kotlin

    1. Create a Broadcast Receiver class that will trigger the specific logic you want to run on a specific date or time.
    class DailyTaskBroadcastReceiver : BroadcastReceiver() {
     
        override fun onReceive(context: Context, intent: Intent) {
          
            yourTask()
        }
    }
    
    1. In the Application class write a method that triggers the alarm only once and make sure that should not reschedule whenever the app launches.
    class MyApplication: Application() {
    
      override fun onCreate() {
            super.onCreate()
            
            // Initiate your task
            scheduleDailyTask(this)
        }
    
      fun scheduleDailyTask(context: Context) {
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        val intent = Intent(context, DailyTaskBroadcastReceiver::class.java)
        val pendingIntent = PendingIntent.getBroadcast(context, 0, intent,
                PendingIntent.FLAG_NO_CREATE or PendingIntent.FLAG_IMMUTABLE)
    
        // If the alarm is not already set, schedule it
        if (pendingIntent == null) {
            val calendar = Calendar.getInstance().apply {
                timeInMillis = System.currentTimeMillis()
                set(Calendar.HOUR_OF_DAY, 0)
                set(Calendar.MINUTE, 0)
                set(Calendar.SECOND, 0)
                add(Calendar.DAY_OF_YEAR, 1) // Set to the next day
            }
    
            // Set the alarm to trigger at midnight every day
            alarmManager.setRepeating(
                AlarmManager.RTC_WAKEUP,
                calendar.timeInMillis,
                AlarmManager.INTERVAL_DAY,
                PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
            )
        }
    }
    

    JAVA

    public class DailyTaskBroadcastReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            yourTask();
        }
        
    }
    
    
    
    public class MyApplication extends Application {
    
        @Override
        public void onCreate() {
            super.onCreate();
            
            // Initiate your task
            scheduleDailyTask(this);
        }
    
        public void scheduleDailyTask(Context context) {
            AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            Intent intent = new Intent(context, DailyTaskBroadcastReceiver.class);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent,
                    PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE);
    
            // If the alarm is not already set, schedule it
            if (pendingIntent == null) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTimeInMillis(System.currentTimeMillis());
                calendar.set(Calendar.HOUR_OF_DAY, 0);
                calendar.set(Calendar.MINUTE, 0);
                calendar.set(Calendar.SECOND, 0);
                calendar.add(Calendar.DAY_OF_YEAR, 1); // Set to the next day
    
                // Set the alarm to trigger at midnight every day
                alarmManager.setRepeating(
                        AlarmManager.RTC_WAKEUP,
                        calendar.getTimeInMillis(),
                        AlarmManager.INTERVAL_DAY,
                        PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
                );
            }
        }
    }
    
    1. Don't forget to add a Broadcast receiver in the Manifest.xml file
    <receiver android:name=".DailyTaskBroadcastReceiver" />
    

    Testing

    To test you can simply update your scheduleDailyTask() to trigger after every 1 minute:

        // Alarm Schedule
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.add(Calendar.MINUTE, 1); // Set to trigger after 1 minute initially
    
    

    And also set the repetition

        // Set the alarm to repeat every minute
        alarmManager.setRepeating(
                AlarmManager.RTC_WAKEUP,
                calendar.getTimeInMillis(),
                60 * 1000, // 60 seconds * 1000 milliseconds
                pendingIntent
        );
    
       // Try printing the Log in the BroadcastReceiver onCreate method to verify if it is triggering after every 1 minute.
    
    }
    
    

    Note: I didn't compile this code, please don't forget to add imports.

    Reference: Check the more Calendar related tasks