Android AlarmManager setExact() is not exact

后端 未结 6 814
隐瞒了意图╮
隐瞒了意图╮ 2020-12-01 04:30

I need to plan sheduled task every 10 minutes.

As in Lollipop and higher version setRepeating() is inexact, I use setExact() and (on alarm

6条回答
  •  粉色の甜心
    2020-12-01 05:22

    Probably a possible workaround could be something like this: you schedule the Alarm about 1 minute before the expected time, than you use a Handler.postDelayed to cover the remaining time.

    Here you can find an example of this kind of implementation. The activity just set-up the first alarm:

    public class MainActivity extends AppCompatActivity {
    
        private static int WAIT_TIME = 60*1000; //1 minute
        public static int DELAY_TIME = 10*60*1000; // delay between iterations: 10min
        public static String UPDATE_TIME_KEY = "update_time_key";
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            setAlarm(this,(new Date().getTime())+DELAY_TIME);
        }
    
        public static void setAlarm(Context context, long delay) {
    
            long fireDelay = delay-WAIT_TIME;
            SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
            sharedPreferences.edit().putLong(UPDATE_TIME_KEY,delay).apply();
    
            Intent startIntent = new Intent(context, UpdateReceiver.class);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, startIntent,PendingIntent.FLAG_UPDATE_CURRENT );
            AlarmManager alarmManager = (AlarmManager) context.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
            int ALARM_TYPE = AlarmManager.RTC;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                alarmManager.setExact(ALARM_TYPE, fireDelay, pendingIntent);
            } else {
                alarmManager.set(ALARM_TYPE, fireDelay, pendingIntent);
            }
        }
    
    }
    

    than the receiver continues the loop:

    public class UpdateReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(final Context context, Intent intent) {
            Log.e("RECEIVED","RECEIVED");
            SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
            long fireTime = sharedPreferences.getLong(MainActivity.UPDATE_TIME_KEY, (new Date()).getTime());
    
            long fireDelay  =(fireTime-(new Date().getTime())>0)?fireTime-(new Date().getTime()):0;
    
            (new Handler()).postDelayed(new Runnable() {
                @Override
                public void run() {
                    Log.e("RECEIVED","PERFORMED");
                    MainActivity.setAlarm(context,(new Date()).getTime()+MainActivity.DELAY_TIME);
                }
            },fireDelay);
    
        }
    
    }
    

    I hope it helped.

提交回复
热议问题