Задать вопрос
@4ainik
начинал с бейсика на 286 в 1994

Как выполнять код с определенной периодичностью?

Есть необходимость выполнять код скажем с интервалом 1 секунда, при этом приложение/активити может быть свернуто и вообще на устройстве может быть выключен экран. Какое более подходящее и архитектурно правильное решение для этого использовать?
  • Вопрос задан
  • 332 просмотра
Подписаться 3 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 4
AndroidManifest.xml
...
<receiver android:name=".MyAlarmReceiver" />
<service android:name=".MyService" android:process=":my_app_alternate" android:enabled="true" />
...


MyAlarmReceiver.java
public class MyAlarmReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        context.startService(new Intent(context, MyService.class));		
        setupAlarm(context);
    }

    final long intervalMs = 60000; // Интервал в миллисекундах

    public static final void setupAlarm(Context context) {
        AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent(context, MyAlarmReceiver.class);
        PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
        if (am != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + intervalMs, pi);
            } else {
                am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + intervalMs, pi);
            }
        }
    }
}


MyService.java
public class MyService extends Service {

    Thread workThread = null;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (workThread == null) {
            workThread = new Thread(run);
            workThread.start();
        }
        return Service.START_STICKY;
    }

    final Runnable run = new Runnable() {
        @Override
        public void run() {
            try {
                while (true) {
                    //todo Что там надо делать раз в секунду
                    Thread.sleep(1000);
                }
            } catch (InterruptedException iex) { }
			
            workThread = null;
        }
    }
}


Когда необходимо запустить выполнение кода, вызываем MyAlarmReceiver.setupAlarm. Последующие вызовы происходят из MyAlarmReceiver.onReceive.
Ответ написан
@peacemakerv
Разработка под Android
Если надо прямо вот на 146% каждую секунду насиловать железку, то поможет только Foreground service (с обязательной иконкой в области уведомлений, т.е. не спрячете). И в настройках питания системы, конечно, надо разрешить фоновую работу приложению. А то от Doze можно и не спастись.
Ответ написан
Neikist
@Neikist
Бывший 1сник, теперь пишу под андроид
У WorkManager ограничения снизу есть. Ну и doze mode никто не отменял. Так что в таком варианте как описано сделать не получится.
Ответ написан
@IvAnHV
я бы сделал через отдельный поток и thread.sleep, а чтобы это все работало в фоне запихнул бы это в службу, это самый простой вариант, а чтобы все было правильно нужно уже от задачи отталкиваться.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы