警报管理器无法正常工作 [英] AlarmManager not working properly

查看:44
本文介绍了警报管理器无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to create an alarm based application. I'm using AlarmManager. The thing is that it's not reliable at all. In some devices it works.. in other devices it works somethimes.. and in other devices it doesn't work at all.

当我说它不起作用时,很简单,警报不会触发.比如我的小米4,关了屏幕就不会闹钟了.我有一个测试 Moto G 并且在那个电话警报中使用正常工作,但在 OnePlus 中,警报也不会触发.他们根本就不会被调用.

When I say that it doesn't work is that simply, alarms won't fire. For example, in my Xiaomi Mi4, if you turn off the screen, no alarm will fire. I have a testing Moto G and in that phone alarms use to work fine, but in OnePlus, alarms won't fire too. They simply are never called.

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

Am I missing something? Does anybody know what am I doing wrong??

非常感谢您的帮助!

这是我的警报类:

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);
    }

}

这是我的 OneTimeAlarm,闹钟只触发一次,然后不再触发.

This is my OneTimeAlarm, alarm that fires just once and then it doesn't fire again.

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);
    }
}

这是我的每日闹钟,每天只触发一次.

This is my daily alarm, alarm that fires just once a day.

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);
    }
}

这是我的重复闹钟,一个每小时响一次的闹钟.

This is my repeating alarm, an alarm that fires every hour.

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 上找到了它).

My WakeLocker class (i found it here at stackoverflow).

public abstract class WakeLocker {

    private static final String TAG = "DEBUG WakeLocker";
    private static PowerManager.WakeLock wakeLock;

    public static void acquire(Context ctx) {
        if (wakeLock != null) wakeLock.release();

        PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
                PowerManager.ACQUIRE_CAUSES_WAKEUP |
                PowerManager.ON_AFTER_RELEASE, TAG);
        wakeLock.acquire();
    }

    public static void release() {
        if (wakeLock != null) wakeLock.release();
        wakeLock = null;
    }

}

最后,我的清单..

<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>

这就是我设置闹钟的方式,例如,在活动中.

And this is how I set alarms, for example, inside of an activity.

    AlarmaDiaria alarma = new AlarmaDiaria();
    alarma.setAlarm(this);

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

推荐答案

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

In addition to marcin´s answer, another reason could be a build in task-manager/energy-manager. If you write, your alarm works fine on some devices and in some not, it could be because of lower/higher APIs like Marcin suggested. But there is another thing that I have explored on my Huawei Ascend Mate 7: Some devices have an energy control system inside that directly closes the application completely after screen goes off. I had the same problem with one of my apps with an alarm manager and nothing helped, wether a usual service nor a foreground service nor any other programming solution. It was just simple: I had to go to settings-->energy saving mode-->protected apps. Here you have to enable the protection of your app.

这可能不是您的情况的解决方案,但它在许多其他设备中存在,并且此解释太长而无法发表评论,因此我必须将其作为答案.

It may be that this is not the solution in Your case, but it is in much other devices and this explanation is too long for a comment, so I have to put it as answer.

这篇关于警报管理器无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