Мое приложение использует AlarmManager и работает 4 года назад. Но заметил, что на некоторых устройствах он начал глючить.
Я почти уверен, что код правильный (я использую WakefulBroadcastReceiver и setExactAndAllowWhileIdle для устройств с Doze), потому что он отлично работает на устройствах Nexus, но не работает на устройствах некоторых производителей (Huawei, Xiaomi ...).
Например, в устройствах Huawei есть своего рода диспетчер батареи, который убивает приложения, а когда приложение прекращается, запланированные будильники отменяются. Таким образом, установка приложения в качестве «защищенного» в диспетчере батарей Huawei решает проблему.
Но недавно я заметил, что он не работает с другими устройствами: Xiaomi, Samsung (может быть, это связано с новым «Умным менеджером»?) ... Похоже, такое поведение становится стандартом: убивать фоновые приложения.
Кто-нибудь знает что-нибудь об этом? Есть ли способ обеспечить срабатывание сигнализации?
РЕДАКТИРОВАТЬ: эта проблема вызвана «экономичными батареями», добавленными разными производителями. Подробнее здесь: https://dontkillmyapp.com/
источник
Ответы:
Уже несколько недель пытаюсь решить. Ничего не нашел. Huawei просто убьет все тревоги через какое-то время. Если я помещаю приложение в защищенное приложение в режиме экономии заряда батареи, это не помогает. Но если я изменю имя пакета своего приложения, чтобы оно содержало такие слова, как будильник, часы или календарь, оно будет работать совершенно нормально, как на любых других устройствах. Я не понимаю, как Google может давать сертификаты на эту хрень. Я считаю, что OEM не должен модифицировать базовую платформу таким образом. Я понимаю, что у них есть собственная заставка, которая убивает приложение через некоторое время, когда пользователь его не использует. Но это убивает тревогу и защищенных приложений.
Также помогает setAlarmClock () для точных сигналов времени. Но это невозможно использовать для таких мыслей, как обновление виджета.
Обновление: защита по ключевым словам имени пакета уже не работает на текущих устройствах Huawei, это было верно в 2017 году.
источник
Проблема в Smart Manager. У Samsung есть диспетчер батареи, который иногда отключает работу определенных приложений в фоновом режиме. Он пытался «возобновить» при возврате в приложение, но полностью отключает приложение или может возобновлять работу каждые 5 минут или около того (в зависимости от того, как у Samsung).
Это будет работать на стандартных версиях Android, так как Samsung Manager отсутствует. Вы также можете установить специальную версию Android, в которой есть некоторые функции для включения SM (в зависимости от ROM).
источник
Большинство современных Android-устройств поставляются с приложением или механизмом, который автоматически пытается выяснить, как сэкономить заряд батареи, и в результате может убить некоторые сторонние приложения. Это может привести к удалению запланированных задач и заданий (например, не срабатывают будильники, не работают push-уведомления и т. Д.). Во многих случаях это происходит совершенно независимо от механизмов экономии заряда батареи Android, в моем случае я не мог больше оптимизировать батарею, когда обнаруживаю какую-то модель устройства, я перенаправляю пользователя в менеджер запуска, чтобы внести мое приложение в белый список
Вы нашли в этой ссылке для каждой модели намерение, которое вы должны вызвать https://android-arsenal.com/details/1/6771
источник
Используйте AlarmManager для устройств <5.0 и JobScheduler для устройств 5.0+. Я не могу с уверенностью сказать, что на JobScheduler не повлияют махинации производителя, но мне это кажется гораздо менее вероятным, учитывая, что Android пытается переместить людей из AlarmManager в JobScheduler.
РЕДАКТИРОВАТЬ: Google представил собственное решение этой проблемы под названием WorkManager . Он абстрагирует несколько структур планирования и использует наиболее подходящую для устройства.
источник
У меня также есть приложение, которое устанавливает будильники. Решение состоит в том, чтобы использовать AlarmManager.setAlarmClock () на api> = 21. Это не зависит от doze afaik и имеет дополнительный бонус в виде размещения значка будильника на панели задач.
источник
в настоящее время большинство новых телефонов поставляются в комплекте с каким-либо менеджером по энергосбережению / батарее, который выполняет то же действие, что вы описали. не считая дубустеров и чистых мастеров.
Я думаю, вам нужно поместить отказ от ответственности или часто задаваемые вопросы в свой список приложений / игр в магазине, в котором говорится, что это приложение необходимо поместить в исключение вашего приложения для управления батареями, чтобы оно работало должным образом.
источник
я перестал использовать AlarmManager некоторое время назад ... лучшая и более стабильная альтернатива
да .. это боль .. но работа сделана НЕ ВАЖНО ЧТО
источник
Вы слушаете BOOT_COMPLETED? Вам нужно снова установить будильник при перезагрузке устройства.
источник
Какая версия Android работает на этих устройствах?
Начиная с API 23, сама ОС переходит в режим ожидания с низким энергопотреблением, если она некоторое время не использовалась, и в этом режиме не будут доставляться сигналы тревоги. Однако есть способ для приложений явно сказать: «Мне нужно, чтобы этот будильник сработал в это время независимо от использования батареи»; новые методы AlarmManager называются
setAndAllowWhileIdle()
иsetExactAndAllowWhileIdle()
.Судя по вашему описанию, это не может быть конкретной причиной ваших проблем на устройствах некоторых OEM-производителей, но это то, о чем должны знать все разработчики, использующие Alarm Manager.
Наконец, многие случаи использования диспетчера аварийных сигналов лучше решаются с помощью механизмов планировщика заданий. Для обратной совместимости Play Services "GCM Network Manager" на самом деле очень близок к планировщику заданий по функциональности - он использует планировщик заданий внутри в новых версиях Android - и не обязательно связан с сетью, несмотря на название класса.
источник
Я не думаю, что удаление приложения помешает диспетчеру сигналов тревоги разбудить ваше приложение.
Только когда вы «принудительно останавливаете» или отключаете приложение, вы не получаете обратных звонков от диспетчера тревог.
Основная причина может быть в другом.
Также на M ... setExactAndAllowWhileIdle дросселируется ... то есть, если вы планируете будильник каждые 2 минуты, он не сработает. .. Должно быть окно 15 минут. .
источник
Для Xiaomi вам может потребоваться включить AutoStart для вашего приложения. Я пытаюсь внести изменения в список модификаций Android (обычно от производителя телефона), которые могут повлиять на фоновый процесс. Если у вас есть что-то новенькое, пожалуйста, добавьте сюда ответ. Список средств убийства Android.
источник
Нам нужно включить наше приложение в диспетчере автозапуска в диспетчере приложений, на некоторых телефонах, таких как vivo v5,
В vivo v5 это меню можно найти в iManager -> Диспетчер приложений -> Диспетчер автозапуска. Включите наше приложение здесь.
Тогда ваш будильник / менеджер будильника вызовет тревогу, если приложение будет убито или закрыто.
источник
Я искал ответ и через несколько часов нашел вот что:
https://stackoverflow.com/a/35220476/3174791
В резюме есть способ узнать, было ли ваше приложение убито «Защищенными приложениями», и это работает только на устройствах Huawei. дайте мне знать, есть ли какое-либо решение для других устройств (Samsung, Sony, Xiaomi и т. д.).
источник
Это может быть поздно, но я надеюсь, что это кому-то поможет.
Я так долго зацикливался на одной и той же проблеме. Но теперь я знаю, как решить эту проблему. Это для всех, у кого может быть такая же проблема. Люди продолжают говорить, что вы должны включить AutoStart, но мне удалось это сделать без использования автоматического запуска.
Во-первых, WakeFullBroadcastaReceiver устарел, и вам следует использовать BroadcastReceiver. Во-вторых, вы должны использовать ForegroudService вместо BackgroundService.
Я дам вам следующий пример:
IntentService.class
public class NotificationService extends IntentService { //In order to send notification when the app is close //we use a foreground service, background service doesn't do the work. public NotificationService() { super("NotificationService"); } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); //There is no difference in the result between start_sticky or start_not_sticky at the moment return START_NOT_STICKY; } @Override protected void onHandleIntent(@Nullable Intent intent) { //TODO check if the app is in foreground or not, we can use activity lifecyclecallbacks for this startForegroundServiceT(); sendNotification(intent); stopSelf(); } /*** * you have to show the notification to the user when running foreground service * otherwise it will throw an exception */ private void startForegroundServiceT(){ if (Build.VERSION.SDK_INT >= 26) { String CHANNEL_ID = "my_channel_01"; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Channel human readable title", NotificationManager.IMPORTANCE_DEFAULT); ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel); Notification notification = new Notification.Builder(this, CHANNEL_ID) .setContentTitle("") .setContentText("").build(); startForeground(1, notification); } } private void sendNotification(Intent intent){ //Send notification //Use notification channle for android O+ } }
запустить службу переднего плана в BroadcastReceiver.class
public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent service = new Intent(context, NotificationService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundService(service); } else { context.startService(service); } } }
А вот setAlarms такой:
public static void setAlarm(Context context, int requestCode, int hour, int minute){ AlarmManager alarmManager =( AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context//same activity should be used when canceling the alarm , AlarmReceiver.class); intent.setAction("android.intent.action.NOTIFY"); //setting FLAG_CANCEL_CURRENT makes some problems. and doest allow the cancelAlarm to work properly PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1001, intent, 0); Calendar time = getTime(hour, minute); //set Alarm for different API levels if (Build.VERSION.SDK_INT >= 23){ alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pendingIntent); } else{ alarmManager.set(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pendingIntent); }
Затем вы должны объявить получателя и службу переднего плана в манифесте.
<receiver android:name=".AlarmReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.NOTIFY"> </action> </intent-filter> </receiver> <service android:name=".NotificationService" android:enabled="true" android:exported="true"></service>
Я надеюсь, что это помогает кому-то.
источник