当前位置: 首页 > 知识库问答 >
问题:

如何在手机锁定的情况下每隔x分钟发送一次通知

姜学海
2023-03-14

我正在制作一个提醒应用程序,所以我需要每x分钟发送一次通知,因为我研究发现我需要使用AlarmManager(idk,如果我可以使用任何其他方法)。所以我尝试使用AlarmManager来触发通知。它只在我使用手机时工作,如果手机已锁定,则不会触发警报,当我解锁手机时,警报就会触发。

这是我的Androidanifest.xml:

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


    <receiver android:name=".util.NotificationAlarmReceiver"/>

    <receiver android:name=".util.BootCompletedReceiver"
        android:permission="android.permission.RECEIVE_BOOT_COMPLETED" android:enabled="true" android:exported="true">
        <intent-filter>
            <category android:name="android.intent.category.DEFAULT"/>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.ACTION_BOOT_COMPLETED"/>
            <action android:name="android.intent.action.REBOOT"/>
            <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
            <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
            <action android:name="android.intent.action.ACTION_SHUTDOWN"/>
        </intent-filter>
    </receiver>

所以我必须接收一个用于通知,一个用于在启动时激活alarmManager。

在扩展BroadcastRecader的NotificationAlrmRecader上,我也在尝试使用WakeLock:

@重写公共void onReceive(Context-Context,Intent-Intent){

    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "com.test.reminder:WakeLockForNotification");
    wl.acquire(60 * 1000L /*1 minute*/);

    // Notification code is here.

    wl.release();
}

