安卓闹钟管理器设置重复在特定时间
我在Android的闹钟管理器有一些问题。所以我试图做的是设置闹钟,重复每天12.01AM左右运行数据库插入。安卓闹钟管理器设置重复在特定时间
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 1);
notificationCount = notificationCount + 1;
AlarmManager mgr = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent notificationIntent = new Intent(context,
ReminderAlarm.class);
notificationIntent.putExtra("NotifyCount", notificationCount);
PendingIntent pi = PendingIntent.getBroadcast(context,
notificationCount, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
mgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
所以基本上我已经想出了这些代码。然而,警报管理器在我设置它的那一分钟后再次执行。
假设我在2014年10月10日5.48PM运行应用程序。我想在每天将onReceive设置在12.01AM左右后运行数据库插入。但不知何故,警报管理器在执行时间为2014年1月10日下午5点49分,这是我设置后一分钟后停止工作。
我想知道我错误地做了哪一部分。
在此先感谢。
编辑
周期性类 对于这个类,就会触发报警经理日常和传递变量一起为DB插入提醒报警类别。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recurring);
context = this;
buildListView();
if(!alarmInitialized(this)) {
scheduleAlarms(this);
}
}
// And the few methods you suggested to schedule the alarm
public static void scheduleAlarms(Context context) {
Calendar calendar = Calendar.getInstance();
if (hasRunnedToday(context)) { // if the alarm has run this day
calendar.add(Calendar.DATE, 1); // schedule it to run again starting
// tomorrow
}
long firstRunTime = calendar.getTimeInMillis();
AlarmManager mgr = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent notificationIntent = new Intent(context, ReminderAlarm.class);
PendingIntent pi = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
mgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstRunTime,
AlarmManager.INTERVAL_DAY, pi);
ComponentName receiver = new ComponentName(context, BootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
BootReceiver类
public void onReceive(Context context, Intent i) {
if (i.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Recurring.scheduleAlarms(context);
}
}
ReminderAlarm类 基本上这个类,它只是抓住从周期性类传递的变量,并执行DB插入。我确实插入了一些Toast.makeText来测试它是否正在检索,但通过测试没有运气。
public class ReminderAlarm extends BroadcastReceiver {
private NotificationManager mNotificationManager;
private Notification notification;
@Override
public void onReceive(Context context, Intent intent) {
String recurID = null;
String recurStartDate = null;
String currentDate = null;
String description = null;
String type = null;
String amount = null;
String categoryName = null;
String frequencyStr = null;
String nextPaymentDate = null;
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
DatabaseAdapter mDbHelper = new DatabaseAdapter(context);
mDbHelper.createDatabase();
mDbHelper.open();
RecurringController rc = new RecurringController(mDbHelper.open());
ArrayList<RecurringModel> recur_list = rc.getAllRecurring();
// THIS PART TO GET DATA FROM DATABASE
for (int i = 0; i < recur_list.size(); i++) {
recurID = recur_list.get(i).getRecurringID();
recurStartDate = recur_list.get(i).getRecurringStartDate();
currentDate = dateFormat.format(new Date());
description = recur_list.get(i).getRecurringDesc();
type = recur_list.get(i).getRecurringType();
amount = Float.toString(recur_list.get(i).getRecurringAmount());
categoryName = recur_list.get(i).getCategoryID();
frequencyStr = recur_list.get(i).getFrequency();
Toast.makeText(context,
description, Toast.LENGTH_LONG)
.show();
Toast.makeText(context,
recurStartDate Toast.LENGTH_LONG)
.show();
Calendar cal = Calendar.getInstance();
try {
cal.setTime(dateFormat.parse(recurStartDate));
if (frequencyStr.equals("Daily")) {
cal.add(Calendar.DAY_OF_MONTH, 1);
nextPaymentDate = dateFormat.format(cal.getTimeInMillis());
cal.add(Calendar.DAY_OF_MONTH, -1);
} else if (frequencyStr.equals("Weekly")) {
cal.add(Calendar.WEEK_OF_YEAR, 1);
nextPaymentDate = dateFormat.format(cal.getTimeInMillis());
cal.add(Calendar.WEEK_OF_YEAR, -1);
} else if (frequencyStr.equals("Monthly")) {
cal.add(Calendar.MONTH, 1);
nextPaymentDate = dateFormat.format(cal.getTimeInMillis());
cal.add(Calendar.MONTH, -1);
} else if (frequencyStr.equals("Yearly")) {
cal.add(Calendar.YEAR, 1);
nextPaymentDate = dateFormat.format(cal.getTimeInMillis());
cal.add(Calendar.YEAR, -1);
}
} catch (ParseException e) {
e.printStackTrace();
}
// If dates match then execute the SQL statements
if (currentDate.equals(nextPaymentDate)) {
// mDbHelper.createDatabase();
// mDbHelper.open();
TransactionRecModel trm = new TransactionRecModel();
CategoryController cc = new CategoryController(mDbHelper.open());
trm.setDate(currentDate);
trm.setTransDescription(description);
trm.setType(type);
trm.setAmount(Float.parseFloat(amount));
// Get the categoryID based on categoryName
String catID = cc.getCatIDByName(categoryName);
trm.setCategory(catID);
// Check if the recurring record exists before insert new
// transaction record
boolean recurExist = rc.checkRecurExist(recurStartDate,
description, catID);
if (recurExist == true) {
TransactionRecController trc = new TransactionRecController(
mDbHelper.open());
// Check if the transaction record exists to prevent
// duplication
boolean moveNext = trc.checkTransExist(trm);
if (moveNext == false) {
if (trc.addTransactionRec(trm)) {
// Update recurring start date after insertion of
// transaction
RecurringModel rm = new RecurringModel();
rm.setRecurringID(recurID);
rm.setRecurringStartDate(currentDate);
if (rc.updateRecurringDate(rm)) {
mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent
.getActivity(
context,
Integer.parseInt(intent
.getExtras()
.get("NotifyCount")
.toString()),
new Intent(), 0);
notification = new Notification(
R.drawable.ic_launcher, "Notification",
System.currentTimeMillis());
notification.setLatestEventInfo(context,
description, nextPaymentDate,
contentIntent);
mNotificationManager
.notify(Integer.parseInt(intent
.getExtras().get("NotifyCount")
.toString()), notification);
mDbHelper.close();
}
}
}
}
mDbHelper.close();
}
}
mDbHelper.close();
Recurring.updateAlarmLastRun(context);
}
}
我在您建议的部分中添加了这部分代码,以安排警报调用BootReceiver类。然后,从BootReceiver类,我会打电话回周期性类和提醒报警类别:
ComponentName receiver = new ComponentName(context, BootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
的问题是在calendar.getTimeInMillis()
在
mgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
的第二个参数setInexactRepeating
引述商务部
triggerAtMillis使用适当的时钟(取决于报警类型),报警应首先关闭的毫秒时间。这是不准确的:警报在此时间之前不会触发,但在第一次调用警报之前可能会有几乎整个警报间隔的延迟。
这意味着它设置之后,因为
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 1);
如果您wan't报警的第一次运行,第二天做 日历将aproximally首次运行一分钟。添加(日历。日期,1);`
至于它停止工作,你重新启动德设备? AlarmCalendar报警不会坚持到设备重新启动,你可以注册一个BroadcastReceiver
接收BOOT_COMPLETED
事件和注册警报再次检查 does Alarm Manager persist even after reboot?
更新:按照您的要求在这里查看您的代码后,一些帮助
在您BOOT_COMPLETED
接收机类:
public void onReceive(Context context, Intent i) {
if (i.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
ReminderAlarm.scheduleAlarms(this);
}
}
在你ReminderAlarm CLA SS
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recurring);
if(!alarmInitialized(this) {
scheduleAlarms(this);
}
}
public static void scheduleAlarms(Context context) {
Calendar calendar = Calendar.getInstance();
if(hasRunnedToday(context)) { //if the alarm has run this day
calendar.add(Calendar.DATE, 1); //schedule it to run again starting tomorrow
}
long firstRunTime = calendar.getTimeInMillis();
AlarmManager mgr = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent notificationIntent = new Intent(context, ReminderAlarm.class);
PendingIntent pi = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
mgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,
firstRunTime, AlarmManager.INTERVAL_DAY, pi);
}
public static boolean alarmInitialized(Context context) {
SharedPreferences preferences = context.getSharedPreferences("alarm_prefs", MODE_PRIVATE);
long alarmLastRun = preferences.getLong("AlarmLastRun", -1);
return alarmLastRun != -1;
}
public static void updateAlarmLastRun(Context context) {
SharedPreferences preferences = context.getSharedPreferences("alarm_prefs", MODE_PRIVATE);
preferences.edit()
.putLong("AlarmLastRun", new Date().getTime())
.apply();
}
public static boolean hasRunnedToday(Context context) {
SharedPreferences preferences = context.getSharedPreferences("alarm_prefs", MODE_PRIVATE);
long alarmLastRun = preferences.getLong("AlarmLastRun", -1);
if(alarmLastRun == -1) {
return false;
}
//check by comparing day, month and year
Date now = new Date();
Date lastRun = new Date(alarmLastRun);
return now.getTime() - lastRun.getTime() < TimeUnit.DAYS.toMillis(1);
}
您的每一个提醒类报警运行,你应该叫updateAlarmLastRun
更新警报已经对最近一次运行时间,这是必要的,因为报警可能会日程是运行一天,并且用户在警报运行之前重新启动设备,在这种情况下,我们不希望 使用calendar.add(Calendar.DATE, 1);
,因为那样会跳过一天。
在您Manifest.xml
<receiver android:name=".BootReceiver" android:enabled="true" android:exported="false" android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
注:
- 你不应该做
context = this
如果上下文是一个类字段,因为对象持有其领域context
和context
字段的引用持有参考到会泄漏的对象 - 您的
Receiver
'onReceive`没有额外设置,您假设拥有像“notificationCount”onRec系统在您的设备完成启动时由系统提供。 - 一旦报警跑致电
updateAlarmLastRun
希望任何这有助于
是的,我添加了代码,以便在重新启动时警报仍然会持续。但我应该在哪里添加instance.add()? – 2014-10-09 11:35:47
我的坏我的意思calendar.add我已经更新了awnser – forcewill 2014-10-09 11:39:16
所以我应该在我的两个类中添加该行?你能帮我检查一下我编辑过的部分吗? – 2014-10-09 11:42:49
**” ......报警经理执行在2014年1月10日下午5点49分是在一分钟后我将它和它停止工作。“**您将”Calendar.HOUR_OF_DAY“设置为0,从而将时间倒退。这会立即触发警报,直到第二天00:01才会再次触发。 – Squonk 2014-10-01 10:11:27
@Squonk那么你有什么想法来解决这个问题吗?因为从我的研究中,我认为这样做能够在特定时间触发警报。 – 2014-10-01 10:13:41
@Squonk那么我把这些代码放在哪里?你介意把整个部分作为答案吗? – 2014-10-01 10:24:52