Как запускать службу каждый день в полдень и при каждой загрузке

#android #service #broadcastreceiver

#Android #Обслуживание #broadcastreceiver

Вопрос:

В моем приложении у меня есть база данных SQLite, в которой есть одна таблица со строками даты в миллисекундах. Я хотел бы, чтобы уведомление отображалось каждый день, если с момента последнего значения даты, сохраненного в моей базе данных, прошло 30 дней. Служба кажется хорошим способом выполнить эту проверку.

Я столкнулся с Commonsware WakefulIntentService и подумал, что это может быть ответом, но я действительно не знаю, как мне его реализовать. В демо-версии служба запускается через 5 минут после завершения загрузки, что просто отлично, но что мне нужно добавить, чтобы она также запускалась каждый полдень. (… но только для отображения одного уведомления в день, а не обоих, как при загрузке, так и при регулярной ежедневной проверке)

Я знаю, что это можно решить с помощью AlarmManager, но на самом деле не знаю как. Итак, помощь, в которой я нуждаюсь, — это дать мне несколько примеров / ключевых моментов, чтобы запустить службу при каждой загрузке и / или каждый день без запуска приложения.

Спасибо

Ответ №1:

Android alarmmanager — ваш ответ. используйте его с широковещательным приемником, который также сбрасывает сигналы тревоги при пробуждении телефона.

Теперь с примером кода: установка будильника внутри метода:

 Intent intent = new Intent(context, AlarmReceiver.class);
intent.setAction("packagename.ACTION");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
            0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
        AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pendingIntent);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
 

Приемник для вашего интервала:

 public class AlarmReceiver extends BroadcastReceiver {
private final String SOMEACTION = "packagename.ACTION"; //packagename is com.whatever.www
@Override
public void onReceive(Context context, Intent intent) {
    Time now = new Time();
    now.setToNow();
    String time = FileHandler.timeFormat(now);

    String action = intent.getAction();
    if(SOMEACTION.equals(action)) {
        // here you call a service etc.
    }
 

Приемник для сброса сигналов тревоги всякий раз, когда телефон был выключен.

 public class AlarmSetter extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // get preferences
        SharedPreferences preferences = context.getSharedPreferences("name_of_your_pref", 0);
        Map<String, ?> scheduleData = preferences.getAll();

        // set the schedule time
        if(scheduleData.containsKey("fromHour") amp;amp; scheduleData.containsKey("toHour")) {
            int fromHour = (Integer) scheduleData.get("fromHour");
            int fromMinute = (Integer) scheduleData.get("fromMinute");

            int toHour = (Integer) scheduleData.get("toHour");
            int toMinute = (Integer) scheduleData.get("toMinute");

            //Do some action
        }
    }

}
 

Манифест очень важен, он добавляется в разделе приложение:

         <receiver android:name="AlarmReceiver">
        <intent-filter>
            <action android:name="packagename.ACTION"/>
            <action android:name="packagename.ACTION2"/>
        </intent-filter>
    </receiver>

    <receiver android:name="AlarmSetter" >
        <intent-filter>
            <action
                android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
 

Также для того, чтобы это работало, вам необходимо добавить разрешение на получение широковещательной загрузки в манифест со следующей строкой:

 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
 

Надеюсь, это прояснило ситуацию, если какие-либо ошибки, пожалуйста, сообщите.

Редактировать (добавлен пример alarmsetter):

 public class AlarmSetter extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // Do your stuff
    }
}
 

Комментарии:

1. извините, что я немного плохо сформулировал свой вопрос, но я уже знал alarmmanager, но не совсем, как использовать его для решения проблемы … и как сбросить его при пробуждении. Итак, я думаю, мне нужно запустить ту же службу, что и в commonsware WakefulIntentService demo ( github.com/commonsguy/cwac-wakeful ), но от другого приемника …? Без запуска приложения, как запускать службу ежедневно и / или при каждой загрузке.

2. Прочитайте о alarmmanagerit очень просто. или Google 🙂 может дать некоторый код сегодня вечером, если вы все еще застряли

3. застряли уже несколько дней 🙂 так что да, примеры кода будут высоко оценены.

4. привет, я не знаю, почему мне так сложно это понять… но в вашем примере в классе AlarmReceiver вы проверяете, соответствует ли ACTION.equals(действие)… должно ли это быть «если (действие. равно (SOMEACTION)»? И если это правда, должен ли я вызывать свою службу как «Намерение i = новое намерение (контекст, MyService.class ); this.startService(i);»?… и что это за «sleepScheduler. ACTION2» вы объявили в своем манифесте? Кроме того, почему вы не вызываете службу в AlarmSetter?

5. Обновлен код и исправлены ошибки сервера. извините, что это было немного быстро. На ваши вопросы 1. Да, 1a. Да, вы могли бы это сделать, 2. Извините, это ошибка, 3. Мой код использовался для чего-то другого, теперь добавлено // Вместо этого выполните какое-то действие. Вы можете делать там все, что захотите.

Ответ №2:

Этот ответ кажется довольно старым. Теперь я бы настоятельно рекомендовал людям ознакомиться с платформой SyncAdapter, предоставляемой Google. Он специально создан для таких вещей. Вот ссылка: https://developer.android.com/training/sync-adapters/index.html

Комментарии:

1. Об этом должно знать больше людей. Как я. Спасибо!

Ответ №3:

В демо-версии служба запускается через 5 минут после завершения загрузки, что просто отлично, но что мне нужно добавить, чтобы она также запускалась каждый полдень.

Измените начальное время setRepeating() вызова. В примере показана одна минута с этого момента — вам нужно будет выполнить вычисления, чтобы определить, когда наступит следующий полдень.

Вы можете увидеть пример такого рода вычислений в this OnBootReceiver из другого примера проекта. Здесь я настраиваю будильник на каждый день в указанное пользователем время.