Android AlarmManager останавливается, когда активность умирает
Я запускаю AlarmManager с PendingIntent, и на нескольких телефонах Alarm не отвечает. На некоторых устройствах работает нормально, на других происходит сбой. Я сделал несколько тестов на разных телефонах.
Нексус работает нормально, также Samsung Galaxy S4 zoom (4.2) работает нормально.
Samsung note 2 (4.3) работает нормально.
OPPO (4.4.4) умирает.
Я также внедрил вещательные приемники, которые работают как надо на всех устройствах.
Log.v(TAG, "START ALARM");
Intent intentAlarm = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, 1000, 5000, pendingIntent);
9 ответов
Проверьте, находится ли приложение в остановленном состоянии. Когда приложение находится в остановленном состоянии, оно не будет получать никаких сигналов тревоги или событий.
Кроме того, я полагаю, что это может быть проблема с прошивкой / ОС для конкретного производителя / производителя. Чтобы проверить, действительно ли расписание было запланировано, используйте adb shell dumpsys alarm и проверьте, действительно ли ваше приложение было запланировано.
Чтобы проверить, находится ли он в остановленном состоянии, используйте следующую команду:
Оболочка adb создает пакет "com.package.name" и проверяет " stop =true"
Чтобы узнать больше о остановленном состоянии, обратитесь:
Launch controls on stopped applications
Starting from Android 3.1, the system's package manager keeps track of applications that are in a stopped state and provides a means of controlling their launch from background processes and other applications.
Note that an application's stopped state is not the same as an Activity's stopped state. The system manages those two stopped states separately.
The platform defines two new intent flags that let a sender specify whether the Intent should be allowed to activate components in stopped application.
FLAG_INCLUDE_STOPPED_PACKAGES — Include intent filters of stopped applications in the list of potential targets to resolve against.
FLAG_EXCLUDE_STOPPED_PACKAGES — Exclude intent filters of stopped applications from the list of potential targets.
When neither or both of these flags is defined in an intent, the default behavior is to include filters of stopped applications in the list of potential targets.
Note that the system adds FLAG_EXCLUDE_STOPPED_PACKAGES to all broadcast intents. It does this to prevent broadcasts from background services from inadvertently or unnecessarily launching components of stoppped applications. A background service or application can override this behavior by adding the FLAG_INCLUDE_STOPPED_PACKAGES flag to broadcast intents that should be allowed to activate stopped applications.
Applications are in a stopped state when they are first installed but are not yet launched and when they are manually stopped by the user (in Manage Applications).
Обратите внимание, что остановленное состояние отличается от не запущенного процесса приложения.
Здесь может быть несколько разных проблем:
- Тип сигнала тревоги, который вы запрашиваете (
ELAPSED_REALTIME
) не разбудит устройство для доставки будильника. Вместо этого, если срок его действия истекает, когда устройство находится в спящем режиме, оно будет доставлено при следующем пробуждении устройства. triggerAtMillis
ценность1000
запрашивает первый сигнал тревоги через 1 секунду после загрузки устройства. Если устройство уже запущено и работает, и вы запрашиваете этот сигнал тревоги, первый сигнал тревоги может не сработать и может привести к тому, что последующие не будут запланированы. Это всего лишь предположение, я не проверил, посмотрев источники 4.4.4 AOSP
Обработка аварийных сигналов была изменена в API 19 (Android 4.4), чтобы обрабатывать сортировку таймеров аварийных сигналов (по умолчанию все они неточны), и это изменение могло повлиять на вещи для 2-го пункта. Вы можете попробовать изменить triggerAtMillis
ценность быть (SystemClock.elapsedRealtime() + 1000)
Обратите внимание, что если вам нужно, чтобы устройство выходило из спящего режима, вам необходимо использовать _WAKEUP
вариант тревоги, а также ваш BroadcastReceiver
взять замок, который ваш Service
или же Activity
освобождает, когда это сделано, обрабатывая сигнал тревоги.
Это только предположение, но я думаю, что проблема связана с API. Начиная с KitKat, система испортила AlarmManager. Возможно, попробуйте использовать что-то еще для систем в abd выше kitkat.
"Примечание. Начиная с API 19 (KITKAT), выдача аварийных сигналов не является точной: ОС будет сдвигать аварийные сигналы, чтобы свести к минимуму пробуждения и использование батареи. Появились новые API для поддержки приложений, которые требуют строгих гарантий доставки; см. SetWindow (int, long, long)., PendingIntent) и setExact(int, long, PendingIntent). Приложения, у которых targetSdkVersion более ранний, чем API 19, продолжат видеть предыдущее поведение, при котором все тревоги доставляются точно по запросу. "
Взято с http://developer.android.com/reference/android/app/AlarmManager.html
Ваши аварийные сигналы будут продолжать существовать после нормального закрытия приложения. Если он принудительно остановлен, или ваше устройство перезапущено, или установлено обновление для вашего приложения, или ваше приложение удалено, они будут потеряны. Вы можете создать BroadcastReceivers
для некоторых из этих ситуаций, чтобы восстановить ваши тревоги.
Также, setInexactRepeating
именно так: неточно. Когда срабатывает этот сигнал тревоги, это зависит от реализации и не может быть точно предсказано.
Try this it works when activity is not running..
Calendar calendar = Calendar.getInstance();
long timemills = calendar.getTimeInMillis();
Intent myIntent = new Intent(this, TimeChangeReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, timemills, pendingIntent);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, timemills,
10000, pendingIntent);
Попробуйте следующее:
1) Добавьте разрешение Wake_lock в свой манифест.
<uses-permission android:name="android.permission.WAKE_LOCK">
2) Изменить
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, 1000, 5000, pendingIntent);
с
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000, 5000, pendingIntent);
Не могли бы вы показать нам код AlarmReceiver.class? Может быть, вам нужно использовать return START_STICKY;
на ваш метод onStartCommand?
Я также использовал сигнализацию в моем проекте для подготовительного задания за 6 или 7 минут. И работает нормально на всех телефонах.
Я сделал службу сигнализации, как это:
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import android.util.Log;
public class MyAlarmService {
private static PendingIntent resetAlarm;
private static String TAG="CellPoliceChildGPSAlarmService";
private static AlarmManager am;
public static void start(Context context) {
try {
// We want the alarm to go off 30 seconds from now.
long firstTime = SystemClock.elapsedRealtime();
// Create an IntentSender that will launch our service, to be scheduled with the alarm manager.
//resetAlarm = PendingIntent.getService(context, 0, new Intent(context, Get_NonRootDetails.class), 0);
resetAlarm = PendingIntent.getService(context, 0, new Intent(context, CallNonRBackgroundService.class), 0);
// Schedule the alarm!
am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Log.i(TAG, firstTime+"");
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, 10*1000*60, resetAlarm);
}
catch (Exception e) {
Log.v("CellInfo", "Exception while start the MyAlarmService at: " + e.getMessage());
}
}
public static void stop(Context context) {
try {
// When interval going to change from web services
am.cancel(resetAlarm);
}
catch (Exception e) {
Log.v("CellInfo", "Exception while start the MyAlarmService at: " + e.getMessage());
}
}
}
Я звонил или начинаю так;
MyAlarmService.start(SplashActivity.this);
Дано разрешение в Манифесте:
<uses-permission android:name="android.permission.WAKE_LOCK">
<service
android:name="com.secure.DataCountService"
android:enabled="true" >
<intent-filter>
<action android:name="com.secure.MyService" />
</intent-filter>
</service>
Для уведомлений я также использовал ожидающие намерения, такие как;
Intent notificationIntent = new Intent(context, DashBoardActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, PushNotificationUtils.notiMsg, pendingIntent);
notification.flags |= notification.FLAG_AUTO_CANCEL;