
WallpaperService שיורשת מ-Service. הפונקציה onBind מחזירה null, כי אין צורך להחליף מידע בין ה-Service לאפליקציה והוא צריך לפעול גם כשהאפליקציה סגורה.onCreate מפעילים את העבודה, אבל לא בתוך המחלקה עצמה. היא רצה באותו thread של האפליקציה, ולכן קוד ארוך שם יתחרה בקוד האפליקציה ועלול לתקוע אותה. לכן יוצרים Thread שמקבל אובייקט של WallpaperChanger ומפעילים אותו.Start Sticky, והיא מתאימה כאן, ולכן הפונקציה נשארת בהערה.Runnable. בפונקציה run יש לולאה שבודקת בכל סיבוב אם הגיעה שעה עגולה, ואם כן מחליפת את הרקע. בלי השהיה הלולאה תתפוס את ה-CPU, ולכן יש פונקציה sleepOneSecond שעושה Thread.sleep של 1000 מילי-שניות בתוך try catch.isRoundHour לוקחת Calendar ומחזירה true כשהדקות והשניות שווות 0.WallpaperManager.getInstance דורש Context, אבל WallpaperChanger אינה Activity או Service. הפתרון הוא מחלקה MyApp שיורשת מ-Application, שומרת Context סטטי ב-onCreate ומחזירה אותו בפונקציה סטטית getContext. חייבים לרשום אותה במאניפסט בשדה name.Math.random כפול 10 משמש כאינדקס (0 עד 9). את התמונה קובעים עם setResource בתוך try catch.Intent ו-startService (לא startActivity). את ה-Service רושמים במאניפסט, בדיוק כמו Activity או Broadcast Receiver.startService(intent) עם WallpaperService.classSET_WALLPAPER במאניפסט, כדי שהמשתמש ידע שהאפליקציה עשויה לשנות את הרקעMyApp.getContext() להשגת Context ממחלקה רגילההטקסט המלא של הדקות הראשונות בהרצאה «Create Service» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.
אז אנחנו מגיעים לדוגמה ליצירת סרוויס והסרוויס שאנחנו הולכים לבנות הולך לרוץ ברקע וכל שעה עגולה הולך לשנות את הרקע של המכשיר לאחד מסדרת רקעים שיש לנו פה בתיקיית drawable.
למה אנחנו צריכים לצורך כך סרוויס? כי אנחנו רוצים שגם אם היוזר ידליק את האפליקציה שלנו ואז יחבא אותה, עדיין משהו ירוץ ברקע מאחורי הקלעים ויבצע את הפעילות הזאת.
כל שעה עגולה תמצא רקע מסדרת רקעים רנדומליים ושים את הרקע הזה בתור הרקע של המכשיר. אז בואו נבנה את זה. הדבר הראשון שאנחנו צריכים לעשות זה פשוט להוסיף מחלקה שיורשת מהמחלקה סרוויס.
אז בואו נקרא למחלקה הזאת wallpaper service. בואו נצרף אותה. ואנחנו רוצים to extend את המחלקה Service. אנחנו רואים שאנחנו צריכים לממש מספר פונקציות.
בואו נגיע ל-Implement Methods ולמעשה זאת פונקציה אחת שנקראת onBind. פונקציית onBind זאת פונקציה שמופעלת כאשר ה-Service שלנו מקושר בלי הפסקה ל-Activity או לאפליקציה שלנו בכדי לבצע החלפת מידע בין ה-Service לבין האפליקציה.
אנחנו לא צריכים כל הזמן לשלוח מידע ולקבל מידע מהסרוויס, אנחנו בכלל רוצים שהסרוויס יופעל גם אם האפליקציה שלנו בכלל סגורה, ולכן אין לנו מה לעשות עם הפונקציה onBind, במקרה כזה אנחנו מחזירים ממנה נ"ל.
מה הדברים שאנחנו כן צריכים להגדיר בסרוויס? אנחנו צריכים לדרוס פונקציה שנקראת onCreate, שמופעלת אוטומטית כאשר הסרוויס מתחיל לפעול. הפונקציה הזאתי צריכה להכיל את הקוד.
מה הקוד שאנחנו רוצים? אנחנו רוצים לרוץ ולבדוק כל שנייה האם הגיעה כרגע שעה עגולה לגמרי. אם הגיעה שעה עגולה, אנחנו רוצים להחליף את ה-Background של המכשיר.
אבל אמרנו שאנחנו לא רוצים לבצע את הקוד הזה בתוך המחלקה הזאת, Wallpaper Service, שאנחנו בונים. למה? כי המחלקה שאנחנו בונים רצה בדיוק באותו ה-thread שמריץ את האפליקציה, ולכן אם נכתוב פה בדיוק קוד, אז הקוד הזה יתחרה בעצם עם קוד האפליקציה ויכול
להפריע לו, לחסום אותו ובכלל להאט את האפליקציה. לכן בדיוק כאן אנחנו רוצים לפתוח thread נפרד שהקוד שאנחנו בונים ירוץ ב-thread נפרד.
אבל לפני שנבצע את הקוד עצמו ב-thread נפרד, בואו נכיר עוד פונקציה. יש עוד פונקציה שנקראת onStartCommand. onStartCommand זאת פונקציה שאחראית להגדיר את ה-Behavior של הסרוויס מבחינת סטיקי או נון סטיקי.
By default, wallpaperService שיורש מסרוויס הוא StickyService, זאת אומרת הוא אוטומטית יופעל עם מסגירות האפליקציה.
אם אנחנו רוצים לשנות את זה אנחנו צריכים להחזיר מהפונקציה הזאת את אחד מהקבועים שראינו בסרטון הקודם, או Start Not Sticky או Redeliver Intent.
כמובן שהדיפולט זה Start Sticky. אז אנחנו בעצם לא צריכים בכלל לממש את הפונקציה הזאת, נשים אותה רק בהערה כי הדיפולט מתאים לנו.
אז בנקודה הזאת אנחנו יכולים לעצור ולגשת ולבנות מחלקה נפרדת שתרוץ ב-thread נפרד. פה אנחנו רוצים לבנות Thread ולהריץ את המחלקה שלנו.
אז בואו נעשה את זה, נצרף מחלקה חדשה, נקרא לה Wallpaper Changer, התפקיד שלה יהיה לרוץ ב-Thread נפרד ולשנות את ה-Wallpaper, כלומר את הרקע של המכשיר.
בכדי שניתן יהיה להריץ את המחלקה הזאת ב-Thread נפרד, בואו נממש את ה-Interface Runable. נממש אותו, יש לנו פה פונקציה אחת ויחידה שנקראת Run, והפונקציה הזאת מופעלת ב-thread נפרד.
מה אנחנו רוצים לעשות בפונקציה הזאת? אנחנו רוצים בפונקציה הזאת לבצע איזושהי לולאה, בוא נניח שכרגע זה יהיה while true, וכל רגע בלולאה אנחנו רוצים לבדוק האם כרגע הגיעה שעה עגולה.
אם כן, נא לשנות את רקע המכשיר. אבל אם אנחנו לא נעשה פה איזושהי השעיה, אז הלולאה הזאת סתם תטחן את מעבד המכשיר. איך עושים השהיה? בואו ניצר את זה באיזושהי פונקציה נפרדת, נקרא לה private void sleep one second ואנחנו רוצים על ידי try catch לבצע השהיה של 1000 מילי שניות דרכן
exception ובצורה כזאת והנה יש לנו פונקציה שאם אנחנו קוראים לה אז היא גורמת לטרד הזה להפסיק לפעול במשך שנייה אבל במשך כל השנייה הזאתי לא לטחון את ה-CPU, את המעבד של המכשיר.
לאחר מכן אנחנו רוצים לבדוק האם כרגע בדיוק הגיעה שעה עגולה. בואו נייצר פה עוד איזושהי פונקציה. private בוליאן is round hour.
ניקח calendar, calendar get instance, הנה הדקות, בואו נקבל על ידי calendar get את calendar minet, ויש לנו כרגע את הדקות של המכשיר, הנה יש לנו את ה-Second, Get Calendar Second ואנחנו רוצים להחזיר True אם עכשיו שעה עגולה.
מה זאת אומרת שעה עגולה? ה-Minate זה 0,0 וגם ה-Second שכרגע נמצאים במכשיר וגם 0,0 והנה יש לנו פה פונקציה בוליאנית נחמדה שאומרת לנו האם כרגע בדיוק זה שעה עגולה במכשיר.
אם כן אנחנו רוצים לקרוא לפונקציה שמשנה את הרקע. אז בואו נבנה אותה כאן: private void change wallpaper. איך אנחנו משנים את ה-wallpaper של המכשיר, את הרקע של המכשיר?
בואו רק שלא נשכח, נקרא לפונקציה הזאת מכאן, זה סוגר לנו את הלולאה הראשית. אז בכדי לשנות את ה-wallpaper של המכשיר אנחנו צריכים אובייקט מסוג wallpaper manager.
יש לנו דבר כזה, wallpaper-manager זה אובייקט שמסוגל לשנות את הרקע של המכשיר. אנחנו מקבלים wallpaper-manager.get-instance והנה איזושהי בעיה שאנחנו נתקלים בה עכשיו, הפונקציה get-instance רוצה מאיתנו קונטקסט אבל אנחנו לא אקטיביטי ואנחנו גם לא סרוויס, אנחנו סתם מחלקה שנקראת wallpaper-changer שאנחנו בונים
כרגע ואנחנו בהחלט לא קונטקסט אז איך אנחנו יכולים להעביר קונטקסט בצורה פשוטה אז טכניקה אחת שלמדנו שמאפשרת לעשות את זה זה יצירת מחלקה חדשה ראינו את זה באחד הסרטונים היותר רחוקים במודול הזה בקורס הזה שמאפשרת לתאר לנו או להביא לנו את הקונטקסט של האפליקציה קראנו בזמנו למחלקה הזאתי מיי אפ ומיי אפ יורשת את אפליקיישן
שזאת המחלקה שאחראית על כל האפליקציה ויש לנו פה פרייבט סטטיק קונטקסט ואובייקט הקונטקסט ויש לנו public void on create פונקציה שניגשת לסופר נקודה on create ובנוסף מכניסה לאובייקט הקונטקסט את get אפליקיישן קונטקסט וקיבלנו את הקונטקסט של האפליקציה.
בואו נבנה פה עוד איזושהי פונקציה סטטית שמחזירה את הקונטקסט, נקרא לה get קונטקסט ואנחנו מחזירים את אובייקט הקונטקסט העליון שיצרנו.
זאת אומרת איך שהאפליקציה רצה אנחנו רוצים להפעיל את הפונקציה הזאתי, היא למעשה תופעל אוטומטית, ייקח את הקונטקסט של האפליקציה, נשים פה באזור הגלובלי, ומי שרוצה שיקרא ויקבל אותו בלי קשר לשום אקטיביטי או לשום סרוויס.
בכדי שהמחלקה הזאת מיי-אפ תהיה באמת מחלקת האפליקציה שמתארת את האפליקציה הנוכחית, אנחנו היינו צריכים לגשת ל-manifest ולהגדיר פה name myapp וזהו. זה כל הטריק שמאפשר למחלקה המיוחדת הזאת שלנו להיות מחלקת האפליקציה עם קונטקסט סטטי שהוא נגיש לכולם.
אם סגרנו את הקונטקסט אנחנו יכולים לחזור לפה, לקרוא ל-myapp.getcontext והנה השגנו קונטקסט ממחלקה כלשהי שהיא לא אקטיביטי והיא לא סרוויס.
עכשיו מה שאנחנו רוצים לעשות זה קודם כל להגריל תמונה מסדרת התמונות שיש פה.