所以我试图唤醒show通知然后释放,但只是没有唤醒。这是我用来设置警报的代码:

 Intent intentAlarm = new Intent(this, NotificationAlarmReceiver.class);
        AlarmManager alarmManager = (AlarmManager) this.getSystemService(ALARM_SERVICE);
        PendingIntent pi = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.getBroadcast(this, Constants.ALARM_ID, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE) : PendingIntent.getBroadcast(this, Constants.ALARM_ID, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
        alarmManager.html" target="_blank">setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+tinyDB.getLong(Constants.notification_interval_key,AlarmManager.INTERVAL_HALF_HOUR), tinyDB.getLong(Constants.notification_interval_key,AlarmManager.INTERVAL_HALF_HOUR), pi);
    

那么,是否有任何解决方案可以在每次需要时显示通知。我还阅读了android文档,没有使用exact alarm manager,我还看到有人使用了job scheduler,但我对此并不熟悉,但也知道他们有问题,所以任何想法或解决方案都会受到欢迎。

共有1个答案

祁兴运
2023-03-14

我自己经历了这个过程。有关警报/计时器的文档不必要地令人困惑。为了简化事情,如果你的应用程序实际上是一个提醒应用程序,并且用户确实希望每X分钟准确出现一次通知,那么可以使用准确的警报。

但是要小心,因为Android之神讨厌常识和任何类型的一致性。唯一可靠的精确警报是setAlallm时钟(),尤其是在您处理打瞌睡模式时。此外,虽然名称setExactAndAllowWhileIdle()听起来可能总是准确执行,但它不会按留档:

为了减少滥用,对特定应用程序发出警报的频率有限制。在正常系统操作下,其发出这些警报的时间不会超过大约每分钟一次(此时发出每个此类待处理警报);在低功率空闲模式下,此持续时间可能会明显更长,例如15分钟。

最后一部分是破坏任何使用setExactAndAllowWhileIdle()作为重复警报的希望的部分。

与您可能认为的相反,您不想要setInexactRepeating(),甚至不想要setRepeating()。如果你仔细观察,文档底部的小注释会说:

注:自API 19起,所有重复报警均不精确。如果您的应用程序需要精确的交付时间,那么它必须使用一次性精确警报,并按上述每次重新安排。targetSdkVersion早于API 19的传统应用程序将继续将其所有警报(包括重复警报)视为精确。

因此,为了真正实现可靠的重复精确报警,您必须使用设置闹钟()来安排第一个报警,并且每次报警响起时,使用设置闹钟()来安排下一个通知/报警。作为开发此功能的提示,您可以将有关何时安排下一个警报的信息存储在广播目的的附加信息中。

可悲的是:上述方法可能适用于AOSP,但其他供应商在如何管理警报方面自由裁量。https://dontkillmyapp.com/了解这些供应商是谁。

一些额外的信息:

AlarmManager已经在BroadcastReceive()方法中提供了唤醒锁,如下所述:

只要报警接收器的onReceive()方法正在执行,报警管理器就会保持CPU唤醒锁。这保证了在您处理完广播之前,手机不会Hibernate。一旦onReceive()返回,报警管理器就会释放此唤醒锁。这意味着在某些情况下,一旦onReceive()方法完成,手机就会进入睡眠状态。如果您的报警接收器调用上下文。startService(),手机可能会在启动请求的服务之前Hibernate。为了防止这种情况,您的BroadcastReceiver和服务将需要实施单独的唤醒锁定策略,以确保手机继续运行,直到服务可用为止。

正如问题注释中所指出的那样,为了使用精确警报(因此,您需要在清单中声明调度精确警报权限)。请注意,这是一种特殊权限,可以撤销。您可以使用canScheduleExactAlarms来确定权限是否被撤销。我建议查看文档,了解如何处理被撤销的权限。

 类似资料:
  • 问题内容: 我正在cronjob中运行PHP脚本,我想每5分钟发送一封电子邮件 我当前的(crontab)cronjob: cronmail.php如下: 但是我没有在30分钟内收到此配置的电子邮件。 问题答案: 在文件中,这些字段是: 每小时的分钟。 一天中的小时。 一个月中的某天。 一年中的月份。 一周中的天。 所以: 表示每小时10分钟执行一次。 如果您希望每五分钟使用一次,请使用以下任一方

  • 问题内容: 我正在使用Python和PyGTK。我对运行某个功能感兴趣,该功能每隔几分钟从串行端口获取数据并保存一次。 当前,我正在时间库中使用sleep()函数。为了能够进行处理,我将系统设置如下: 这种设置使我从串口读取数据的间隔为5分钟。我的问题是我希望能够让我的readserial()函数每隔5分钟暂停一次,并且能够一直执行操作,而不是使用time.sleep()函数。 关于如何解决这个问

  • 问题内容: 如何每分钟运行一个函数?在JavaScript中,我可以做类似的事情,在Swift中是否存在类似的事情? 想要的输出: 你好世界每分钟一次… 问题答案: 记住要导入基金会。 斯威夫特4:

  • 我正在建立一个应用程序,用户将把他们的测试和作业和任何东西。我想知道我的应用程序是否有可能在测试前一周和一天发出通知? 我看到的到处都是firebase通知和push通知。 我不想要这些在线通知,我将需要应用程序发送他们自己离线。这可能吗?

  • 场景如下,我希望每分钟在电报通道上发送消息或通知(无需用户发送命令)。 我可以在每次输入URL并发送消息时发送消息,但我希望每分钟自动发送(不输入URL)。我不知道怎么做,提前谢谢。 注意:此聊天id必须是一个人的聊天id,而不是另一个机器人聊天id!!!**$params=['聊天室id'= 我必须输入要发送的邮件的URL。。。https://bot.unpixelmas.com/bot.php

  • 问题内容: 我想尝试通过以下方式使用@Schedule批注: 根据日志,CronService运行良好,但是计划的任务“ runsEveryMinute”不起作用。 使用EJB计划任务如何工作? 问题答案: 按照该Javadoc中的注释,默认值是: 除小时,分钟和秒外的所有字段;和 默认情况下为小时,分钟和秒。 通过将小时值保留为默认值,它要求计时器在午夜之后每分钟运行一小时(即00:00、00: