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) 不会唤醒设备发送闹钟。相反,如果它在设备休眠时过期,它将在设备下次唤醒时传送。
  • 1000triggerAtMillis 值请求设备启动后 1 秒的第一个警报。如果设备已经启动并且 运行 并且您请求此警报,则第一个警报可能不会触发并可能导致后续警报无法安排。这只是一个猜测,我没有通过查看 4.4.4 AOSP 源代码进行验证

在 API 19 (Android 4.4) 中更改了警报处理以处理警报计时器的整理(默认情况下都是不准确的)并且此更改可能会影响第二个项目符号的内容。您可以尝试将 triggerAtMillis 值更改为 (SystemClock.elapsedRealtime() + 1000)

请注意,如果您需要设备从睡眠中唤醒,您将需要使用 _WAKEUP 闹钟变体,并让您的 BroadcastReceiver 使用唤醒锁,您的 ServiceActivity 处理完警报后释放。

尝试以下操作:

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;