我希望有一个应用程序创建一个在应用程序启动时每2小时运行一次的任务,但当我关闭应用程序并再次打开它时,我的onReceive会被调用。
AlarmManager alarmManager=(AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 2*60*60*1000, pendingIntent);
正如您所看到的,alarmManager.setRepeating
的第三个论点是System.currentTimeMillies()
,这意味着将立即调用BroadcastReciever,然后每2小时调用一次。但是,如果我打开应用程序,将其滑动到侧面并再次启动它关闭它,然后BroadcastReciever会在两个小时之前得到通知,我不希望这种情况发生。我怎样才能防止这种情况发生?
这是我的AlarmReciever.java:
public class AlarmReceiver extends BroadcastReceiver {
Random rng = new Random();
boolean isRegistered = false;
@Override
public void onReceive(Context context, Intent intent) {
if(isRegistered)
return;
isRegistered = true;
List<Food> foods = new ArrayList<>();
File file = new File(context.getFilesDir(), "foods.txt");
if(!file.exists())
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
try {
InputStream inputStream = context.openFileInput("foods.txt");
if ( inputStream != null ) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line = "";
while ((line = bufferedReader.readLine()) != null ) {
foods.add(new Food(line.split("\\|")[0], Boolean.valueOf(line.split("\\|")[1])));
}
inputStream.close();
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
List<Food> temp = new ArrayList<>();
for (Food food : foods) {
if(food.isAvailable())
temp.add(food);
}
Food food = temp.get(rng.nextInt(temp.size()));
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder mBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("Food Reminder!")
.setContentText("Remember you still have " + food.getText().trim() + " in your home!")
.setSound(soundUri);
Intent resultIntent = new Intent(context, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
}
}
除非应用程序被强制停止或我通过代码对其进行编码,否则如何防止这种情况发生并始终每隔2小时运行一次?
另外:我正在使用isRegistered
变量来阻止应用在关闭并打开应用时创建多个AlarmRecivers,这是我应该怎么做的?
答案 0 :(得分:0)
问题是,如果你要杀死你的活动,所有变量都会被粉碎。这意味着你必须在BroadcastReceiver本身做这种事情。
您可以在AlarmReceiver
课程中定义新的变量:
private Long LastTime = 0;
然后你把这个
@Override
public void onReceive(Context context, Intent intent) {
if(isRegistered)
return;
if((System.currentTimeMillis()-LastTime)<7200000 && !intent.getBooleanExtra("ignoreTime",false))
return;
LastTime = System.currentTimeMillis();
isRegistered = true;
List<Food> foods = new ArrayList<>();
File file = new File(context.getFilesDir(), "foods.txt");
if(!file.exists())
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
try {
InputStream inputStream = context.openFileInput("foods.txt");
if ( inputStream != null ) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line = "";
while ((line = bufferedReader.readLine()) != null ) {
foods.add(new Food(line.split("\\|")[0], Boolean.valueOf(line.split("\\|")[1])));
}
inputStream.close();
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
List<Food> temp = new ArrayList<>();
for (Food food : foods) {
if(food.isAvailable())
temp.add(food);
}
Food food = temp.get(rng.nextInt(temp.size()));
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder mBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("Food Reminder!")
.setContentText("Remember you still have " + food.getText().trim() + " in your home!")
.setSound(soundUri);
Intent resultIntent = new Intent(context, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
}
现在如果你想忽略计时器(因为我假设有时你不想等待2个小时)你必须修改用于触发广播接收器的意图,如下所示:
Intent intent = new Intent(this, AlarmReceiver.class);
intent.setBooleanExtra("ignoreTime",true);
为什么你不能在主要课程中做到这一点:
问题是如果你的Activity死了所有预定的Intents,变量等因为你确实毁掉了它而死掉了。要从您的活动中执行此操作,您必须在onDestroy()
方法中执行某些操作,以便将某些变量保存到存储i.E.保持最后一次调用接收器的SharedPreferences
。如果由于某种原因,你的活动会被终止,你就不会打电话给onDestroy,所以即使那个方法风险很大