每个午夜在 Android 应用程序中使用 AlarmManager 运行 编码

Using an AlarmManager to run code every midnight in Android app

我在这里看到了这个答案 但无法正常工作。

我有一个函数 refreshStuff() 可以刷新片段的值。我在制作片段时、用户更新值时以及 onResume() 期间调用此函数。我还想在午夜强制刷新,这在用户只是看着屏幕而不做任何事情时是相关的。

但我不确定如何在 MyFragment class 中进行设置。我试过了:

public class MyFragment extends Fragment {
    ...
    private AlarmManager alarmMgr;
    private PendingIntent alarmIntent;
    private Context context;
    ...

    //in onCreate method
    context = getActivity();
    alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, AlarmReceiver.class);
    alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

    //midnight I hope
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis()); //do I even need this?
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);

    alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        AlarmManager.INTERVAL_DAY, alarmIntent);

如果我理解答案,我必须在某处添加此方法:

@Override
public void onReceive(Context context, Intent intent) {
   refreshStuff();
} 

但是我在任何地方都没有 AlarmReceiver,而且我不知道将 onReceive() 放在哪里或者我必须在清单中定义什么。我也不知道收到后要不要"turn it off"? (在不该做的时候做 "alarms" "stack"?)

否则到目前为止这是正确的方法吗?

编辑:

我尝试实现 CommonsWare 的答案:

public class MyFragment extends Fragment implements Runnable, SomeOtherListenersIUse, YetAnotherListenerEtc {

    private View viewForDisplayingTotals;

    //...rest of implementation omitted for brevity

    @Override
    public void run() {
        refreshValues();
    }

    @Override
    public void onStart() {
        super.onStart();
        refreshValues();
        viewForDisplayingTotals.postDelayed(this, HelperMethods.getMillisecondsTillNextMidnight());
    }

    @Override
    public void onStop() {
        super.onStop();
        viewForDisplayingTotals.removeCallbacks(this);
    }
}

我的辅助方法:

public static long getMillisecondsTillNextMidnight() {
    Calendar c = Calendar.getInstance();
    c.add(Calendar.DAY_OF_MONTH, 1); //add a day first
    c.set(Calendar.HOUR_OF_DAY, 0); //then set the other fields to 0
    c.set(Calendar.MINUTE, 0);
    c.set(Calendar.SECOND, 0);
    c.set(Calendar.MILLISECOND, 0);
    return c.getTimeInMillis() - System.currentTimeMillis();
}

摆脱所有 AlarmManager 东西。那是当你想在某些时候在后台获得控制权时,在你的情况下,这只是当你在前台时的问题。

第 1 步:将 implements Runnable 添加到您的 MyFragment 定义中

第 2 步:这将要求您实现 run() 方法,并在其中调用 refreshStuff()

第 3 步:在 onResume()(或者更好,onStart())中,当您调用 refreshStuff() 时,在一些方便的 View 上也会 call postDelayed(this, ...) ],其中 ... 是现在和下一个午夜之间的毫秒数

第 4 步:在 onPause()(或者,更好的 onStop())中,在同一个 View

上调用 removeCallbacks(this)

这将导致您的 run() 方法在午夜左右被调用,您将在其中调用 refreshStuff().

//do I even need this?

是的。不过请注意,您的计算是针对 过去 的午夜,忽略秒数。 add() 一天,并考虑使用 set() 将秒数归零。