应用程序关闭并启动时如何使BroadcastReciever不重启?

时间:2016-09-14 21:23:59

标签: android alarmmanager

我希望有一个应用程序创建一个在应用程序启动时每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,这是我应该怎么做的?

1 个答案:

答案 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,所以即使那个方法风险很大