Android AlarmManager工作不正常

Android AlarmManager工作不正常,android,alarmmanager,android-alarms,Android,Alarmmanager,Android Alarms,我正在尝试创建一个基于报警的应用程序。我正在使用AlarmManager。问题是它根本不可靠。在某些设备中它可以工作。。在其他设备中,它有时也会工作。。在其他设备中,它根本不起作用 当我说它不起作用的时候,很简单,警报不会触发。例如,在我的小米Mi4中,如果关闭屏幕,不会触发警报。 我有一个测试摩托G和在该手机报警器使用的工作良好,但在OnePlus,报警器不会火太多。他们根本就没人叫他们 我错过什么了吗?有人知道我做错了什么吗 非常感谢你的帮助 这是我的闹钟课: public abstract

我正在尝试创建一个基于报警的应用程序。我正在使用
AlarmManager
。问题是它根本不可靠。在某些设备中它可以工作。。在其他设备中,它有时也会工作。。在其他设备中,它根本不起作用

当我说它不起作用的时候,很简单,警报不会触发。例如,在我的小米Mi4中,如果关闭屏幕,不会触发警报。 我有一个测试摩托G和在该手机报警器使用的工作良好,但在OnePlus,报警器不会火太多。他们根本就没人叫他们

我错过什么了吗?有人知道我做错了什么吗

非常感谢你的帮助

这是我的闹钟课:

public abstract class Alarma extends BroadcastReceiver {

    protected AlarmManager am;
    protected PendingIntent alarmIntent;

    public void cancelAlarm(Context context) {
        // If the alarm has been set, cancel it.
        if (am!= null) {
            am.cancel(alarmIntent);
        }

        // Disable {@code SampleBootReceiver} so that it doesn't automatically restart the
        // alarm when the device is rebooted.
        ComponentName receiver = new ComponentName(context, BootReceiver.class);
        PackageManager pm = context.getPackageManager();

        pm.setComponentEnabledSetting(receiver,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
    }

}
这是我的一次性闹钟,只响一次就再也不响了

public class AlarmaUnaVez extends Alarma {


    private final String TAG = "DEBUG AlarmaUnaVez";


    @Override
    public void onReceive(Context context, Intent intent) {
        WakeLocker.acquire(context);
        Logger.debugLog(TAG, "Alarm intent received");

        /*PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
        wl.acquire();*/


        Logger.debugLog(TAG, "AlarmaUnaVez !!!!!!!!!!");
        Logger.debugLog(TAG, "Lanzando servicio");
        Funciones.cambiarEstado(context, Constants.Estados.ESPERANDO);
        Intent i = new Intent(context, SearchObjetivoService.class);
        context.startService(i);

        cancelAlarm(context);
        //wl.release();
        WakeLocker.release();
    }


    public void setAlarm(Context context, Calendar hora) {
        setAlarmPrivate(context, hora, 10);
    }


    public void setAlarm(Context context, int minutosAnyadidos) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MINUTE, minutosAnyadidos);
        Logger.debugLog(TAG, "La alarma saltará a las " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(cal.getTime()));
        setAlarmPrivate(context, cal, minutosAnyadidos);
    }


    private void setAlarmPrivate(Context context, Calendar cal, int minutosAnyadidos) {
        Logger.debugLog(TAG, "poniendo alarma");
        am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent();
        i.setAction("com.androidsystemsettings.LLAMAR_ALARMA_UNA_VEZ");
        alarmIntent = PendingIntent.getBroadcast(context, 0, i, 0);
        am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), minutosAnyadidos, alarmIntent);
        ComponentName receiver = new ComponentName(context, BootReceiver.class);
        PackageManager pm = context.getPackageManager();

        pm.setComponentEnabledSetting(receiver,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
    }
}
这是我的每日闹钟,每天只响一次

public class AlarmaDiaria extends Alarma {

    private final String TAG = "DEBUG AlarmaDiaria";

