Android AlarmManager 在 activity 死亡时停止
Android AlarmManager stops when activity die
我使用 PendingIntent 启动 AlarmManager,但在少数手机上,Alarm 没有响应。在某些设备上运行正常,但在其他设备上运行失败。我在不同的手机上做了一些测试。
Nexus 正常,Samsung Galaxy S4 zoom (4.2) 也正常。
三星 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);
这只是一个猜测,但我认为问题与 API 有关。从 KitKat 开始,系统搞乱了 AlarmManager。也许考虑尝试在 abd kitkat 以上的系统中使用其他东西。
"Note: Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested. "
取自http://developer.android.com/reference/android/app/AlarmManager.html
这里可能有几个不同的问题:
- 您请求的闹钟类型 (
ELAPSED_REALTIME
) 不会唤醒设备发送闹钟。相反,如果它在设备休眠时过期,它将在设备下次唤醒时传送。
-
1000
的 triggerAtMillis
值请求设备启动后 1 秒的第一个警报。如果设备已经启动并且 运行 并且您请求此警报,则第一个警报可能不会触发并可能导致后续警报无法安排。这只是一个猜测,我没有通过查看 4.4.4 AOSP 源代码进行验证
在 API 19 (Android 4.4) 中更改了警报处理以处理警报计时器的整理(默认情况下都是不准确的)并且此更改可能会影响第二个项目符号的内容。您可以尝试将 triggerAtMillis
值更改为 (SystemClock.elapsedRealtime() + 1000)
请注意,如果您需要设备从睡眠中唤醒,您将需要使用 _WAKEUP
闹钟变体,并让您的 BroadcastReceiver
使用唤醒锁,您的 Service
或 Activity
处理完警报后释放。
尝试以下操作:
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 代码吗?
也许您需要在 onStartCommand 方法上使用 return START_STICKY;
?
检查应用程序是否处于停止状态state.When应用程序处于停止状态,不会收到任何警报或事件。
此外,我猜它可能是 OEM/manufacturer 具体的 firmware/OS issue.To 检查警报是否已实际调度使用 adb shell dumpsys alarm 并检查你的app alarm是否真的被调度了
要检查它是否处于停止状态,请使用以下命令:
adb shell dumpsys package "com.package.name" 并检查
"stopped=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).
请注意停止状态不同于应用程序进程而不是运行。
尝试将 AlarmManager 置于后台服务中。
您的应用程序正常关闭后,您的闹钟将继续存在。如果它被强制停止,或者您的设备重新启动,或者安装了您的应用程序更新,或者您的应用程序被卸载,它们将会丢失。您可以为其中一些情况创建 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);
我也曾在我的项目中使用 Alarm Service 在 6 或 7 分钟内完成准备任务。 运行 phone.
都很好
我有这样的报警服务:
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;
我使用 PendingIntent 启动 AlarmManager,但在少数手机上,Alarm 没有响应。在某些设备上运行正常,但在其他设备上运行失败。我在不同的手机上做了一些测试。
Nexus 正常,Samsung Galaxy S4 zoom (4.2) 也正常。
三星 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);
这只是一个猜测,但我认为问题与 API 有关。从 KitKat 开始,系统搞乱了 AlarmManager。也许考虑尝试在 abd kitkat 以上的系统中使用其他东西。
"Note: Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested. "
取自http://developer.android.com/reference/android/app/AlarmManager.html
这里可能有几个不同的问题:
- 您请求的闹钟类型 (
ELAPSED_REALTIME
) 不会唤醒设备发送闹钟。相反,如果它在设备休眠时过期,它将在设备下次唤醒时传送。 -
1000
的triggerAtMillis
值请求设备启动后 1 秒的第一个警报。如果设备已经启动并且 运行 并且您请求此警报,则第一个警报可能不会触发并可能导致后续警报无法安排。这只是一个猜测,我没有通过查看 4.4.4 AOSP 源代码进行验证
在 API 19 (Android 4.4) 中更改了警报处理以处理警报计时器的整理(默认情况下都是不准确的)并且此更改可能会影响第二个项目符号的内容。您可以尝试将 triggerAtMillis
值更改为 (SystemClock.elapsedRealtime() + 1000)
请注意,如果您需要设备从睡眠中唤醒,您将需要使用 _WAKEUP
闹钟变体,并让您的 BroadcastReceiver
使用唤醒锁,您的 Service
或 Activity
处理完警报后释放。
尝试以下操作:
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 代码吗?
也许您需要在 onStartCommand 方法上使用 return START_STICKY;
?
检查应用程序是否处于停止状态state.When应用程序处于停止状态,不会收到任何警报或事件。
此外,我猜它可能是 OEM/manufacturer 具体的 firmware/OS issue.To 检查警报是否已实际调度使用 adb shell dumpsys alarm 并检查你的app alarm是否真的被调度了
要检查它是否处于停止状态,请使用以下命令:
adb shell dumpsys package "com.package.name" 并检查 "stopped=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).
请注意停止状态不同于应用程序进程而不是运行。
尝试将 AlarmManager 置于后台服务中。
您的应用程序正常关闭后,您的闹钟将继续存在。如果它被强制停止,或者您的设备重新启动,或者安装了您的应用程序更新,或者您的应用程序被卸载,它们将会丢失。您可以为其中一些情况创建 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);
我也曾在我的项目中使用 Alarm Service 在 6 或 7 分钟内完成准备任务。 运行 phone.
都很好我有这样的报警服务:
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;