Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android--Scheduling Repeating Alarms學習

android--Scheduling Repeating Alarms學習

編輯:關於Android編程

原文地址: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_MINUTES, INTERVAL_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至少被用戶啟動一次後有作用)。
            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事件
              
                  
                      
                  
              

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

              翻譯不好的地方,請指正,我會非常感謝的並且及時修改。


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved