Martin
Martin

Reputation: 2914

Android: How to call function inside Application class every 5 minutes in background

I want to start refresh Service within my app. What I want to achieve is to do API call every 5 minutes even if user locked his screen to update data and especially visible Notification by recreating Notification with new data from API call.

I tried to move my logic to Application class where I will initialize Job within GlobalScope, which will run indefinitely until I cancel this Job. This solution works if I set delay to 10 or 30 seconds. It is working even if my App is in background. But if I set delay to way longer period (which I need in this case) like 5 - 10 minutes, it will suddenly stop. My understanding is that this Job will die down or Application class is destroyed when there is long inactivity.

I would like to create Service which will communicate with my Application class and initialize this Job within Service to call Application class function to refresh Notification. But I cant use parameters in Service.

Is there any way how to link Application class and Service?

I don't need to run this refreshAPI if App is killed.

Example(this is running within Application class - want to move it to Service and call app.callRefreshAPI() from Service class):

var refresher: Job? = null
private var refreshRate = 300000L
fun createNotificationRefresher(){
    refresher = GlobalScope.launch {
        while (isActive){
            callRefreshAPI()
            delay(refreshRate)
        }
    }
}

UPDATE: CountDownTimer solution (not working):

var refresher: CountDownTimer? = null
private var refreshRate = 300000L //5min
private var refresherDuration = 780000L //12min
fun initNotificationRefresher(){
    refresher = object : CountDownTimer(refresherDuration, refreshRate) {
        override fun onTick(millisUntilFinished: Long) {
            callRefreshAPI()
        }
        override fun onFinish() {
            initNotificationRefresher()
        }
    }.start()
}

UPDATE 2: Timers/jobs/workers are not working when phone screen is locked and OS is in a sleep mode. That means there is no way to use timers in a background-background operations. I had to use BroadcastReceiver registered in Application class (NOT! AndroidManifest) and listen to SCREEN_ON action. Then saving time when user unlocked his phone and checking if it was at least 5-10 minutes between screen lock which updated notification and under this condition refresh Notification by calling API in GlobalScope.

I hope this will be helpful for others. Job/Timer will work if Application is in background and user is still interacting with phone (Checking other App, browsing stuff etc.).

Upvotes: 0

Views: 2808

Answers (2)

Atif AbbAsi
Atif AbbAsi

Reputation: 6035

you can use CountDownTimer for that. and Create an IntentService class and Run that service for API call.

JAVA

public void repeatCall(){

   new CountDownTimer(50000, 1000) {

        public void onTick(long millisUntilFinished) {

        }

        public void onFinish() {
           repeatCall();//again call your method
        }

    }.start();

}

//Declare timer
CountDownTimer cTimer = null;

//start timer function
void startTimer() {
    cTimer = new CountDownTimer(30000, 1000) {
        public void onTick(long millisUntilFinished) {
        }
        public void onFinish() {
        }
    };
    cTimer.start();
}


//cancel timer
void cancelTimer() {
    if(cTimer!=null)
        cTimer.cancel();
}

KOTLIN

 fun repeatCall() {

        object : CountDownTimer(50000, 1000) {

            override fun onTick(millisUntilFinished: Long) {

            }

            override fun onFinish() {
                repeatCall()//again call your method
            }

        }.start()

    }

Upvotes: 1

Raja chakraborty
Raja chakraborty

Reputation: 825

Though calling an API after every 5 minutes is not the most optimized way to do the task. The minimum value is 15min for periodic jobs. You can use

Ever Note Android Job Library for that.

private void schedulePeriodicJob() {
    int jobId = new JobRequest.Builder(DemoSyncJob.TAG)
            .setPeriodic(TimeUnit.MINUTES.toMillis(15), TimeUnit.MINUTES.toMillis(5))
            .build()
            .schedule();
}

Upvotes: 1

Related Questions