Android的AlarmManager RTC_WAKEUP不准确吗?

huangapple go评论77阅读模式
英文:

Android AlarmManager RTC_WAKEUP inprecise?

问题

我正在尝试找到一种在特定时间执行一些代码的方法。为此,我目前正在尝试使用Android提供的AlarmManager。在设置时间后,它会被执行,但执行时间通常不会与我设置的时间完全一致。似乎当设置的时间距离当前时间更远时,延迟会更长。我该如何修复这个问题?重要的是,代码在用户不在应用程序中但没有使用任务管理器关闭它时也能运行。

(抱歉,格式有点混乱)

MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private final String tag = "MainActivity";

    private TimePicker timePicker;
    private Button button;

    private boolean isRunning;
    private PendingIntent servicePI;
    private AlarmManager alarmManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    @Override
    public void onClick(View v) {
        if (isRunning) {
            Log.d(tag, "Stop service");

            alarmManager.cancel(servicePI);
            setState(false);
        } else {
            Log.d(tag, "Start service");

            int[] alarmTime = new int[2];
            if (Build.VERSION.SDK_INT < 23) {
                alarmTime[0] = timePicker.getCurrentHour();
                alarmTime[1] = timePicker.getCurrentMinute();
            } else {
                alarmTime[0] = timePicker.getHour();
                alarmTime[1] = timePicker.getMinute();
            }

            Calendar c = Calendar.getInstance();
            c.set(Calendar.HOUR_OF_DAY, alarmTime[0]);
            c.set(Calendar.MINUTE, alarmTime[1]);
            c.set(Calendar.SECOND, 0);

            alarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), servicePI);
            setState(true);
        }
    }

    private void setState(boolean state) {
        isRunning = state;
        if (state)
            button.setText("Stop");
        else
            button.setText("Start");
    }

    private void init() {
        timePicker = findViewById(R.id.timePicker);
        button = findViewById(R.id.button_power);
        button.setOnClickListener(this);

        setState(false);

        Intent service = new Intent(getApplicationContext(), MyService.class);
        servicePI = PendingIntent.getService(getApplication(), 0, service, 0);
        alarmManager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
    }
}


MyService
public class MyService extends Service {

    private final String tag = "MyService";

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(tag, "Start");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
英文:

I am trying to find a way to execute some code at specifics times. For this I am trying currently to just use what Android gives: the AlarmManger. When setting the time it gets executed but not exactly to when I've set the time -> There is always a delay which seems to be longer when the time is more away from the current. How can I fix it? And it's important that the codes runs when the user is not in the app but did not close it with the task manager.

(Sorry for the formatting)

MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private final String tag = &quot;MainActivity&quot;;
private TimePicker timePicker;
private Button button;
private boolean isRunning;
private PendingIntent servicePI;
private AlarmManager alarmManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
@Override
public void onClick(View v) {
if (isRunning) {
Log.d(tag, &quot;Stop service&quot;);
alarmManager.cancel(servicePI);
setState(false);
}else {
Log.d(tag, &quot;Start service&quot;);
int[] alarmTime = new int[2];
if (Build.VERSION.SDK_INT &lt; 23) {
alarmTime[0] = timePicker.getCurrentHour();
alarmTime[1] = timePicker.getCurrentMinute();
}else {
alarmTime[0] = timePicker.getHour();
alarmTime[1] = timePicker.getMinute();
}
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, alarmTime[0]);
c.set(Calendar.MINUTE, alarmTime[1]);
c.set(Calendar.SECOND, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), servicePI);
setState(true);
}
}
private void setState(boolean state) {
isRunning = state;
if (state)
button.setText(&quot;Stop&quot;);
else
button.setText(&quot;Start&quot;);
}
private void init() {
timePicker = findViewById(R.id.timePicker);
button = findViewById(R.id.button_power);
button.setOnClickListener(this);
setState(false);
Intent service = new Intent(getApplicationContext(), MyService.class);
servicePI = PendingIntent.getService(getApplication(), 0, service,0);
alarmManager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
}
}
MyService:
public class MyService extends Service {
private final String tag = &quot;MyService&quot;;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(tag, &quot;Start&quot;);
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

答案1

得分: 0

调用 AlarmManager.set() 是不精确的。这允许 Android 优化设备的电源使用。如果您需要精确的传递,您需要使用 setExact() 或者 setExactAndAllowWhileIdle()。请查阅文档中的注意事项。

英文:

Calls to AlarmManager.set() are inexact. This allows Android to optimize the power usage of the device. If you require exact delivery, you need to use setExact() or setExactAndAllowWhileIdle(). See the NOTE in the documentation.

huangapple
  • 本文由 发表于 2020年5月2日 18:16:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/61557695.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定