在Android 5.1中设置每秒的闹钟

13
我想在我的应用程序中每秒运行一次闹钟服务。在5.1版本以下可以正常工作,但在5.1设备上无法触发。我正在使用commonsware wakeful intent service。logcat消息显示:“可疑的短间隔1000毫秒;扩展到60秒”。如何在5.1中每秒轮询?有人能建议我如何做到这一点吗?
更详细的解释: 我的用例是需要每30分钟进行一次操作。据我所知,使用闹钟管理器是有效的方法,但在这里:
1)我需要向用户显示倒计时器。(定时器任务、倒计时器、ScheduledExecutorService对此非常有用) 2)即使应用程序处于后台,我也需要每30分钟向用户发出通知。(闹钟服务就足够了)
但是,当应用程序在后台运行时,如果从最近列表中滑出应用程序(即杀死应用进程),则所有的服务、定时器、处理程序和执行器服务都将不起作用。在这种情况下,我如何在完成30分钟后通知用户?如果我想错了,请指导我。
谢谢, Chaitanya

1
使用TimerTask可以满足这种需求。 - Techfist
请检查我的更新答案。 - Sami Eltamawy
我的问题有什么问题吗?我能知道被踩的原因吗? - Chaitu
我认为他们给负评是因为logcat 已经解释了一切,但我认为这个问题还是可以的。 - shkschneider
在5.1设备中,您可以每秒从onReceive再次调用闹钟。它的工作方式类似于1秒计时器,并且当应用程序从最近的列表中被杀死时不会受到影响。我曾经遇到过同样的问题,但是通过这种方式我解决了它...祝你好运。 - Ketan Patel
7个回答

8

这是安卓Lollipop正常的行为。

可疑的短时间间隔1000毫秒;扩展到60秒

这告诉你系统不再支持那些短时间间隔。

问题#161244 记录了:

这是预期行为,但目前文档说明不充分(我们意识到这个问题的一面)。

总体来说:短周期和近期的闹钟会消耗惊人的电量;需要短周期或将来的任务的应用程序应使用其他机制来调度其活动。

因此,请勿使用 AlarmService。最好使用线程、ExecutorsTimerTask 或其他机制:

// Using Handler
new Handler().postDelayed(runnable, TimeUnit.SECONDS.toMillis(1));

// Using Executors
Executors.newSingleThreadScheduledExecutor().schedule(runnable, 1, TimeUnit.SECONDS);

4
如果任务必须在设备休眠或应用程序未运行时运行,该怎么办? - Giulio Piancastelli
你不能每秒设置一个触发警报的服务,这是上述原因所暴露的。请查看上面的替代方案或官方参考文献:https://developer.android.com/training/scheduling/alarms.html#set,或者只需使用更长的时间间隔即可。 - shkschneider
抱歉,我不是指每秒钟都会发生。我是指任何少于1分钟的时间段(例如25秒),因为日志信息似乎暗示了这一点。即使设备处于睡眠状态或应用程序不再运行,postDelayed和Executors是否仍然有效? - Giulio Piancastelli
我不这么认为。即使它们是线程,那些线程也是你的应用程序组进程的一部分。使用服务来实现你想要的功能。 - shkschneider
1
好的...但是服务需要重新安排,例如每25秒...那么,如果AlarmManager无法完成这项任务,应该使用什么来重新安排它呢? - Giulio Piancastelli
显示剩余2条评论

5

为什么要这样做?
使用处理程序(handler)代替:

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        // do your stuff here, called every second
        mHandler.postDelayed(this, 1000);
    }
};

// start it with:
mHandler.post(runnable);

使用以下代码停止1秒计时器:

mHandler.removeCallbacks(runnable);

嘿 @lazy-ninja,你可以检查一下我更新后的问题吗?并给我建议。 - Chaitu
1
谢谢。解决方案按预期工作。AlarmManager无法强制在精确时间触发。 - Ahmed Gad

1

同时使用 1 2:

  • 在需要用户每隔一分钟以上(如所请求的30分钟)进行提醒的角色中,使用 AlarmManager

  • 如果通知触发了需要在前台显示更新的活动,则还应该执行廉价操作,例如 postDelayed() ,以在该活动中定期向用户更新


谢谢您的建议。我按照您说的做了,效果很好,正如我所预期的那样。 - Chaitu
请问chaitu能否帮一下我,你做了什么? - Efrain Sanjay Adhikary

0

这是一个针对 Android 5.1 报告的 问题,当您尝试设置低于 60000 毫秒的时间间隔时会发生。

这个警告出现是因为设置非常低的时间间隔会非常快地耗尽您的电池。

平台上的项目成员表示:

一般来说:短期和近期的闹钟会消耗惊人的电量; 需要短期或近期工作的应用程序应使用其他机制来安排它们的活动。

这就是为什么在您的情况下不建议使用 Alarm

根据您的问题更新。 您想让后台服务保持唤醒状态,即使用户手动从最近使用的应用列表中滑掉了它。 这可以通过使用以下代码中的 START_STICKY 标志来简单完成。 将此代码添加到您的服务中的 onStartCommand 方法中:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
} 

来源:答案


我正在使用START_STICKY,但是当我关闭应用程序时,我的服务仍然被杀死。我认为这不是一个可靠的解决方案。 - szx

0

请尝试以下步骤:

  1. 使用AlarmManager,定期每1分钟执行一次
  2. 在AlarmManager中使用Handler,在一定时间后调用并执行您的任务。

请记住:

这不是一个好主意,因为AlarmManager并不知道设备当前的情况,例如它不考虑设备是否连接到电源插头、闲置或连接到网络。此外,AlarmManager浪费资源,因为它不关心设备何时有更多可用资源。


0

我不完全理解你的使用情况,但每秒钟设置一个闹钟是过度的。你可以使用计时器。请查看这个类。


-2

我已成功将AlarmManager的最小间隔从1分钟更改为30秒。

在您的设备上,将/system/framework/services.jar复制到您的计算机上。 从中提取classes.dex,例如使用Winrar打开。

 

下载baksmali

java -jar baksmali.jar -o extractfolder classes.dex

编辑extractfolder\com\android\server\AlarmManagerService$Constants.smali

将所有值0xea60(十六进制中的60000ms / 1min)替换为您想要的最小间隔时间,例如30秒的0x7530

保存并重新编译回classes.dex

java -Xmx512M -jar smali.jar extractfolder -o classes.dex

在Winrar中再次打开services.jar,删除classes.dex并将新创建的classes.dex拖入services.jar。

复制回/system/framework/services.jar

重新启动设备。

此外,在我的三星设备上,包名称中含有“alarm”或“alert”(未经测试)的应用程序将被添加到白名单中。当我这样做时,我的闹钟会准确地触发。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接