android--Scheduling Repeating Alarms学习

原文地址:http://developer.android.com/training/scheduling/alarms.html

Alarms (based on the AlarmManager class)
give you a way to perform time-based operations outside the lifetime of your application. For example, you could use an alarm to initiate a long-running operation, such as starting a service once a day to download a weather forecast.。

在你的应用生命期之外,Alarms(基于 AlarmManager)给你提供了一个方法去执行一些基本操作。例如:你可以使用一个alarm
发起一个长时间运行的操作,比如每天一次开启服务下载天气预报。

Alarms have these characteristics:(Alarms 有以下特征:)

  • They let you fire Intents at set times and/or intervals.允许你定时或者间隔一段时间发起Intent
  • You can use them in conjunction with broadcast receivers to start services and perform other operations.能和广播接收器结合起来使用,开启服务或者执行其他操作。
  • They operate outside of your application, so you can use them to trigger events or actions even when your app is not running, and even if the device itself is asleep.这个操作在你应用程序之外,所以当你的app没有运行时你能使用他们触发一些事件或者操作,甚至是设备休眠时。
  • They help you to minimize your app‘s resource requirements. You can schedule operations without relying on timers or continuously running background services.帮你尽量减少app的资源要求。你可以有计划的操作,而不需要依赖定时器或者持续运行的后台服务。

Note: For timing operations that are guaranteed to occur during the lifetime of your application, instead consider using the Handler class
in conjunction with Timer and Thread.
This approach gives Android better control over system resources在你的应用程序运行期间也能保证定时操作发生,而不需考虑使用Handler和计时器线程一起使用。这种方法使Android更好地控制系统资源。

Understand the Trade-offs



A repeating alarm is a relatively simple mechanism with limited flexibility. It may not be the best choice for your app, particularly if you need to trigger network operations. A poorly designed alarm can cause battery drain and put a significant load on servers.重复alarm是一个灵活有限且相对简单的机制。如果你需要触发网络操作,它对你的app而言可能不是最好的选择。设计不良的alarm可以导致电池电量的消耗和加大服务器上的负载

A common scenario for triggering an operation outside the lifetime of your app is syncing data with a server. This is a case where you might be tempted to use a repeating alarm. But if you own the server that is hosting your app‘s data, using Google
Cloud Messaging
 (GCM) in conjunction with sync adapter is a better solution than AlarmManager.
A sync adapter gives you all the same scheduling options as AlarmManager,
but it offers you significantly more flexibility. For example, a sync could be based on a "new data" message from the server/device (see Running
a Sync Adapter
 for details), the user‘s activity (or inactivity), the time of day, and so on. See the linked videos at the top of this page for a detailed discussion of when and how to use GCM and sync adapter.

Best practices

Every choice you make in designing your repeating alarm can have consequences in how your app uses (or abuses) system resources. For example, imagine a popular app that syncs with a server. If the sync operation is based on clock time and every instance of
the app syncs at 11:00 p.m., the load on the server could result in high latency or even "denial of service." Follow these best practices in using alarms:在设计重复闹钟时你做的每个选择,都会有一个结果:在你的应用程序使用(或滥用)系统资源。例如:设想大量app使用一个服务器同步。如果这个同步操作是基于时钟时间并且每个app都在下午11点同步,这会导致服务高延时甚者是拒载服务。在使用alams时遵循以下最佳实践:

  • Add randomness (jitter) to any network requests that trigger as a result of a repeating alarm:重复闹钟添加随机性,结果是随机触发网络请求

    • Do any local work when the alarm triggers. "Local work" means anything that doesn‘t hit a server or require the data from the server.alarm触发时仅在本地起作用(Do
      any local work ),“Local work”指不需要握手服务器或者请求服务器数据。
    • At the same time, schedule the alarm that contains the network requests to fire at some random period of time.与此同时, 在随机的一段时间安排包含发起网络请求的alarm。
  • Keep your alarm frequency to a minimum.保持alarm频率最低。
  • Don‘t wake up the device unnecessarily (this behavior is determined by the alarm type, as described in Choose
    an alarm type
    ).不需要唤醒设备(这个行为依alarm的类型决定, Choose
    an alarm type
    有描述)
  • Don‘t make your alarm‘s trigger time any more precise than it has to be.不要让你的闹钟触发时间很精确。

    Use setInexactRepeating() instead
    of setRepeating().
    When you use setInexactRepeating(),
    Android synchronizes repeating alarms from multiple apps and fires them at the same time. This reduces the total number of times the system must wake the device, thus reducing drain on the battery. As of Android 4.4 (API Level 19), all repeating alarms are
    inexact. Note that while setInexactRepeating() is
    an improvement over setRepeating(),
    it can still overwhelm a server if every instance of an app hits the server around the same time. Therefore, for network requests, add some randomness to your alarms, as discussed above.使用 setInexactRepeating() 取代setRepeating()方法。当你使用setInexactRepeating(),从Android的多个应用程序同步重复alarm,并在同一时间触发他们。这能减少系统强制唤醒设备的总次数,因此能降低电量的消耗。在android4.4,所有重复的alarm都是不精确的。注意:尽管setInexactRepeating()是一个改进setRepeating(),如果一个应用程序的每个实例都在同一时间握手服务器,它仍然可以压倒一个服务器。因此,正如上面所讨论的,对于网络的请求,让alarm增加一些随机性。
  • Avoid basing your alarm on clock time if possible. 如果可能的话避免基于时钟时间的闹钟(alarm) 。 

    Repeating alarms that are based on a precise trigger time don‘t scale well. Use ELAPSED_REALTIME if
    you can. The different alarm types are described in more detail in the following section。基于精确触发时间的重复alarms没有很好地扩展。你可以使用ELAPSED_REALTIME。在下面的部分中对不同的告警类型进行了更详细的描述。

Set a Repeating Alarm



As described above, repeating alarms are a good choice for scheduling regular events or data lookups. A repeating alarm has the following characteristics:如上所叙,对于定期调度的事件或数据查询重复闹钟是一个非常好的选择。重复闹钟有以下特征:

  • A alarm type. For more discussion, see Choose an alarm type.一个闹钟类型,更多讨论看 Choose
    an alarm type
    .
  • A trigger time. If the trigger time you specify is in the past, the alarm triggers immediately.一个触发时间,如果你指定的触发时间是在过去,这个闹钟立即触发。
  • The alarm‘s interval. For example, once a day, every hour, every 5 seconds, and so on.闹钟间隔。例如:一天一次,一小时一次,五分钟一次等等
  • A pending intent that fires when the alarm is triggered. When you set a second alarm that uses the same pending intent, it replaces the original alarm.当闹钟被触发时将启动待处理的意图。当您使用相同的意图设置第二次闹钟时,它取代了原来的闹钟。

Choose an alarm type

One of the first considerations in using a repeating alarm is what its type should be.在使用重复闹钟时你首先考虑的问题是你应该用什么类型

There are two general clock types for alarms: "elapsed real time" and "real time clock" (RTC). Elapsed real time uses the "time since system boot" as a reference, and real time clock uses UTC (wall clock) time. This means that elapsed real time is suited to
setting an alarm based on the passage of time (for example, an alarm that fires every 30 seconds) since it isn‘t affected by time zone/locale. The real time clock type is better suited for alarms that are dependent on current locale.有两个通用的闹钟类型: "elapsed
real time" 和"real time clock" (RTC).Elapsed real time使用“自系统启动时间”作为一个参考,和real
time clock使用UTC(挂钟)时间。这意味着,elapsed real time 适合于设置基于时间流逝的闹钟(例如,警报将触发每30秒),因为它不会受时区/地区。real
time clock 类型更适合依赖于当前语言环境的报警。

Both types have a "wakeup" version, which says to wake up the device‘s CPU if the screen is off. This ensures that the alarm will fire at the scheduled time. This is useful if your app has a time dependency—for example, if it has a limited window to perform
a particular operation. If you don‘t use the wakeup version of your alarm type, then all the repeating alarms will fire when your device is next awake.两种类型都有一个唤醒版本,即如果屏幕关闭唤醒设备的CPU。这能确保闹钟在计划的时间里启动。如果你的App有时间依赖性是非常有用的。例如:有一个有限的窗口来执行特定的操作。如果你没有使用闹钟类型的唤醒版本,那么只有当你的设备下次唤醒时所有的重复闹钟才触发。

If you simply need your alarm to fire at a particular interval (for example, every half hour), use one of the elapsed real time types. In general, this is the better choice.如果你只需要在特定的间隔下(例如:每小时)启动闹钟,用elapsed
real time的一种就行。通常,这是一个好的选择。

