במאמר הזה מוסבר מהו גידור גיאוגרפי בצד הלקוח, מתי כדאי להשתמש בו ואיך להחיל אותו על תרחישי שימוש באפליקציה לנייד. בנוסף, מוצגות בו הוראות להטמעה של דוגמה ב-Android באמצעות Google Navigation SDK.

לעתים קרובות חברות צריכות לדעת מתי מכשיר נייד נכנס לאזור מסוים או יוצא ממנו. הדבר מתבצע באמצעות שמירה על גבולות גיאוגרפיים וירטואליים, או גדרות וירטואליות, שמאפשרות לתוכנה להפעיל אירועים כשמכשיר חוצה גבול.
הבנה של מקרים שבהם רכב מסוים חוצה גבול חשובה למספר תרחישי שימוש, כמו:
- מעורבות לקוחות: עסקים יכולים להשתמש בגדרות וירטואליות כדי לשלוח התראות פוש למשתמשי קצה לגבי מבצעים מיוחדים, אירועים או מוצרים חדשים.
- אבטחה ובטיחות: עסקים יכולים להשתמש בגדרות וירטואליות כדי ליצור גבולות וירטואליים סביב אזורים רגישים, כמו מרכזי נתונים או מחסנים, ולהתריע לאנשי האבטחה אם מישהו נכנס לאזור או יוצא ממנו.
- תחבורה: עסקים יכולים להשתמש בגידור גיאוגרפי כדי לעקוב אחרי המיקום של כלי רכב ולבצע אופטימיזציה של מסלולים ולוחות זמנים.
לכן חשוב לדעת איך לייצג את האזורים האלה (מצולעים) באפליקציה שפונה ללקוח. האפליקציה הזו צריכה לעקוב אחרי מיקום המכשיר ולבדוק אם הוא חרג מגדר וירטואלית מסוימת.
היקף
המאמר הזה מתמקד בהטמעה של גיאופנסינג מצד הלקוח . כלומר, באפליקציית הלקוח צריכים להיות:
- הפוליגונים שצריך לבדוק אם יש בהם חריגות.
- המיקום בזמן אמת של המשתמש
- לוגיקה לבדיקה אם המיקום הנוכחי נמצא בתוך אחד מהפוליגונים או מחוצה לו.
המדריך הזה כולל דוגמאות ל-Android, אבל יש דרכים מקבילות לעשות את זה ב-iOS. לשירות המיקום של Android יש הטמעה מובנית של גדרות וירטואליות עגולות, שאפשר לראות כאן. קוד ההפניה והתיאור שבהמשך הם נקודת התחלה להטמעות מורכבות יותר.
Navigation SDK
Navigation SDK היא ספריית Native ל-Android או ל-iOS שמוסיפים לאפליקציית הנהג. היא אחראית ל:
- קבלת מיקומים שמוצמדים לכביש מהאפליקציה שמריצה אותו. המיקום הזה מדויק יותר מ-FusedLocationProvider (FLP) של Android, כי הוא משתמש ברשת הכבישים של Google כדי להצמיד מיקומים לקטע הכביש הקרוב ביותר, וכך הערכת זמן ההגעה מדויקת יותר. הוא גם משתמש במידע אחר מ-FLP.
- חוויית ניווט מפורט שמאפשרת לנהגים להגיע מנקודה א' לנקודה ב' ביעילות, תוך התחשבות במצב התנועה בזמן אמת ובמגבלות אחרות במסלול.
- הפעלת אירועים באמצעות פונקציות event listener וקריאות חוזרות (callback) רשומות.
פונקציות מסוג Listener
ב-Navigation SDK יש הרבה מאזינים שאפשר להשתמש בהם. לדוגמה:
- שינויים במיקום באמצעות הספק RoadSnappedLocation.
- ניתוב מחדש של אירועים (המשתמש פספס פניית פרסה, פנייה שמאלה וכו' וסטה מהמסלול המומלץ) באמצעות ReroutingListener.
- אירועי הגעה (המשתמש מגיע ליעד המתוכנן) באמצעות ArrivalListener.
- אירועים של מרחק שנותר וזמן משוער להגעה (קבלת התראה כשהנהג עומד להגיע ליעד – על סמך מטרים, קבלת התראה כשהנהג עומד להגיע ליעד – על סמך זמן) – שניהם זמינים דרך RemainingTimeOrDistanceChangedListener.
במדריך הזה נעשה שימוש רק ב-RoadSnappedLocationProvider וב-LocationListener שלו.
פתרון הגידור הגיאוגרפי בצד הלקוח
עכשיו נסביר איך לבנות יכולת גידור גיאוגרפי בצד הלקוח. בדוגמה שלמטה, Navigation SDK פועל במצב של הנחיות נסיעה מפורטות, ומוגדר מצולע במסלול שמייצג את הגדר הגיאוגרפית שלנו.
- הגדרות הגידור הגיאוגרפי מאוחסנות ב-BigQuery ונשלפות על ידי ה-Backend.
- הקצה העורפי דוחף מעת לעת את הגדרות הגיאוגרפיות לאפליקציות של Drive.
- הנהג מנווט והאפליקציה לנהגים בודקת באופן קבוע את הגדרות הגיאוגרפיות כדי לזהות טריגר.
- אפליקציית הנהג שולחת הודעה על אירוע מפעיל אל ה-Backend כדי שהוא יוכל לפעול.
בזמן שהרכב נע לאורך המסלול, האפליקציה בודקת באופן קבוע אם יש חדירה למצולע. כשהאפליקציה מזהה שהיא חצתה גבול וירטואלי, מוצגת בממשק המשתמש ההודעה: הגבול הווירטואלי נחצה.
הגדרת יחסי תלות עבור Android-Maps-Utils
בפתרון הזה נעשה שימוש ב-Android-Maps-Utils, ספרייה בקוד פתוח שמכילה כלי עזר שימושיים למגוון רחב של אפליקציות שמשתמשות ב-Google Maps Android API.
הספרייה הזו היא ציבורית, היא מתארחת ב-GitHub ואפשר לגשת אליה בכתובת:
- Android: https://github.com/googlemaps/android-maps-utils
- iOS: https://github.com/googlemaps/google-maps-ios-utils
כדי לכלול את הספרייה הזו באפליקציית Android (היקף המסמך הזה), צריך לשנות את הקובץ build.gradle כדי לכלול אותה. שימו לב: קובץ build.gradle הזה הוא של המודול (האפליקציה) שאתם בונים, ולא ברמת הפרויקט.
dependencies {
...
// Utilities for Maps SDK for Android (requires Google Play Services)
implementation 'com.google.maps.android:android-maps-utils:2.3.0'
}
אחר כך, אחרי שמסנכרנים את Gradle עם קובץ build.gradle העדכני, אפשר לייבא את com.google.maps.android.PolyUtil בקובץ Java:
import com.google.android.gms.maps.model.PolygonOptions;
import com.google.maps.android.PolyUtil;
הגדרת גבולות וירטואליים
שימו לב שגם PolygonOptions
מיובא כאן. הסיבה לכך היא שזה מה שמשמש לייצוג הפוליגון:
mPolygonOptions = new PolygonOptions()
.add(new LatLng(29.4264525,-98.4948758))
.add(new LatLng(29.4267029,-98.4948758))
.add(new LatLng(29.4273742,-98.4945822))
.add(new LatLng(29.4264562,-98.4943592))
.fillColor(0x0000ff36)
.strokePattern(Arrays.asList(new Dash(45.0f), new Gap(10.0f)))
.strokeColor(Color.BLUE)
.strokeWidth(5);
כפי שאפשר לראות למעלה, כאן אנחנו מגדירים מצולע קבוע עם קואורדינטות שהוגדרו מראש – זוגות של (קו רוחב, קו אורך). עם זאת, בתרחישים אמיתיים, הקואורדינטות והגדרות המצולעים האלה יגיעו ברוב המקרים מנקודת קצה בעורף האפליקציה, וכנראה שיישלפו מרחוק. כלומר, האפליקציה תצטרך ליצור את הפוליגונים תוך כדי תנועה.
מידע נוסף על מה שאפשר לציין ב-PolygonOptions
זמין כאן.
צריך להגדיר את המצולעים במהלך היצירה של Fragment או Activity. לדוגמה:
protected void onCreate(Bundle savedInstanceState) {
...
mPolygonOptions = new PolygonOptions()
.add(new LatLng(29.4264525,-98.4948758))
.add(new LatLng(29.4267029,-98.4948758))
.add(new LatLng(29.4273742,-98.4945822))
.add(new LatLng(29.4264562,-98.4943592))
.fillColor(0x0000ff36)
.strokePattern(Arrays.asList(new Dash(45.0f), new Gap(10.0f)))
.strokeColor(Color.BLUE)
.strokeWidth(5);
...// more code here
}
האזנה לעדכוני מיקום
אחרי שמגדירים את הגדרות הגיאוגרפיות, צריך ליצור מאזין לעדכוני מיקום כדי להירשם לאירוע שצוין למעלה ב-Navigation SDK שנקרא RoadSnappedLocationProvider
. האירוע הזה יחזיר את המיקום האחרון של המכשיר.
mLocListener = new RoadSnappedLocationProvider.LocationListener() {
@Override
public void onLocationChanged(Location snapped) {
LatLng snappedL = new LatLng(snapped.getLatitude(), snapped.getLongitude());
if(PolyUtil.containsLocation(snappedL, mPolygonOptions.getPoints(), true) && !mGeofenceBreached){
Log.d("Geofence", "Vehicle has breached the polygon");
}
}
@Override
public void onRawLocationUpdate(Location location) {
}
};
אחרי שמשתמשים ב-Android-Maps-Utils, אפשר להשתמש ב-PolyUtil.containsLocation
כדי לבדוק אם המיקום שהתקבל נמצא בתוך המצולע שהוגדר מראש. בדוגמה שלמטה נעשה שימוש במצולע מוגדר מראש שמייצג את הגדר הגיאוגרפית, אבל בפועל יכול להיות שיהיו לכם כמה מצולעים ותצטרכו להשתמש בלולאה.
גישה חלופית
המאמר הזה מתמקד באפליקציה שפונה ללקוח ומבצעת בדיקה של חדירה לגדר וירטואלית מותאמת אישית (מצולע). עם זאת, יש תרחישים שבהם כדאי לבצע בדיקות כאלה בקצה העורפי.
כלומר, האפליקציה תדווח על עדכוני מיקום לשרת עורפי, והשרת העורפי יבדוק אם הרכב חרג ממצולע מסוים, כך שהאימות לא יהיה תלוי באפליקציית הלקוח.
פתרון אפשרי:
[סביבת הפעלה] ארכיטקטורה של גידור גיאוגרפי בצד השרת
דוגמה לארכיטקטורה שממחישה גישה לגידור גיאוגרפי בצד השרת.

- אפליקציית הנהג, שמשתמשת ב-Driver SDK, שולחת עדכוני מיקום ל-Fleet Engine. עדכוני מיקום וניווט בתוך האפליקציה מתבצעים באמצעות Navigation SDK.
- מערכת Fleet Engine מוציאה את העדכונים האלה ל-Cloud Logging או ל-Pub/Sub.
- הקצה העורפי אוסף את אותות המיקום האלה.
- הגדרות של גדרות וירטואליות מאוחסנות ב-BigQuery לצורך ניתוח על ידי ה-Backend.
- כשגדר וירטואלית מופעלת, התראות נשלחות לאפליקציית הנהג.
בארכיטקטורה הזו נעשה שימוש ב-Driver SDK וב-Fleet Engine. Fleet Engine יכול לשלוח עדכונים ל-PubSub וליצור רשומות ביומן ב-Cloud Logging. בשני המקרים, אפשר לאחזר את מיקום הרכב.
הקצה העורפי יכול לעקוב אחרי תור PubSub או לקרוא יומנים ולחפש עדכונים לגבי הרכב. לאחר מכן, בכל פעם שמתרחש עדכון (או כל כמה שניות או דקות, בהתאם לחשיבות העדכון), ה-backend יכול לקרוא לפונקציות של BigQuery GIS כדי לקבוע אם רכב מסוים נמצא בתוך גדרות וירטואליות או מחוץ להן. אם יש חדירה לגדר וירטואלית אחת או יותר, ה-backend יכול לפעול ולהפעיל צינורות פנימיים או תהליכי עבודה רלוונטיים אחרים.
סיכום
גידור גיאוגרפי הוא כלי רב-עוצמה שאפשר להשתמש בו למטרות שונות. עסקים יכולים להשתמש בגדרות וירטואליות כדי לטרגט משתמשי קצה עם מודעות ומבצעים רלוונטיים, לספק שירותים מבוססי-מיקום ולשפר את האבטחה.
Navigation SDK מספק מאזינים שימושיים לאירועים שיכולים לזהות הרבה רגעים חשובים במהלך נסיעה. חברות לרוב דורשות גדרות וירטואליות מותאמות אישית לתרחישי שימוש ספציפיים. במסמך הזה הצגנו דרך להשיג את המטרה הזו, אבל האפשרויות הן אינסופיות. אנחנו סקרנים לראות מה תצליחו ליצור.
הפעולות הבאות
- מומלץ לצפות בסמינר האינטרנטי Explore, learn, and get inspired by what’s possible with Google Maps Platform.
הצעות לקריאה נוספת: