For your prayer app every day the prayer times are changing. What about writing a procedure, which gives you only the next prayer time ? Then set the alarm to that time. And after an alarm gets triggered, get the next prayer time, etc. This process will work as long as there is internet access available.
The extension does all this, but without background button activation, it's all useless. In this case, the app works perfectly. But I have to open the app to update the data.
I tried to create a background connection with AI, but nothing worked. Notifications came in the background while the app was minimized, but as soon as I closed the app, everything stopped.
// --- Удален код фоновых задач ---
// package com.muslimapp.prayertimes;
// import android.app.AlarmManager;
// import android.app.NotificationManager;
// import android.app.PendingIntent;
// import android.app.Service;
// import android.content.Context;
// import android.content.Intent;
// import android.os.Handler;
// import android.os.IBinder;
// import android.os.Looper;
// import android.util.Log;
// import androidx.core.app.NotificationCompat;
// import androidx.core.app.NotificationManagerCompat;
// import java.text.SimpleDateFormat;
// import java.util.*;
// public class PrayerBackgroundService extends Service {
// private static final String TAG = "PrayerBackgroundService";
// private static final long CHECK_INTERVAL_MS = 60000; // Проверять каждые 60 секунд (1 минута)
// private static final long NOTIFICATION_THRESHOLD_MS = 5 * 60 * 1000; // Отправлять уведомление за 5 минут до намаза
// private Handler serviceHandler;
// private Runnable checkerRunnable;
// private Map<String, List<String>> prayerTimesData; // Локальная копия для сервиса
// private boolean dataLoaded = false;
// @Override
// public void onCreate() {
// super.onCreate();
// Log.d(TAG, "PrayerBackgroundService: onCreate() вызван.");
// // Создаем уведомление для Foreground Service
// NotificationCompat.Builder builder = buildForegroundNotification();
// if (builder != null) {
// startForeground(FOREGROUND_NOTIFICATION_ID, builder.build());
// Log.d(TAG, "PrayerBackgroundService: Foreground Service запущен с уведомлением (ID: " + FOREGROUND_NOTIFICATION_ID + ").");
// } else {
// Log.e(TAG, "PrayerBackgroundService: Не удалось создать уведомление для Foreground Service.");
// }
// // Инициализируем Handler и Runnable для периодических проверок
// serviceHandler = new Handler(Looper.getMainLooper());
// startServiceChecker();
// // Обновляем ссылку на сервис в главном классе
// Muslimapp.backgroundService = this;
// Muslimapp.isServiceRunning = true; // Устанавливаем флаг, что сервис активен
// Log.d(TAG, "PrayerBackgroundService: onCreate() -> Muslimapp.isServiceRunning = true");
// }
// @Override
// public int onStartCommand(Intent intent, int flags, int startId) {
// Log.d(TAG, "PrayerBackgroundService: onStartCommand() вызван. Action: " + (intent != null ? intent.getAction() : "null"));
// if (intent != null) {
// // Обработка команды от AlarmManager
// if ("com.muslimapp.ACTION_ALARM_TRIGGER".equals(intent.getAction())) {
// Log.d(TAG, "PrayerBackgroundService: Получена команда от AlarmManager.");
// // При срабатывании AlarmManager, мы просто перезапускаем наш планировщик проверок,
// // чтобы убедиться, что он работает, даже если приложение было закрыто.
// // Основная логика проверки времени намаза находится в checkPrayerTimesInService().
// if (checkerRunnable == null) {
// startServiceChecker(); // Запускаем, если еще не запущен
// }
// // Если данные еще не загружены, пытаемся их получить
// if (!Muslimapp.dataLoaded) {
// Log.d(TAG, "PrayerBackgroundService: Данные не загружены, пытаемся загрузить.");
// // Не пытаемся загрузить данные здесь, т.к. это блокирующая операция.
// // Загрузка происходит в Muslimapp.LoadPrayerTimesData().
// // Просто убеждаемся, что сервис будет работать, когда данные появятся.
// } else {
// // Обновляем локальные данные, если они изменились
// prayerTimesData = new HashMap<>(Muslimapp.prayerTimes);
// dataLoaded = true; // Устанавливаем локальный флаг
// Log.d(TAG, "PrayerBackgroundService: Данные обновлены из Muslimapp.");
// }
// } else if ("com.muslimapp.ACTION_START_MANUALLY".equals(intent.getAction())) {
// Log.d(TAG, "PrayerBackgroundService: Получена команда на ручной запуск.");
// // При ручном запуске, также проверяем загрузку данных
// if (Muslimapp.dataLoaded) {
// prayerTimesData = new HashMap<>(Muslimapp.prayerTimes);
// dataLoaded = true;
// Log.d(TAG, "PrayerBackgroundService: Данные загружены при ручном запуске.");
// } else {
// Log.d(TAG, "PrayerBackgroundService: Данные еще не загружены, сервис будет ждать.");
// // Если данные не загружены, сервис будет работать, но проверки будут пропускаться
// // до тех пор, пока Muslimapp не загрузит данные.
// }
// }
// }
// // Возвращаем START_STICKY, чтобы система могла перезапустить сервис, если он будет уничтожен
// return START_STICKY;
// }
// @Override
// public void onDestroy() {
// super.onDestroy();
// Log.d(TAG, "PrayerBackgroundService: onDestroy() вызван.");
// // Останавливаем периодические проверки
// stopServiceChecker();
// // Отменяем AlarmManager, который был установлен в Muslimapp
// Intent serviceIntent = new Intent(this, PrayerBackgroundService.class);
// serviceIntent.setAction("com.muslimapp.ACTION_ALARM_TRIGGER"); // Тот же action, что и при установке
// int requestCode = 100; // Тот же requestCode, что и при установке
// int pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// pendingIntentFlags |= PendingIntent.FLAG_IMMUTABLE;
// }
// PendingIntent pendingIntent = PendingIntent.getService(this, requestCode, serviceIntent, pendingIntentFlags);
// AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// if (alarmManager != null && pendingIntent != null) {
// alarmManager.cancel(pendingIntent);
// Log.d(TAG, "PrayerBackgroundService: AlarmManager отменен.");
// } else {
// Log.w(TAG, "PrayerBackgroundService: AlarmManager или PendingIntent null при отмене.");
// }
// Muslimapp.backgroundService = null; // Очищаем ссылку на сервис
// Muslimapp.isServiceRunning = false; // Устанавливаем флаг, что сервис остановлен
// Log.d(TAG, "PrayerBackgroundService: onDestroy() -> Muslimapp.isServiceRunning = false");
// Log.d(TAG, "PrayerBackgroundService: onDestroy() -> Завершено.");
// }
// @Override
// public IBinder onBind(Intent intent) {
// Log.d(TAG, "PrayerBackgroundService: onBind() вызван. Возвращаем null.");
// return null; // Сервис не предназначен для биндинга
// }
// private void startServiceChecker() {
// Log.d(TAG, "PrayerBackgroundService: Запуск внутреннего планировщика проверок.");
// if (checkerRunnable == null) {
// checkerRunnable = new Runnable() {
// @Override
// public void run() {
// Log.d(TAG, "PrayerBackgroundService: Выполнение проверки времени намаза...");
// checkPrayerTimesInService();
// // Планируем следующую проверку
// if (checkerRunnable != null) { // Проверяем, не был ли уже остановлен
// serviceHandler.postDelayed(checkerRunnable, CHECK_INTERVAL_MS);
// }
// }
// };
// }
// // Запускаем первую проверку немедленно, если еще не запускались
// serviceHandler.post(checkerRunnable);
// }
// private void stopServiceChecker() {
// Log.d(TAG, "PrayerBackgroundService: Остановка внутреннего планировщика проверок.");
// if (checkerRunnable != null) {
// serviceHandler.removeCallbacks(checkerRunnable); // Удаляем все отложенные вызовы
// checkerRunnable = null;
// Log.d(TAG, "PrayerBackgroundService: Внутренний планировщик проверок остановлен.");
// }
// }
// private void checkPrayerTimesInService() {
// if (!dataLoaded || prayerTimesData == null || prayerTimesData.isEmpty() || !Muslimapp.AreNotificationsEnabled()) {
// Log.d(TAG, "PrayerBackgroundService: Проверка пропущена (данные не загружены, уведомления отключены, или prayerTimesData null/empty).");
// return;
// }
// String currentDate = Muslimapp.getCurrentDate();
// String currentTime = Muslimapp.getCurrentTime();
// List<String> times = prayerTimesData.get(currentDate);
// if (times == null) {
// Log.d(TAG, "PrayerBackgroundService: Нет данных о времени намаза для текущей даты: " + currentDate);
// return;
// }
// // Индексы для основных намазов (Фаджр, Зухр, Аср, Магриб, Иша)
// // Индексы в файле: [1] Сухур End, [2] Фаджр, [3] Восход, [4] Зухр, [5] Аср, [6] Магриб, [7] Иша
// int[] prayerIndices = {2, 4, 5, 6, 7};
// String[] prayerNames = {"Фаджр", "Зухр", "Аср", "Магриб", "Иша"};
// Set<String> sentNotifications = Muslimapp.sentNotifications; // Используем общее поле для отслеживания отправленных уведомлений
// SimpleDateFormat parser = new SimpleDateFormat("dd.MM HH:mm", Locale.getDefault());
// try {
// Date now = parser.parse(currentDate + " " + currentTime); // Текущее время
// for (int i = 0; i < prayerIndices.length; i++) {
// int prayerIndex = prayerIndices[i];
// String currentPrayerName = prayerNames[i]; // Имя намаза
// String notificationKey = currentDate + "_" + currentPrayerName; // Уникальный ключ для этого намаза сегодня
// // Проверяем, есть ли данные для этого намаза и не отправлялось ли уже уведомление
// if (prayerIndex < times.size()) {
// String prayerTimeStr = times.get(prayerIndex);
// if (prayerTimeStr != null && !sentNotifications.contains(notificationKey)) {
// Date prayerTimeDate = parser.parse(currentDate + " " + prayerTimeStr); // Время намаза
// long timeDiff = prayerTimeDate.getTime() - now.getTime(); // Разница во времени в миллисекундах
// // Отправляем уведомление, если до намаза осталось <= NOTIFICATION_THRESHOLD_MS
// // timeDiff > 0 означает, что намаз еще не наступил.
// if (timeDiff > 0 && timeDiff <= NOTIFICATION_THRESHOLD_MS) {
// sentNotifications.add(notificationKey); // Отмечаем, что уведомление отправлено
// sendNotificationDirectlyFromService(currentPrayerName, prayerTimeStr);
// Log.d(TAG, "PrayerBackgroundService: Уведомление для " + currentPrayerName + " в " + prayerTimeStr);
// }
// }
// } else {
// Log.w(TAG, "PrayerBackgroundService: Индекс намаза " + currentPrayerName + " (" + prayerIndex + ") выходит за границы списка данных.");
// }
// }
// } catch (Exception e) {
// Log.e(TAG, "PrayerBackgroundService: Ошибка при проверке времени намаза в сервисе.", e);
// }
// }
// // Строит уведомление для Foreground Service
// private NotificationCompat.Builder buildForegroundNotification() {
// Log.d(TAG, "PrayerBackgroundService: buildForegroundNotification() -> Создание уведомления...");
// Intent notificationIntent = new Intent(this, getMainActivityClass());
// if (notificationIntent.resolveActivity(getPackageManager()) != null) {
// notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Log.d(TAG, "PrayerBackgroundService: Notification Intent для MainActivity создан.");
// } else {
// notificationIntent = null; // Если MainActivity не найдена, Intent будет null
// Log.w(TAG, "PrayerBackgroundService: MainActivity не найдена. Notification Intent будет null.");
// }
// int pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// pendingIntentFlags |= PendingIntent.FLAG_IMMUTABLE;
// }
// PendingIntent pendingIntent = null;
// if (notificationIntent != null) {
// pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, pendingIntentFlags);
// Log.d(TAG, "PrayerBackgroundService: PendingIntent для MainActivity создан.");
// } else {
// Log.w(TAG, "PrayerBackgroundService: PendingIntent не будет создан, так как Notification Intent null.");
// }
// int appIcon = getApplicationInfo().icon; // Иконка приложения
// Log.d(TAG, "PrayerBackgroundService: appIcon = " + appIcon);
// return new NotificationCompat.Builder(this, CHANNEL_ID)
// .setContentTitle("MuslimApp активно")
// .setContentText("Проверка времени намаза...")
// .setSmallIcon(appIcon)
// .setContentIntent(pendingIntent)
// .setOngoing(true); // Уведомление нельзя удалить вручную, пока сервис активен
// }
// // Публичный метод для отправки уведомления напрямую из сервиса
// public void sendNotificationDirectlyFromService(String prayerName, String prayerTime) {
// // Снова проверяем, разрешены ли уведомления
// if (!Muslimapp.AreNotificationsEnabled()) {
// Log.w(TAG, "sendNotificationDirectlyFromService: Уведомления отключены. Уведомление не будет отправлено.");
// return;
// }
// // Intent для открытия MainActivity при нажатии на уведомление о намазе
// Intent notificationIntent = new Intent(this, getMainActivityClass());
// if (notificationIntent.resolveActivity(getPackageManager()) != null) {
// notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
// } else {
// notificationIntent = null; // Если MainActivity не найдена, Intent будет null
// }
// int pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// pendingIntentFlags |= PendingIntent.FLAG_IMMUTABLE;
// }
// PendingIntent pendingIntent = (notificationIntent == null) ? null : PendingIntent.getActivity(this, 0, notificationIntent, pendingIntentFlags);
// int appIcon = getApplicationInfo().icon;
// NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
// .setContentTitle("Время намаза")
// .setContentText(prayerName + ": " + prayerTime)
// .setSmallIcon(appIcon)
// .setContentIntent(pendingIntent) // Прикрепляем Intent, если он есть
// .setPriority(NotificationCompat.PRIORITY_HIGH) // Высокий приоритет для уведомлений
// .setAutoCancel(true); // Уведомление исчезнет после нажатия
// // Отправляем уведомление с уникальным ID для уведомлений о намазе
// try {
// NotificationManagerCompat.from(this).notify(PRAYER_NOTIFICATION_ID, builder.build());
// Log.d(TAG, "PrayerBackgroundService: Уведомление отправлено (ID: " + PRAYER_NOTIFICATION_ID + ").");
// } catch (SecurityException e) {
// Log.e(TAG, "PrayerBackgroundService: SecurityException при отправке уведомления. Требуется разрешение POST_NOTIFICATIONS (API 33+)?", e);
// } catch (Exception e) {
// Log.e(TAG, "PrayerBackgroundService: Неизвестная ошибка при отправке уведомления.", e);
// }
// }
// private Class<?> getMainActivityClass() {
// // Используем полный путь, как указано в вашем манифесте
// String fullMainActivityPath = "io.kodular.chechnya360.ghghg.Screen1";
// try {
// Log.d(TAG, "Пытаемся загрузить класс MainActivity: " + fullMainActivityPath);
// return Class.forName(fullMainActivityPath);
// } catch (ClassNotFoundException e) {
// Log.e(TAG, "PrayerBackgroundService: Класс MainActivity '" + fullMainActivityPath + "' не найден.", e);
// return null; // Возвращаем null, если класс не найден
// }
// }
// }
// --- ИСПРАВЛЕНО: Добавлен BroadcastReceiver для обработки перезагрузки устройства ---
// class BootReceiver extends BroadcastReceiver {
// private static final String TAG = "BootReceiver";
// @Override
// public void onReceive(Context context, Intent intent) {
// Log.d(TAG, "onReceive() вызван. Action: " + intent.getAction());
// if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
// Log.d(TAG, "Received BOOT_COMPLETED. Rescheduling AlarmManager.");
// Context appContext = context.getApplicationContext();
// if (appContext != null) {
// Intent serviceIntent = new Intent(appContext, PrayerBackgroundService.class);
// serviceIntent.setAction("com.muslimapp.ACTION_ALARM_TRIGGER"); // Действие, совпадающее с Muslimapp
// int pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// pendingIntentFlags |= PendingIntent.FLAG_IMMUTABLE;
// }
// PendingIntent pendingIntent = PendingIntent.getService(appContext, 100, serviceIntent, pendingIntentFlags); // Тот же requestCode, что и в Muslimapp
// AlarmManager alarmManager = (AlarmManager) appContext.getSystemService(Context.ALARM_SERVICE);
// if (alarmManager != null) {
// // Устанавливаем будильник примерно через 1 минуту после загрузки
// alarmManager.setInexactRepeating(
// AlarmManager.RTC_WAKEUP,
// System.currentTimeMillis() + 60000, // 1 минута задержки
// AlarmManager.INTERVAL_DAY,
// pendingIntent
// );
// Log.d(TAG, "AlarmManager установлен после BOOT_COMPLETED.");
// } else {
// Log.e(TAG, "AlarmManager is null after BOOT_COMPLETED.");
// }
// } else {
// Log.e(TAG, "AppContext is null, cannot reschedule AlarmManager after BOOT_COMPLETED.");
// }
// } else {
// Log.d(TAG, "Received unknown action: " + intent.getAction());
// }
// }
// }