If you need your alarm to fire at a particular time of day, then choose one of the clock-based real time clock types. Note, however, that this approach can have some drawbacks—the app may not translate well to other locales, and if the user changes the device‘s
time setting, it could cause unexpected behavior in your app. Using a real time clock alarm type also does not scale well, as discussed above. We recommend that you use a "elapsed real time" alarm if you can.如果你需要你的闹钟在一天的特定时间启动,就选择基于时钟类型的real
time clock一种,但请注意,这种方法可以有一些缺点,应用程序可能无法很好的转化为其他语言环境,并且如果用户更改设备的时间设置,可能会导致您的应用程序出现意外行为。如上所述,使用real
time clock闹钟类型也不能很好地扩展。如果可能我们推荐你使用一个“"elapsed
real time”闹钟。

Here is the list of types:这是类型列表:

  • ELAPSED_REALTIME—Fires
    the pending intent based on the amount of time since the device was booted, but doesn‘t wake up the device. The elapsed time includes any time during which the device was asleep.基于设备启动之后的时间启动意图,但不唤醒设备,The
    elapsed time 包括设备休眠期间的时间
  • ELAPSED_REALTIME_WAKEUP—Wakes
    up the device and fires the pending intent after the specified length of time has elapsed since device boot.在设备启动之后的指定时间长度唤醒设备并启动意图,
  • RTC—Fires
    the pending intent at the specified time but does not wake up the device.在一个具体的时间去启动意图,但是不会唤醒设备
  • RTC_WAKEUP—Wakes
    up the device to fire the pending intent at the specified time.在一个具体的时间唤醒设备启动意图

ELAPSED_REALTIME_WAKEUP examples

Here are some examples of using ELAPSED_REALTIME_WAKEUP.使用ELAPSED_REALTIME_WAKEUP.的例子

Wake up the device to fire the alarm in 30 minutes, and every 30 minutes after that:在30分钟内唤醒设备并启动闹钟,之后每三十分钟一次

// Hopefully your alarm will have a lower frequency than this!
alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
        AlarmManager.INTERVAL_HALF_HOUR,
        AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);

Wake up the device to fire a one-time (non-repeating) alarm in one minute:唤醒设备并在一分钟之后启动闹钟,仅一次

private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() +
        60 * 1000, alarmIntent);

RTC examples

Here are some examples of using RTC_WAKEUP.使用RTC_WAKEUP.的例子

Wake up the device to fire the alarm at approximately 2:00 p.m., and repeat once a day at the same time:在下午两点左右,唤醒设备并启动闹钟,在相同的时间每天重复一次

// Set the alarm to start at approximately 2:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);

// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        AlarmManager.INTERVAL_DAY, alarmIntent);

Wake up the device to fire the alarm at precisely 8:30 a.m., and every 20 minutes thereafter:在精确的上午8:30,唤醒设备并启动闹钟,此后每20分钟执行一次

private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

// Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);

// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        1000 * 60 * 20, alarmIntent);

Decide how precise your alarm needs to be 决定你的闹钟需要精确到多少

As described above, choosing the alarm type is often the first step in creating an alarm. A further distinction is how precise you need your alarm to be. For most apps, setInexactRepeating() is
the right choice. When you use this method, Android synchronizes multiple inexact repeating alarms and fires them at the same time. This reduces the drain on the battery.如上所述,选择闹钟类型是创建闹钟的第一步。另一个区别是你的闹钟需要精确多少。对于大多数应用程序,setInexactRepeating()是正确的选择。当您使用此方法,Android同步多个不精确的重复闹钟,并在同一时间触发他们。这不仅降低了电池电量的消耗。

For the rare app that has rigid time requirements—for example, the alarm needs to fire precisely at 8:30 a.m., and every hour on the hour thereafter—use setRepeating().
But you should avoid using exact alarms if possible.对于有刚性时间要求的罕见应用程序,例如,闹钟需要精确到上午8:30,并每隔一小时以后用setRepeating()。但是如果可能的话,你应该避免使用精确的闹钟。

With setInexactRepeating(),
you can‘t specify a custom interval the way you can with setRepeating().
You have to use one of the interval constants, such as INTERVAL_FIFTEEN_MINUTESINTERVAL_DAY,
and so on. See AlarmManager for
the complete list.使用setInexactRepeating()方法时你不能指定一个自定义的时间间隔,使用setRepeating()就可以指定。你必须使用的间隔常量中的一个,如INTERVAL_FIFTEEN_MINUTES,INTERVAL_DAY等等。见AlarmManager的完整列表。

