AlarmManager
) מאפשרות לבצע פעולות מבוססות-זמן מחוץ למשך החיים של האפליקציה.
לדוגמה, אפשר להשתמש בהתראה כדי להפעיל פעולה ממושכת, כמו הפעלה של שירות פעם ביום כדי להוריד תחזית מזג אוויר.
המאפיינים של שעונים מעוררים:
הן מאפשרות להפעיל Intents בזמנים או במרווחי זמן מוגדרים.
אפשר להשתמש בהם בשילוב עם מקלטי שידורים כדי לתזמן משימות או בקשות עבודה לביצוע פעולות אחרות.
הן פועלות מחוץ לאפליקציה, כך שאפשר להשתמש בהן כדי להפעיל אירועים או פעולות גם כשהאפליקציה לא פועלת, ואפילו אם המכשיר עצמו במצב שינה.
הם עוזרים לכם לצמצם את דרישות המשאבים של האפליקציה. אפשר לתזמן פעולות בלי להסתמך על טיימרים או על שירותים שפועלים באופן רציף.
הגדרת התראה לא מדויקת
כשבאפליקציה מוגדר שעון מעורר לא מדויק, המערכת מפעילה את השעון המעורר בשלב מסוים בעתיד. התראות לא מדויקות מספקות כמה הבטחות לגבי התזמון של שליחת ההתראה, תוך התחשבות בהגבלות של חיסכון בסוללה, כמו מצב שינה.
מפתחים יכולים להשתמש בהתחייבויות הבאות לגבי ה-API כדי להתאים אישית את התזמון של מסירת התראות לא מדויקות.
הפעלת התראה אחרי זמן מסוים
אם האפליקציה קוראת ל-set()
,
setInexactRepeating()
,
או ל-setAndAllowWhileIdle()
,
ההתראה לא תופעל לפני שעת ההפעלה שצוינה.
ב-Android 12 (רמת API 31) ומעלה, המערכת מפעילה את ההתראה תוך שעה אחת מזמן ההפעלה שצוין, אלא אם חלות הגבלות על חיסכון בסוללה, כמו חיסכון בסוללה או מצב שינה.
הפעלת שעון מעורר במהלך חלון זמן
אם האפליקציה שלכם קוראת ל-setWindow()
, ההתראה אף פעם לא מופעלת לפני זמן ההפעלה שצוין. אלא אם יש הגבלות כלשהן על חיסכון בסוללה, ההתראה תתקבל בחלון הזמן שצוין, החל משעת ההפעלה שצוינה.
אם האפליקציה מיועדת ל-Android 12 או לגרסאות מתקדמות יותר, המערכת יכולה לדחות את ההפעלה של אזעקה לא מדויקת עם חלון זמן ב-10 דקות לפחות. לכן, ערכי הפרמטר windowLengthMillis
בקטע 600000
נחתכים ל-600000
.
השמעת שעון מעורר חוזר במרווחי זמן קבועים בערך
אם האפליקציה קוראת ל-setInexactRepeating()
,
המערכת מפעילה כמה התראות:
- ההתראה הראשונה תופעל בחלון הזמן שצוין, החל משעת ההפעלה שצוינה.
- בדרך כלל, האזעקות הבאות יופעלו אחרי חלון הזמן שצוין. הזמן בין שני הפעלות רצופות של ההתראה יכול להשתנות.
הגדרת התראה מדויקת
המערכת מפעילה שעון מעורר מדויק ברגע מסוים בעתיד.
רוב האפליקציות יכולות לתזמן משימות ואירועים באמצעות שעונים מעוררים לא מדויקים כדי להשלים כמה תרחישי שימוש נפוצים. אם הפונקציונליות העיקרית של האפליקציה תלויה בהתראה מדויקת – למשל באפליקציית שעון מעורר או באפליקציית יומן – אפשר להשתמש בהתראה מדויקת במקום זאת.
תרחישים לדוגמה שבהם יכול להיות שלא נדרש שימוש בהתראות מדויקות
ברשימה הבאה מפורטים תהליכי עבודה נפוצים שאולי לא מצריכים התראה מדויקת:
- תזמון פעולות שקשורות לתזמון במהלך מחזור החיים של האפליקציה
- המחלקות
Handler
כוללות כמה שיטות טובות לטיפול בפעולות שקשורות לתזמון, כמו ביצוע פעולה כל n שניות, בזמן שהאפליקציה פעילה:postAtTime()
ו-postDelayed()
. הערה: ממשקי ה-API האלה מסתמכים על זמן הפעולה של המערכת ולא על זמן אמת. - עבודת רקע מתוזמנת, כמו עדכון האפליקציה והעלאת יומנים
WorkManager
מאפשרת לתזמן עבודה תקופתית שרגישה לזמן. אפשר לציין מרווח חזרהflexInterval
(15 דקות לפחות) כדי להגדיר זמן ריצה מפורט לעבודה.- פעולה שמוגדרת על ידי המשתמש וצריכה לקרות אחרי פרק זמן מסוים (גם אם המערכת במצב לא פעיל)
- שימוש בהתראה לא מדויקת. במיוחד, התקשר אל
setAndAllowWhileIdle()
. - פעולה שהמשתמש מציין שצריכה לקרות אחרי פרק זמן מסוים
- שימוש בהתראה לא מדויקת. במיוחד, התקשר אל
set()
. - פעולה שהמשתמש מגדיר שיכולה לקרות בתוך חלון זמן מוגדר
- שימוש בהתראה לא מדויקת. במיוחד, התקשר אל
setWindow()
. שימו לב: אם האפליקציה שלכם מיועדת ל-Android 12 ואילך, אורך החלון הקצר ביותר שמותר הוא 10 דקות.
דרכים להגדרת התראה מדויקת
האפליקציה יכולה להגדיר התראות מדויקות באחת מהשיטות הבאות. השיטות האלה מסודרות כך שהשיטות שקרובות יותר לתחתית הרשימה מיועדות למשימות שדורשות תגובה מהירה, אבל הן צורכות יותר משאבי מערכת.
setExact()
הפעלת שעון מעורר בשעה מדויקת בעתיד, כל עוד לא מופעלים אמצעים אחרים לחיסכון בסוללה.
אפשר להשתמש בשיטה הזו כדי להגדיר התראות מדויקות, אלא אם העבודה של האפליקציה היא קריטית למשתמשים מבחינת הזמן.
setExactAndAllowWhileIdle()
הפעלת שעון מעורר בשעה מדויקת בעתיד, גם אם מופעלים אמצעים לחיסכון בסוללה.
setAlarmClock()
הפעלת שעון מעורר בשעה מדויקת בעתיד. ההתראות האלה גלויות מאוד למשתמשים, ולכן המערכת אף פעם לא משנה את זמן המסירה שלהן. המערכת מזהה את ההתראות האלה כהתראות החשובות ביותר, ויוצאת ממצבי חיסכון בסוללה אם צריך כדי להציג אותן.
צריכת משאבי המערכת
כשהמערכת מפעילה אזעקות מדויקות שהאפליקציה מגדירה, המכשיר צורך הרבה משאבים, כמו חיי סוללה, במיוחד אם הוא במצב חיסכון באנרגיה. בנוסף, המערכת לא יכולה בקלות לאגד את הבקשות האלה כדי להשתמש במשאבים בצורה יעילה יותר.
מומלץ מאוד ליצור אזעקה לא מדויקת בכל הזדמנות אפשרית. כדי לבצע עבודה ארוכה יותר, אפשר לתזמן אותה באמצעות WorkManager
או JobScheduler
מתוך השעון המעורר BroadcastReceiver
. כדי לבצע עבודה בזמן שהמכשיר במצב שינה, צריך ליצור התראה לא מדויקת באמצעות setAndAllowWhileIdle()
ולהתחיל עבודה מההתראה.
הצהרה על ההרשאה המתאימה להתראה מדויקת
אם האפליקציה מטרגטת ל-Android 12 ומעלה, צריך לקבל את הרשאת הגישה המיוחדת 'התראות ותזכורות'. כדי לעשות זאת, צריך להצהיר על ההרשאה SCHEDULE_EXACT_ALARM
בקובץ המניפסט של האפליקציה, כמו שמוצג בקטע הקוד הבא:
<manifest ...> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/> <application ...> ... </application> </manifest>
אם האפליקציה מטרגטת ל-Android 13 (רמת API 33) ומעלה, יש לך אפשרות להצהיר על ההרשאה SCHEDULE_EXACT_ALARM
או על ההרשאה USE_EXACT_ALARM
.
<manifest ...> <uses-permission android:name="android.permission.USE_EXACT_ALARM"/> <application ...> ... </application> </manifest>
למרות שההרשאות SCHEDULE_EXACT_ALARM
ו-USE_EXACT_ALARM
מציינות את אותן יכולות, הן ניתנות בצורה שונה ותומכות בתרחישי שימוש שונים. האפליקציה שלך צריכה להשתמש בהתראות מדויקות ולהצהיר על ההרשאה SCHEDULE_EXACT_ALARM
או USE_EXACT_ALARM
רק אם פונקציה שגלויה למשתמשים באפליקציה מחייבת פעולות עם תזמון מדויק.
USE_EXACT_ALARM
- הוענקה אוטומטית
- המשתמש לא יכול לבטל את הגישה
- בכפוף למדיניות חדשה של Google Play
- תרחישים לדוגמה לשימוש מוגבל
SCHEDULE_EXACT_ALARM
- ניתנה על ידי המשתמש
- מגוון רחב יותר של תרחישים לדוגמה
- האפליקציות צריכות לוודא שההרשאה לא בוטלה
ההרשאה SCHEDULE_EXACT_ALARM
לא ניתנת מראש להתקנות חדשות של אפליקציות שמטרגטות ל-Android 13 (רמת API 33) ומעלה. אם משתמש מעביר נתוני אפליקציות למכשיר עם Android 14 באמצעות פעולת גיבוי ושחזור, ההרשאה SCHEDULE_EXACT_ALARM
תידחה במכשיר החדש. עם זאת, אם לאפליקציה קיימת כבר יש את ההרשאה הזו, היא תינתן מראש כשהמכשיר ישודרג ל-Android 14.
הערה: אם ההתראה המדויקת מוגדרת באמצעות אובייקט OnAlarmListener
, כמו באמצעות API setExact
, לא נדרשת ההרשאה SCHEDULE_EXACT_ALARM
.
שימוש בהרשאה SCHEDULE_EXACT_ALARM
בניגוד להרשאה USE_EXACT_ALARM
, המשתמש צריך להעניק את ההרשאה SCHEDULE_EXACT_ALARM
. גם המשתמש וגם המערכת יכולים לבטל את ההרשאה SCHEDULE_EXACT_ALARM
.
כדי לבדוק אם ההרשאה ניתנה לאפליקציה, צריך להתקשר אל
canScheduleExactAlarms()
לפני שמנסים להגדיר התראה מדויקת. כשמבטלים את ההרשאה SCHEDULE_EXACT_ALARM
לאפליקציה, האפליקציה מפסיקה לפעול וכל ההתראות המדויקות העתידיות מבוטלות. זה גם אומר שהערך שמוחזר על ידי הפונקציה canScheduleExactAlarms()
נשאר תקף לאורך כל מחזור החיים של האפליקציה.
כשההרשאה SCHEDULE_EXACT_ALARMS
ניתנת לאפליקציה, המערכת שולחת לה את השידור ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
. באפליקציה צריך להטמיע broadcast receiver שמבצע את הפעולות הבאות:
- מאשרים שלאפליקציה עדיין יש גישה מיוחדת. כדי לעשות זאת, מתקשרים למספר
canScheduleExactAlarms()
. הבדיקה הזו מגנה על האפליקציה במקרה שבו המשתמש מעניק לאפליקציה הרשאה, ואז מבטל אותה כמעט מיד לאחר מכן. - מתזמן מחדש את כל ההתראות המדויקות שהאפליקציה צריכה, בהתאם למצב הנוכחי שלה.
הלוגיקה הזו צריכה להיות דומה למה שהאפליקציה עושה כשהיא מקבלת את השידור
ACTION_BOOT_COMPLETED
.
בקשה מהמשתמשים להעניק הרשאה ל-SCHEDULE_EXACT_ALARM
במקרה הצורך, אפשר להפנות את המשתמשים למסך Alarms & reminders בהגדרות המערכת, כמו שמוצג באיור 1. כדי לעשות זאת, פועלים לפי השלבים הבאים:
- בממשק המשתמש של האפליקציה, צריך להסביר למשתמש למה האפליקציה צריכה לתזמן אזעקות מדויקות.
- מפעילים Intent שכולל את פעולת ה-Intent
ACTION_REQUEST_SCHEDULE_EXACT_ALARM
.
הגדרת התראה חוזרת
התראות חוזרות מאפשרות למערכת להודיע לאפליקציה שלכם על בסיס לוח זמנים חוזר.
התראה שתוכננה בצורה לא טובה עלולה לגרום לריקון הסוללה ולהעמיס עומס משמעותי על השרתים. לכן, ב-Android 4.4 (רמת API 19) ואילך, כל האזעקות החוזרות הן אזעקות לא מדויקות.
מאפיינים של שעון מעורר חוזר:
סוג ההתראה. מידע נוסף זמין במאמר בחירת סוג ההתראה.
שעת ההפעלה. אם שעת ההפעלה שציינתם היא בעבר, ההתראה תופעל מיד.
המרווח של ההתראה. לדוגמה, פעם ביום, כל שעה או כל 5 דקות.
כוונה בהמתנה שמופעלת כשההתראה מופעלת. כשמגדירים התראה שנייה שמשתמשת באותו pending intent, היא מחליפה את ההתראה המקורית.
כדי לבטל PendingIntent()
, מעבירים את FLAG_NO_CREATE
אל PendingIntent.getService()
כדי לקבל מופע של ה-Intent (אם הוא קיים), ואז מעבירים את ה-Intent אל AlarmManager.cancel()
.
Kotlin
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager val pendingIntent = PendingIntent.getService(context, requestId, intent, PendingIntent.FLAG_NO_CREATE) if (pendingIntent != null && alarmManager != null) { alarmManager.cancel(pendingIntent) }
Java
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); PendingIntent pendingIntent = PendingIntent.getService(context, requestId, intent, PendingIntent.FLAG_NO_CREATE); if (pendingIntent != null && alarmManager != null) { alarmManager.cancel(pendingIntent); }
בחירת סוג השעון המעורר
אחד הדברים הראשונים שצריך לקחת בחשבון כשמשתמשים בהתראה חוזרת הוא הסוג שלה.
יש שני סוגים כלליים של שעונים לאזעקות: 'זמן שחלף בזמן אמת' ו'שעון זמן אמת' (RTC). השעון שחלף בזמן אמת משתמש ב'זמן מאז הפעלת המערכת' כנקודת התייחסות, והשעון בזמן אמת משתמש בזמן UTC (שעון קיר). כלומר, הזמן שחלף בזמן אמת מתאים להגדרת שעון מעורר שמבוסס על חלוף הזמן (לדוגמה, שעון מעורר שמצלצל כל 30 שניות), כי הוא לא מושפע מאזור זמן או ממיקום. סוג השעון בזמן אמת מתאים יותר לשעונים מעוררים שתלויים במיקום הנוכחי.
לשני הסוגים יש גרסה של 'התעוררות', שאומרת למעבד של המכשיר להתעורר אם המסך כבוי. כך מוודאים שההתראה תופעל בזמן המתוזמן. האפשרות הזו שימושית אם האפליקציה שלכם תלויה בזמן. לדוגמה, אם יש לו חלון זמן מוגבל לביצוע פעולה מסוימת. אם לא משתמשים בגרסת ההשכמה של סוג השעון המעורר, כל השעונים המעוררים החוזרים יצלצלו בפעם הבאה שהמכשיר יתעורר.
אם אתם רק רוצים שההתראה תופעל במרווח זמן מסוים (למשל, כל חצי שעה), אתם יכולים להשתמש באחד מסוגי הזמן שחלפו מאז ההפעלה. בדרך כלל, זו הבחירה הטובה יותר.
אם אתם צריכים שההתראה תופעל בשעה מסוימת ביום, אתם צריכים לבחור באחד מסוגי השעון שמבוססים על שעון זמן אמת. עם זאת, חשוב לזכור שלגישה הזו יש כמה חסרונות. יכול להיות שהאפליקציה לא תתורגם טוב ללוקאלים אחרים, ואם המשתמש ישנה את הגדרת הזמן של המכשיר, יכול להיות שיופיעו באפליקציה התנהגויות לא צפויות. כמו כן, השימוש בסוג שעון מעורר של שעון זמן אמת לא מתאים לשינוי גודל, כפי שצוין למעלה. מומלץ להשתמש בהתראה מסוג 'זמן שעבר בזמן אמת' אם אפשר.
זו רשימת הסוגים:
ELAPSED_REALTIME
: מפעיל את הכוונה בהמתנה על סמך משך הזמן שעבר מאז הפעלת המכשיר, אבל לא מוציא את המכשיר ממצב שינה. הזמן שחלף כולל את כל הזמן שבו המכשיר היה במצב שינה.
ELAPSED_REALTIME_WAKEUP
: המכשיר מתעורר ומפעיל את הכוונה בהמתנה אחרי שחלף משך הזמן שצוין מאז הפעלת המכשיר.
RTC
: הכוונה התלויה ועומדת מופעלת בזמן שצוין, אבל המכשיר לא מופעל.
RTC_WAKEUP
: מעיר את המכשיר כדי להפעיל את הכוונה בהמתנה בזמן שצוין.
דוגמאות להתראות על זמן שחלף בזמן אמת
הנה כמה דוגמאות לשימוש ב-ELAPSED_REALTIME_WAKEUP
תעיר את המכשיר כדי להפעיל את ההתראה בעוד 30 דקות, וכל 30 דקות לאחר מכן:
Kotlin
// Hopefully your alarm will have a lower frequency than this! alarmMgr?.setInexactRepeating( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR, AlarmManager.INTERVAL_HALF_HOUR, alarmIntent )
Java
// Hopefully your alarm will have a lower frequency than this! alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR, AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);
כדי להפעיל התראה חד-פעמית (לא חוזרת) בעוד דקה, מוציאים את המכשיר ממצב שינה:
Kotlin
private var alarmMgr: AlarmManager? = null private lateinit var alarmIntent: PendingIntent ... alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent -> PendingIntent.getBroadcast(context, 0, intent, 0) } alarmMgr?.set( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60 * 1000, alarmIntent )
Java
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_WAKEUP
.
להוציא את המכשיר ממצב שינה כדי שהשעון המעורר יצלצל בערך בשעה 14:00, ו לחזור על הפעולה פעם ביום באותה השעה:
Kotlin
// Set the alarm to start at approximately 2:00 p.m. val calendar: Calendar = Calendar.getInstance().apply { timeInMillis = System.currentTimeMillis() 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.timeInMillis, AlarmManager.INTERVAL_DAY, alarmIntent )
Java
// 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);
מוציאים את המכשיר ממצב שינה כדי שהשעון המעורר יצלצל בדיוק בשעה 8:30 בבוקר, וכל 20 דקות לאחר מכן:
Kotlin
private var alarmMgr: AlarmManager? = null private lateinit var alarmIntent: PendingIntent ... alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent -> PendingIntent.getBroadcast(context, 0, intent, 0) } // Set the alarm to start at 8:30 a.m. val calendar: Calendar = Calendar.getInstance().apply { timeInMillis = System.currentTimeMillis() set(Calendar.HOUR_OF_DAY, 8) set(Calendar.MINUTE, 30) } // setRepeating() lets you specify a precise custom interval--in this case, // 20 minutes. alarmMgr?.setRepeating( AlarmManager.RTC_WAKEUP, calendar.timeInMillis, 1000 * 60 * 20, alarmIntent )
Java
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);
החליטו מה רמת הדיוק של השעון המעורר
כמו שצוין קודם, בחירת סוג ההתראה היא לרוב השלב הראשון ביצירת התראה. ההבדל הנוסף הוא רמת הדיוק שאתם צריכים בהתראה. ברוב האפליקציות, setInexactRepeating()
היא הבחירה הנכונה. כשמשתמשים בשיטה הזו, מערכת Android מסנכרנת כמה אזעקות חוזרות לא מדויקות ומפעילה אותן בו-זמנית. כך קצב התרוקנות הסוללה יפחת.
אם אפשר, כדאי להימנע משימוש בהתראות מדויקות. עם זאת, באפליקציות נדירות שיש להן דרישות זמן קשיחות, אפשר להגדיר שעון מעורר מדויק באמצעות קריאה ל-setRepeating()
.
ב-setInexactRepeating()
, אי אפשר לציין מרווח זמן מותאם אישית כמו ב-setRepeating()
.
צריך להשתמש באחד הקבועים של מרווחי הזמן, כמו
INTERVAL_FIFTEEN_MINUTES
,
INTERVAL_DAY
,
וכן הלאה. AlarmManager
הרשימה המלאה
ביטול התראה
בהתאם לאפליקציה, יכול להיות שתרצו לכלול אפשרות לביטול ההתראה.
כדי לבטל התראה, מתקשרים אל cancel()
ב-Alarm Manager ומעבירים את PendingIntent
שלא רוצים יותר להפעיל. לדוגמה:
Kotlin
// If the alarm has been set, cancel it. alarmMgr?.cancel(alarmIntent)
Java
// If the alarm has been set, cancel it. if (alarmMgr!= null) { alarmMgr.cancel(alarmIntent); }
הפעלת שעון מעורר כשהמכשיר מופעל מחדש
כברירת מחדל, כל האזעקות מבוטלות כשמכבים את המכשיר.
כדי למנוע את המצב הזה, אפשר לתכנן את האפליקציה כך שהיא תפעיל מחדש באופן אוטומטי אזעקה חוזרת אם המשתמש יפעיל מחדש את המכשיר. כך מוודאים שAlarmManager
ימשיך לבצע את המשימה בלי שהמשתמש יצטרך להפעיל מחדש את האזעקה באופן ידני.
אלה השלבים:
מגדירים את ההרשאה
RECEIVE_BOOT_COMPLETED
במניפסט של האפליקציה. ההרשאה הזו מאפשרת לאפליקציה לקבל אתACTION_BOOT_COMPLETED
שמשודר אחרי שהמערכת מסיימת את האתחול (ההרשאה הזו פועלת רק אם המשתמש כבר הפעיל את האפליקציה לפחות פעם אחת):<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
כדי לקבל את השידור, צריך להטמיע את
BroadcastReceiver
:Kotlin
class SampleBootReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == "android.intent.action.BOOT_COMPLETED") { // Set the alarm here. } } }
Java
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. } } }
מוסיפים את ה-receiver לקובץ המניפסט של האפליקציה עם מסנן Intent שמסנן את הפעולה
ACTION_BOOT_COMPLETED
:<receiver android:name=".SampleBootReceiver" android:enabled="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"></action> </intent-filter> </receiver>
שימו לב שבמניפסט, מקלט האתחול מוגדר ל-
android:enabled="false"
. המשמעות היא שהמקלט לא יופעל אלא אם האפליקציה תפעיל אותו באופן מפורש. כך נמנעת קריאה מיותרת של מקלט האתחול. כדי להפעיל מקלט (לדוגמה, אם המשתמש מגדיר שעון מעורר):Kotlin
val receiver = ComponentName(context, SampleBootReceiver::class.java) context.packageManager.setComponentEnabledSetting( receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP )
Java
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class); PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
אחרי שמפעילים את המקלט בדרך הזו, הוא יישאר מופעל גם אם המשתמש יפעיל מחדש את המכשיר. במילים אחרות, הפעלה פרוגרמטית של המקלט מבטלת את הגדרת המניפסט, גם אחרי הפעלה מחדש. המקלט יישאר מופעל עד שהאפליקציה תשבית אותו. אפשר להשבית את המקלט (לדוגמה, אם המשתמש מבטל את האזעקה) באופן הבא:
Kotlin
val receiver = ComponentName(context, SampleBootReceiver::class.java) context.packageManager.setComponentEnabledSetting( receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP )
Java
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class); PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
הפעלת אזעקות כשהמכשיר במצב שינה
במכשירים עם Android 6.0 (רמת API 23) יש תמיכה במצב שינה, שעוזר להאריך את חיי הסוללה של המכשיר. השעונים המעוררים לא יצלצלו כשהמכשיר נמצא במצב שינה. כל השעונים המעוררים שתוזמנו יופעלו רק כשהמכשיר יצא ממצב שינה. אם אתם צריכים להשלים עבודה גם כשהמכשיר לא פעיל, יש כמה אפשרויות:
מגדירים התראה מדויקת.
משתמשים ב-WorkManager API, שנועד לבצע עבודה ברקע. אתם יכולים לציין שהמערכת צריכה לזרז את העבודה כדי שהיא תסתיים בהקדם האפשרי. מידע נוסף זמין במאמר בנושא תזמון משימות באמצעות WorkManager
שיטות מומלצות
לכל בחירה שתעשו בתכנון של אזעקה חוזרת יכולות להיות השלכות על האופן שבו האפליקציה משתמשת במשאבי המערכת (או עושה בהם שימוש לרעה). לדוגמה, נניח שיש אפליקציה פופולרית שמסתנכרנת עם שרת. אם פעולת הסנכרון מבוססת על השעה, וכל מופע של האפליקציה מסתנכרן בשעה 23:00, העומס על השרת עלול לגרום לזמן אחזור ארוך או אפילו ל'מניעת שירות'. כדאי לפעול לפי השיטות המומלצות הבאות לשימוש בהתראות:
הוספת אקראיות (jitter) לכל בקשות הרשת שמופעלות כתוצאה מהתראה חוזרת:
לבצע עבודה מקומית כשההתראה מופעלת. 'עבודה מקומית' היא כל פעולה שלא מגיעה לשרת או שלא דורשת נתונים מהשרת.
במקביל, מתזמנים את השעון המעורר שמכיל את בקשות הרשת כך שיפעל בתקופת זמן אקראית.
כדאי להגדיר את תדירות ההתראות למינימום.
לא להפעיל את המכשיר שלא לצורך (ההתנהגות הזו נקבעת לפי סוג ההתראה, כמו שמתואר במאמר בחירת סוג התראה).
אל תגדירו את שעת ההפעלה של ההתראה בצורה מדויקת יותר ממה שצריך.
במקום
setRepeating()
, צריך להשתמש ב-setInexactRepeating()
. כשמשתמשים בsetInexactRepeating()
, מערכת Android מסנכרנת התרעות חוזרות מכמה אפליקציות ומפעילה אותן בו-זמנית. כך מצמצמים את מספר הפעמים הכולל שבהן המערכת צריכה להעיר את המכשיר, ולכן גם את ניצול הסוללה. החל מ-Android 4.4 (API ברמה 19), כל ההתראות החוזרות הן התראות לא מדויקות. הערה: למרות ש-setInexactRepeating()
הוא שיפור לעומתsetRepeating()
, הוא עדיין עלול לגרום לעומס יתר על השרת אם כל מופע של אפליקציה יפנה לשרת בערך באותו הזמן. לכן, כשמדובר בבקשות רשת, כדאי להוסיף קצת אקראיות לאזעקות, כמו שצוין קודם.אם אפשר, כדאי להימנע מהגדרת השעון המעורר לפי השעה.
שעונים מעוררים חוזרים שמבוססים על זמן טריגר מדויק לא מתאימים לשימוש נרחב. אם אפשר, משתמשים ב-
ELAPSED_REALTIME
. בקטע הבא יש תיאור מפורט של סוגי ההתראות השונים.