Home » Android » java – Action TIME_SET in android getting called many times without changing the time manually

java – Action TIME_SET in android getting called many times without changing the time manually

Posted by: admin June 15, 2020 Leave a comment

Questions:

I have a receiver which listens to the TIME_SET action android.

but some times am getting intent action without changing the time (random issue)

please help me in solving this issue

Thanks in advance.
code

    <receiver
        android:name=".tamperprooftime.TimeChangedReceiver"
        android:exported="false" >
        <intent-filter>
            <action android:name="android.intent.action.TIME_SET" />
            <action android:name="android.intent.action.TIMEZONE_CHANGED" />
        </intent-filter>
    </receiver>
How to&Answers:

I also had this same issue. It appears that if your device has the “Use network provided time” checked the device will periodically update the time. It seems like if the time is updated even for the smallest of time corrections the TIME_SET broadcast will happen… I wish that there was some threshold parameter that could be checked/used so that these minor time corrections are broadcast, or that there was a different broadcast for when the user explicitly changed the time versus the device was correcting itself.

Answer:

I found it unreliable, to use ACTION_TIME_CHANGED and ACTION_TIMEZONE_CHANGED. Sometimes it gets triggered and sometimes it does not get triggered even i change device time manually. When device time is changed manually ACTION_TIME_CHANGED gets called twice on my device.

Depending on your use case and needs, you might calculate if device time (System.currentTimeMillis() only) has changed manually, by checking every X seconds. But it does not detect if Timezone has changed. Since System.currentTimeMillis() might change but SystemClock.elapsedRealtime() does not change unless device is booted, you can detect if System.currentTimeMillis() changed.

In Kotlin, sample implementation would look like this:

private val TIME_CHANGE_CONTROL_INTERVAL = 10_000L
private val TIME_CHANGE_THRESHOLD = 1_000L
private var lastUptimeTime = SystemClock.elapsedRealtime()
private var lastEpochTime = System.currentTimeMillis()
private lateinit var timeChangeJob: Job

private fun detectTimeChange() {
    val uptimeDifference = SystemClock.elapsedRealtime() - lastUptimeTime
    val epochDifference = System.currentTimeMillis() - lastEpochTime
    val timeChange = Math.abs(uptimeDifference - epochDifference)

    if (timeChange > TIME_CHANGE_THRESHOLD) {
        // Time has changed more than 1sec
    }

    lastUptimeTime = SystemClock.elapsedRealtime()
    lastEpochTime = System.currentTimeMillis()
}

fun listenToDeviceTimeChanges() {
    if (::timeChangeJob.isInitialized) timeChangeJob.cancel()
    timeChangeJob = Job()

    GlobalScope.launch(timeChangeJob) {
        while (isActive) {
            detectTimeChange()
            delay(TIME_CHANGE_CONTROL_INTERVAL)
        }
    }
}

fun unlistenToDeviceTimeChanges() {
    if (::timeChangeJob.isInitialized) timeChangeJob.cancel()

    lastUptimeTime = SystemClock.elapsedRealtime()
    lastEpochTime = System.currentTimeMillis()
}