告警解释AlarmManager.setExact()启动时间错误



我计划在5秒内发送pendingIntent,但它在23秒内开始。API = 19 (AlarmManager.setExact(…)):

10-23 16:43:44.638  11903-11903/? D/MainActivity﹕ Fri Oct 23 16:43:44 GMT+05:00 2015: scheduled in 5000 ms
10-23 16:44:07.728  11903-11903/? D/MainActivity﹕ Fri Oct 23 16:44:07 GMT+05:00 2015: fired
private PendingIntent pendingIntent;
    private int SCHEDULE_REQUEST_CODE = 1;
    private static final String SCHEDULER_ACTION = "android.intent.action.FOTA_SCHEDULE_CHECK";
    private void log(String message) {
        StringBuilder sb = new StringBuilder();
        sb.append(new Date().toString());
        sb.append(": ");
        sb.append(message);
        sb.append("n");
        Log.d(getClass().getSimpleName(), sb.toString());
        tv.append(sb.toString());
        tv.append("n");
    }
    private BroadcastReceiver schedulerReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            log("fired");
        }
    };
    private void schedule() {
        registerReceiver(schedulerReceiver, new IntentFilter(SCHEDULER_ACTION));
        Intent scheduleIntent = new Intent(SCHEDULER_ACTION);
        pendingIntent = PendingIntent.getBroadcast(this, SCHEDULE_REQUEST_CODE, scheduleIntent, 0);
        AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        // first invocation (once, exact)
        int delay = 5 * 1000; // 5s
        log("scheduled in " + delay + " ms");
        alarmManager.setExact(AlarmManager.RTC, System.currentTimeMillis() + delay, pendingIntent);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unschedule();
    }
    private void unschedule() {
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarmManager.cancel(pendingIntent);
        pendingIntent = null;
        unregisterReceiver(schedulerReceiver);
    }

我有同样的问题,但pendingIntent在5秒后开始,而不是2,因为我试图设置。

alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 2 * 1000, pIntent);

如果设置为5秒及以上,则alarmManager精确启动。我不知道我在生产环境中得到的精确时间间隔,所以我选择1分钟作为短时间间隔。

所以,我的应用程序使用postDelayed()代替AlarmManager短时间间隔,AlarmManager长时间间隔。

代码示例:

if (delay == 0) {
    Intent intent = new Intent(context, SoundService.class);
    intent.putExtra(SoundService.SOUND, sound);
    context.startService(intent);
} else if (delay <= 60) {
    (new Handler()).postDelayed(new Runnable() {
        @Override
        public void run() {
            Intent intent = new Intent(context, SoundService.class);
            intent.putExtra(SoundService.SOUND, sound);
            context.startService(intent);
        }
    }, delay * 1000);
} else if (delay > 60) {
    final int SDK_INT = Build.VERSION.SDK_INT;
    Intent intent = new Intent(context, AlarmBroadcastReceiver.class);
    intent.setAction("action_play: " + sound);
    intent.putExtra(SoundService.SOUND, sound);
    PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    long runTime = System.currentTimeMillis() + delay * 1000;
    if (SDK_INT < Build.VERSION_CODES.KITKAT) {
        alarmManager.set(AlarmManager.RTC_WAKEUP, runTime, pIntent);
    } else if ((SDK_INT >= Build.VERSION_CODES.KITKAT) && (SDK_INT < Build.VERSION_CODES.M)) {
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, runTime, pIntent);
    } else if (SDK_INT >= Build.VERSION_CODES.M) {
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, runTime, pIntent);
    }
}

其中SoundService -具有声音播放功能的服务delay -播放前的延迟,以秒为单位;AlarmBroadcastReceiver——

public class AlarmBroadcastReceiver extends BroadcastReceiver {
final String LOG_TAG = this.getClass().getName();
@Override
public void onReceive(Context ctx, Intent intent) {
    if (intent.getAction().startsWith("action_play:")){
        Intent playIntent = new Intent(ctx, SoundService.class);
        playIntent.putExtra(SoundService.SOUND, intent.getStringExtra(SoundService.SOUND));
        ctx.startService(playIntent);
    }
}

}

最新更新