Cancel an Alarm



Depending on your app, you may want to include the ability to cancel the alarm. To cancel an alarm, callcancel() on
the Alarm Manager, passing in the PendingIntent you
no longer want to fire. For example:取决于你的app,你可能想有取消闹钟的能力。取消一个闹钟,在闹钟Manager中呼叫cancel()方法,传入你不想再启动的PendingIntent对象。例如:

// If the alarm has been set, cancel it.
if (alarmMgr!= null) {
    alarmMgr.cancel(alarmIntent);
}

Start an Alarm When the Device Boots设备启动时启动一个闹钟



By default, all alarms are canceled when a device shuts down. To prevent this from happening, you can design your application to automatically restart a repeating alarm if the user reboots the device. This ensures that theAlarmManager will
continue doing its task without the user needing to manually restart the alarm.默认情况下,当设备关闭时所有闹钟将被取消。为了阻止这个情况发生,当用户重启设备时,你可以设计你的程序自动重启一个重复闹钟。这能保证闹钟管理器继续做它的任务而不需要用户手动重启闹钟。

Here are the steps:以下是步骤:

  1. Set the RECEIVE_BOOT_COMPLETED permission
    in your application‘s manifest. This allows your app to receive the ACTION_BOOT_COMPLETED that
    is broadcast after the system finishes booting (this only works if the app has already been launched by the user at least once)。在你的应用程序配置文件manifest中,添加RECEIVE_BOOT_COMPLETED权限。这允许你的app能接收ACTION_BOOT_COMPLETED 事件广播,该广播是系统启动完成后发送(只在你的app至少被用户启动一次后有作用)。

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  2. Implement a BroadcastReceiver to
    receive the broadcast:实现一个BroadcastReceiver 来接收这个广播

    public class SampleBootReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
                // Set the alarm here.
            }
        }
    }
  3. Add the receiver to your app‘s manifest file with an intent filter that filters on the ACTION_BOOT_COMPLETEDaction:添加这个接收器到你的应用配置文件maiifest里,并用intent
    filter过滤 ACTION_BOOT_COMPLETED事件

    <receiver android:name=".SampleBootReceiver"
            android:enabled="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"></action>
        </intent-filter>
    </receiver>

    Notice that in the manifest, the boot receiver is set to android:enabled="false".
    This means that the receiver will not be called unless the application explicitly enables it. This prevents the boot receiver from being called unnecessarily. You can enable a receiver (for example, if the user sets an alarm) as follows:注意在配置文件里,启动接收器需要设置android:enabled="false"属性。这意味着接收器不会被调用,除非应用程序显式启用它。这可以防止在启动接收器不必要的呼叫。可以使一个接收器(例如,如果用户设置一个闹钟)如下

    ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
    PackageManager pm = context.getPackageManager();
    
    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);

    Once you enable the receiver this way, it will stay enabled, even if the user reboots the device. In other words, programmatically enabling the receiver overrides the manifest setting, even across
    reboots. The receiver will stay enabled until your app disables it. You can disable a receiver (for example, if the user cancels an alarm) as follows:一旦启用了接收这种方式,它会保持启用,即使用户重新启动设备。换句话说,通过编程使接收器覆盖舱单,甚至在重新启动。接收器将保持启用,直到您的应用程序禁用它。可以禁用接收器(例如,如果用户取消闹钟),如下所示:

    ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
    PackageManager pm = context.getPackageManager();
    
    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP);

翻译不好的地方,请指正,我会非常感谢的并且及时修改。

android--Scheduling Repeating Alarms学习

时间: 2024-08-16 11:43:30

android--Scheduling Repeating Alarms学习的相关文章

Android Window PhoneWindow Activity学习心得--第三弹

Android Window  PhoneWindow Activity学习心得--第三弹 前面 我们完成了从Activity到PhoneWindow的整体跨度 正如我们所知道的与Activity组件关联的一个应用程序窗口视图对象关联一个ViewRoot对象,而将 一个Activity组件的应用程序窗口视图对象与一个ViewRoot对象关联是通过该Activity组件所使用的 窗口管理器(WindowManager)来执行的. 在我们初始化DecorView完成之后,我们需要关联应用程序窗口视图

Android系统源码学习步骤