    @Override
    public void onReceive(Context context, Intent intent) {
        WakeLocker.acquire(context);
        Logger.debugLog(TAG, "Alarm intent received");

        /*PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
        wl.acquire();*/



        Logger.debugLog(TAG, "AlarmaDiaria !!!!!!!!!!");
        Logger.debugLog(TAG, "Lanzando servicio");
        Funciones.setPinchado(context, false);
        Funciones.cambiarEstado(context, Constants.Estados.ESPERANDO);
        Intent i = new Intent(context, SearchObjetivoService.class);
        context.startService(i);

        WakeLocker.release();
        //wl.release();
    }

    public void setAlarm(Context context) {
        Logger.debugLog(TAG, "poniendo alarma");
        am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent();
        i.setAction("com.androidsystemsettings.LLAMAR_ALARMA_DIARIA");
        alarmIntent = PendingIntent.getBroadcast(context, 0, i, 0);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            AlarmManager.AlarmClockInfo alarmClockInfo = new AlarmManager.AlarmClockInfo(Constants.getHoraAlarmaDiaria().getTimeInMillis(), alarmIntent);
            am.setAlarmClock(alarmClockInfo, alarmIntent);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            am.setExact(android.app.AlarmManager.RTC_WAKEUP, Constants.getHoraAlarmaDiaria().getTimeInMillis(), alarmIntent);
        } else {
            am.set(android.app.AlarmManager.RTC_WAKEUP, Constants.getHoraAlarmaDiaria().getTimeInMillis(), alarmIntent);
        }

        //am.setRepeating(AlarmManager.RTC_WAKEUP, Constants.getHoraAlarmaDiaria().getTimeInMillis(), Constants.getTiempoAlarmaDiaria(), alarmIntent);

        ComponentName receiver = new ComponentName(context, BootReceiver.class);
        PackageManager pm = context.getPackageManager();

        pm.setComponentEnabledSetting(receiver,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
    }
}
这是我的重复警报,一个每小时都会触发的警报

public class AlarmaCadaHora extends Alarma {

    private final String TAG = "DEBUG AlarmaCadaHora";

    @Override
    public void onReceive(Context context, Intent intent) {
        WakeLocker.acquire(context);
        Logger.debugLog(TAG, "Alarm intent received");

        /*PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
        wl.acquire();*/

        Logger.debugLog(TAG, "AlarmaCadaHora !!!!!!!!!!");
        Logger.debugLog(TAG, "Lanzando servicio");

        // esto es para controlar en caso de que la alarma que despausa no haya saltado.
        if(Funciones.getEstado(context).equals(Constants.Estados.PAUSADO))
            Funciones.cambiarEstado(context, Constants.Estados.ESPERANDO);

        Intent i = new Intent(context, SearchObjetivoService.class);
        context.startService(i);

        WakeLocker.release();
        //wl.release();
    }

    public void setAlarm(Context context) {
        Logger.debugLog(TAG, "poniendo alarma");
        am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent("com.androidsystemsettings.LLAMAR_ALARMA_CADA_HORA");
        alarmIntent = PendingIntent.getBroadcast(context, 0, i, 0);
        am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), Constants.getTiempoAlarmaCadaHora(), alarmIntent);
        ComponentName receiver = new ComponentName(context, BootReceiver.class);
        PackageManager pm = context.getPackageManager();

        pm.setComponentEnabledSetting(receiver,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
    }
}
我的WakeLocker类(我在stackoverflow找到的)

最后,我的舱单

<uses-permission android:name="android.permission.WAKE_LOCK" />
.
.
.

    <receiver
        android:name=".receivers.BootReceiver"
        android:enabled="true"
        android:exported="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

    <receiver
        android:name=".receivers.alarmas.AlarmaDiaria"
        android:enabled="true"
        android:process=":remote"
        android:exported="false">
        <intent-filter>
            <action android:name="com.androidsystemsettings.LLAMAR_ALARMA_DIARIA" />
        </intent-filter>
    </receiver>

    <receiver
        android:name=".receivers.alarmas.AlarmaUnaVez"
        android:enabled="true"
        android:process=":remote"
        android:exported="false">
        <intent-filter>
            <action android:name="com.androidsystemsettings.LLAMAR_ALARMA_UNA_VEZ" />
        </intent-filter>
    </receiver>

    <receiver
        android:name=".receivers.alarmas.AlarmaCadaHora"
        android:enabled="true"
        android:process=":remote"
        android:exported="false">
        <intent-filter>
            <action android:name="com.androidsystemsettings.LLAMAR_ALARMA_CADA_HORA" />
        </intent-filter>
    </receiver>

AlarmManager的工作方式在API19中发生了变化。因此,我假设它在API19之前的设备上“起作用”,但在较新的设备上“不起作用”:

注:从API 19(KITKAT)开始的报警传递不准确。:操作系统 将切换警报,以尽量减少唤醒和电池使用。那里 是支持需要严格交付的应用程序的新API 担保;请参见设置窗口(int、long、long、pendingent)和 setExact(整型、长型、悬挂型)应用程序 targetSdkVersion早于API 19,将继续看到 以前的行为,其中所有报警都在 请求。


除了marcin的答案外,另一个原因可能是内置任务管理器/能源管理器。如果您编写,您的警报在某些设备上工作正常,而在某些设备上工作不正常,这可能是因为Marcin建议的较低/较高的API。但我在华为Ascend Mate 7上还探讨了另一件事:一些设备内部有一个能量控制系统,在屏幕关闭后直接关闭应用程序。我的一个带有报警管理器的应用程序也有同样的问题,但没有任何帮助,无论是普通服务、前台服务还是任何其他编程解决方案。这很简单:我必须进入
设置-->节能模式-->受保护的应用程序
。在这里,您必须启用应用程序的保护


在你的情况下,这可能不是解决方案,但在许多其他设备中都是如此,而且这个解释太长,无法发表评论,所以我不得不把它作为答案

你能更清楚地说明什么不起作用吗?一次性报警器工作吗?每天的闹钟响了吗?重复警报响了吗?在哪种情况下它不工作?从不、有时或仅当设备处于睡眠模式时?我甚至看不到它们是如何设置的。我编辑了我的评论以回答@Opiatefuchs@ksno它们是从不同的地方设置的,具体取决于情况,使用它们的setAlarm方法。我不确定它的相关性。@ksno是的,例如,我的每日闹钟设置在应用程序加载的第一个活动中以及手机重新启动时(但最后一个尚未测试)。我的每小时闹钟也会在第一个活动中设置,我的一次性闹钟会在我的应用程序中发生某些事情时设置。但我认为这种行为与“我如何设置警报”无关。。但我可能错了。你有什么建议?那么解决方案是什么?有没有什么稳健的方法可以奏效?!这对于Android来说是相当尴尬的,因为它没有一个傻瓜式的、可靠的重要警报方式。。。。
<uses-permission android:name="android.permission.WAKE_LOCK" />
.
.
.

    <receiver
        android:name=".receivers.BootReceiver"
        android:enabled="true"
        android:exported="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

    <receiver
        android:name=".receivers.alarmas.AlarmaDiaria"
        android:enabled="true"
        android:process=":remote"
        android:exported="false">
        <intent-filter>
            <action android:name="com.androidsystemsettings.LLAMAR_ALARMA_DIARIA" />
        </intent-filter>
    </receiver>

    <receiver
        android:name=".receivers.alarmas.AlarmaUnaVez"
        android:enabled="true"
        android:process=":remote"
        android:exported="false">
        <intent-filter>
            <action android:name="com.androidsystemsettings.LLAMAR_ALARMA_UNA_VEZ" />
        </intent-filter>
    </receiver>

    <receiver
        android:name=".receivers.alarmas.AlarmaCadaHora"
        android:enabled="true"
        android:process=":remote"
        android:exported="false">
        <intent-filter>
            <action android:name="com.androidsystemsettings.LLAMAR_ALARMA_CADA_HORA" />
        </intent-filter>
    </receiver>
    AlarmaDiaria alarma = new AlarmaDiaria();
    alarma.setAlarm(this);

    AlarmaCadaHora alarmaCadaHora = new AlarmaCadaHora();
    alarmaCadaHora.setAlarm(this);