AlarmManager 无法正常工作

2023-11-25

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

当我说它不起作用时,很简单,警报不会响起。例如,在我的小米4中,如果关闭屏幕,则不会触发警报。 我有一个测试 Moto 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);
    }

}

这是我的 OneTimeAlarm,警报只触发一次,然后就不会再次触发。

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 找到它)。

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>

这就是我设置闹钟的方式,例如在活动内部。

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

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

除了马尔辛的回答之外,另一个原因可能是任务管理器/能源管理器的构建。如果您写道,您的闹钟在某些设备上工作正常,而在某些设备上则不然,这可能是因为像 Marcin 建议的那样较低/较高的 API。但我在华为 Ascend Mate 7 上探索的另一件事是:有些设备内部有一个能量控制系统,可以在屏幕关闭后直接完全关闭应用程序。我的一个带有警报管理器的应用程序也遇到了同样的问题,无论是常用服务、前台服务还是任何其他编程解决方案,都没有任何帮助。事情很简单:我必须去settings-->energy saving mode-->protected apps。在这里您必须启用应用程序的保护。

这可能不是您的情况的解决方案,但它在许多其他设备中都是如此,并且这个解释对于评论来说太长了,所以我必须将其作为答案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AlarmManager 无法正常工作 的相关文章

随机推荐

  • 在父视图的两侧放置两个具有wrap_content宽度的多行TextView

    请帮助我实现两个 TextView 的以下排列 左边是一个带有标题的简单 TextView 右边是另一个 TextView 左侧有一个 Drawable 这很重要 因为我不能使用它match parent 两个 TextView 都应该是w
  • 在 Bash 中解析日期

    如何在 bash 中解析日期 将不同的字段 年 月 日 小时 分钟 秒 转换为不同的变量 日期格式为 YYYY MM DD hh mm ss 一定要bash吗 您可以使用 GNU coreutils bin date许多转换的二进制 dat
  • 标准库中有执行原子操作的函数吗?

    C 运行时库或任何其他实用程序库是否支持用于执行原子操作 例如整数的递增 递减 等的函数 如果是 那么使用此类函数可以使哪些操作成为原子操作 使用此类函数会比互斥体等普通同步原语更有利吗 操作系统 Windows Linux Solaris
  • 如果“if”条件为 false,则语句不会在 chrome 中执行,但会在 Firefox 中执行

    这是我的场景的 plnkr 当我在 Chrome 中调试此代码时 第二个 if 中的语句未执行 但是当我在 Firefox 中调试它时 第二个 if 中的语句被执行 angular module optionsExample control
  • 允许重复的属性名称的目的是什么?

    我正在读MDN JavaScript 参考 因此下面的代码不再返回false function haveES6DuplicatePropertySemantics use strict try prop 1 prop 2 No error
  • Android Instant App:找不到默认活动

    这似乎是明显的合并错误 我正在尝试将现有代码移植到即时应用程序模块 我尝试过的是 将主应用程序模块更改为 baseFeatureModule 创建了一个新模块completeApp 清空completeAppModule的Manifest
  • pandas 将数据框中的多列字符串转换为浮点数

    我是 pandas 的新手 并试图弄清楚如何将格式化为字符串的多个列转换为 float64 目前我正在执行以下操作 但似乎 apply 或 applymap 应该能够更有效地完成此任务 不幸的是 我有点菜鸟无法弄清楚如何 目前 这些值是百分
  • 无需 webRTC 即可访问相机或网络摄像头

    在我的网站中 它需要访问相机或网络摄像头 但基于ios的webview尚不支持webRTChttps forums developer apple com thread 88052 请cmiiw 所以 我正在尝试找到一种无需 webRTC
  • R 中的条件和

    我有一个 200 行 x 6 列的数据框 我感兴趣的是计算 A 列中的值小于特定数字的总次数 该数字可以被硬编码 我不知道从哪里开始 对于稍微复杂一点的问题 使用 which 来告诉 sum 在哪里求和 如果 DF 是数据框 Ozone S
  • 什么是 UICalloutBarButton,为什么它会使我的应用程序崩溃?

    我正在查看我的 iPhone 应用程序的一些崩溃报告 但我对以下内容感到困惑 它很可能在我的代码中的某个地方崩溃 它可能是一个事件处理程序在某个地方调用了错误的选择器 问题是我不知道这段代码在哪里 我不知道 UICalloutBarButt
  • 如何修复预期启动联盟。在命令行上将 JSON 转换为 Avro 时得到 VALUE_NUMBER_INT?

    我正在尝试使用 Avro 架构验证 JSON 文件并写入相应的 Avro 文件 首先 我定义了以下 Avro 架构 名为user avsc namespace example avro type record name user field
  • 在 CodeIgniter 中使用多个数据库

    场景 我正在构建一个 Web 应用程序 它使用 ion auth 来管理所有用户 管理员信息 使用 MySQL 数据库 并且每个用户都有自己的数据库 也有 MySQL 用于核心应用程序目的 我已在 CodeIgniter 内的 applic
  • 用 CGPathRef 屏蔽 CGContext?

    我正在使用 CGContext 进行一些绘图 我目前正在使用这样的 png 文件来屏蔽绘图 UIImage myImage UIImage imageNamed frame png CGContextRef context UIGraphi
  • 如何仅在悬停时显示 CSS 过渡?

    我在 div 上添加了一个过渡 这样当它悬停在上面时 颜色就会改变 有点像这里的例子 http jsfiddle net 78LWT HTML 代码如下 div div 这是 CSS 代码 transition background col
  • JENKINS 中是否有从节点 home 的环境变量?

    我们知道有一个名为 JENKINS HOME 的环境变量 因此我们可以在任何地方使用它作为 JENKINS HOME 但是现在当我在从节点上运行项目时 我需要使用从节点上的jenkins主目录 在定义从节点时名为 remote FS roo
  • Android Studio 3.1.4 Gradle 同步失败

    每当我在 Android Studio 中创建一个新项目时 它都会在 Gradle Sync 中失败 并且总是出现相同的错误 Connection timed out connect org gradle internal resource
  • java.lang.NumberFormatException:对于输入字符串:“20,475.00”

    我正在努力使我的系统保持运行平衡 为此 我从 AMOUNT 列中获取 jtable 中所有数字的总和 并将总和减去 txtLoanAmount 内的值 这是我的代码片段 String LoanAmount txtLoanAmount get
  • Oracle 选择今天之间的日期

    我有一个像这样的 Oracle SELECT 查询 Select From Customer Rooms CuRo Where CuRo Date Enter Between TODAY 12 00 00 PM And TODAY 11 5
  • 在子图网格中重新定位子图

    I am trying to make a plot with 7 subplots At the moment I am plotting two columns one with four plots and the other wit
  • AlarmManager 无法正常工作

    我正在尝试创建一个基于警报的应用程序 我在用着AlarmManager 问题是它根本不可靠 在某些设备中它可以工作 在其他设备中它有时可以工作 而在其他设备中它根本不起作用 当我说它不起作用时 很简单 警报不会响起 例如 在我的小米4中 如