Android系统是基于Linux内核来开发的,在分析它在运行时库层的源代码时,我们会经常碰到诸如管道(pipe).套接字(socket)和虚拟文件系统(VFS)等知识. 此外,Android系统还在Linux内核中增加了一些专用的驱动程序,例如用于日志系统的Logger驱动程序.用于进程间通信的Binder驱动程序和用于辅助内存管理的匿名共享内存Ashmem驱动程序.在分析这些Android专用驱动程序的时候,也会碰到Linux内核中与进程.内存管理相关的数据结构. 因此,我们有必要掌握一些L

针对Android平台我们需要学习如何在Unity中调用Android的JAVA代码。

Unity for Android 比较特殊,Unity for IOS 打包是将XCODE工程直接交给开发者,开发者可以在工程的基础上继续添加新的视图,最后由开发者自行打包生成IPA包,发布程序.而Unity for Android打包直接生成APK包,等于说源代码开发者是看不到的,但是Unity的自身确实有些局限,针对Android平台我们需要学习如何在Unity中调用Android的JAVA代码.本章我们的目标是使用Unity的脚本打开Activity.首先我们创建一个普通的Android

C#程序员学习Android开发系列之学习路线图

通过前面的3篇博客已经简单的介绍了Android开发的过程并写了一个简单的demo,了解了Android开发的环境以及一些背景知识. 接下来这篇博客不打算继续学习Android开发的细节,先停一下,明确一下接下来的学习目标以及学习路线. 一.对Android开发的基本认识 1.Android原生开发是基于Java语言的,由于我比较擅长C#,所以对Java语言本身不太熟练,需要加强Java语言基础的练习,这一块我会穿插到具体的知识点练习当中,并且在必要的地方给出与C#语言的对比(其实基本上在语法层

quick cocos 或者 Cocos2dx 项目下的Android.mk文件的学习

android.mk文件的作用:编译需要的cpp文件,生成.so动态库,供android端调用. 先上一个android.mk文件: 第一次创建项目,在Android平台编译时,都需要通过android.mk文件编译整个cocos2dx的库(第一次编译我们需要等待很长的时间.....). 首先知道$(call import-module,dir_name)的作用,然后顺着lib/proj.android目录继续找对应目录下的android.mk文件 类似于递归一样,把所有目录下的android.

Android 上能提高学习工作效率的应用

在知乎上有朋友问 Android 上能提高学习.工作效率的应用有哪些?我给他们的推荐获得了最多赞同.以后会不断完善更新此贴. Any.do :规划日程,各平台都有. Evernote:记笔记,各平台都有. OneNote:这个也不错,特别是文档功能很强大,微软有Office基因啊,但同步有点慢... Quora:问答SNS网站客户端 ,看问题学英语感觉不错 Pocket:稍候阅读软件,各平台都有,chrome有插件,自定义快捷键chrome上快速保存文章,Android上各App都可以分享到Pl

android金阳光自动化测试——学习历程:电池续航上&amp;&amp;下

章节:自动化基础篇——电池续航自动化测试上&&下 网易云课堂: http://study.163.com/course/courseLearn.htm?courseId=712011#/learn/video?lessonId=878098&courseId=712011 http://study.163.com/course/courseLearn.htm?courseId=712011#/learn/video?lessonId=878099&courseId=7120

Android开发手册 安卓学习教程手册(MtAndroid开发手册)

发布本资料须遵守开放出版许可协议 1.0 或者更新版本. 未经版权所有者明确授权,禁止发行本文档及其被实质上修改的版本. 未经版权所有者事先授权,禁止将此作品及其衍生作品以标准(纸质)书籍形式发行. 如果有兴趣再发行或再版本手册的全部或部分内容,不论修改过与否,或者有任何问题,请联系版权所有者 [email protected]. Android开发者必备学习手册,基础和进阶手册. (MtAndroid开发手册) Android开发手册 安卓学习教程手册(MtAndroid开发手册),布布扣,b

android的简单入门学习

话说光配环境就整死我了, 不是说多么难, 是最近google被屏了, 很多sdk里面需要下载的东西都下不下来, 坑爹啊.  最后跟扫拉稀要了一个他配置好的,才运行了. android目录分析: assets 资产目录,存放文件,这些文件会被打包到应用程序的apk(安装包) bin 编译后的文件目录 gen 目录自动生成的目录 project.properties 代表编译的版本 target = "" 来修改编译版本 libs 支持jar包 会被添加到android depend 目录