1. לפני שמתחילים
פיתוח אפליקציות באמצעות מפות Google מאפשר לכם להוסיף לאפליקציה תכונות כמו תמונות לוויין, אמצעי בקרה חזקים בממשק המשתמש של המפות, מעקב אחר מיקום וסמני מיקום. אתם יכולים להוסיף ערך למפות Google הרגילות על ידי הצגת מידע ממערך הנתונים שלכם, כמו מיקומים של אזורים מוכרים לדיג או לטיפוס. אפשר גם ליצור משחקים שבהם השחקן חוקר את העולם הפיזי, כמו בחיפוש אוצרות או אפילו במשחקי מציאות רבודה.
בשיעור הזה תיצרו אפליקציה של מפות Google בשם Wander, שמציגה מפות בהתאמה אישית ומראה את מיקום המשתמש.
דרישות מוקדמות
ידע בנושאים הבאים:
- איך ליצור אפליקציית Android בסיסית ולהפעיל אותה באמצעות Android Studio.
- איך ליצור ולנהל משאבים, כמו מחרוזות.
- איך לבצע רפקטורינג של קוד ולשנות את השם של משתנים באמצעות Android Studio.
- איך משתמשים במפת Google בתור משתמש.
- איך מגדירים הרשאות בזמן ריצה.
מה תלמדו
- איך מקבלים מפתח API מ-Google API Console ורושמים את המפתח באפליקציה
- איך משלבים מפת Google באפליקציה
- איך מציגים סוגים שונים של מפות
- איך משנים את הסגנון של מפת Google
- איך מוסיפים סמנים למפה
- איך מאפשרים למשתמש להציב סמן בנקודת עניין (POI)
- איך מפעילים את המעקב אחר המיקום
- איך יוצרים את אפליקציית
Wanderעם מפת Google מוטמעת - איך ליצור תכונות מותאמות אישית לאפליקציה, כמו סמנים וסגנונות
- איך מפעילים מעקב מיקום באפליקציה
2. סקירה כללית של האפליקציה
ב-Codelab הזה תיצרו את האפליקציה Wander, שמציגה מפת Google עם סגנון מותאם אישית. אפליקציית Wander מאפשרת להוסיף סמנים למיקומים, להוסיף שכבות-על ולראות את המיקום שלכם בזמן אמת.

3. משימה: הגדרת הפרויקט וקבלת מפתח API
SDK של מפות ל-Android דורש מפתח API. כדי לקבל את מפתח ה-API, צריך לרשום את הפרויקט בדף API & Services. מפתח ה-API קשור לאישור דיגיטלי שמקשר את האפליקציה ליוצר שלה. מידע נוסף על שימוש באישורים דיגיטליים ועל חתימה על האפליקציה זמין במאמר בנושא חתימה על האפליקציה.
ב-codelab הזה משתמשים במפתח ה-API לאישור הניפוי באגים. אישור הניפוי באגים לא מאובטח מעצם הגדרתו, כפי שמתואר במאמר בנושא חתימה על גרסת build לניפוי באגים. אפליקציות ל-Android שפורסמו ומשתמשות ב-SDK של מפות ל-Android דורשות מפתח API שני: המפתח של אישור הפרסום. מידע נוסף על קבלת אישור הפצה זמין במאמר בנושא קבלת מפתח API.
Android Studio כולל תבנית של פעילות במפות Google, שמייצרת קוד תבנית שימושי. קוד התבנית כולל קובץ google_maps_api.xml שמכיל קישור שמפשט את קבלת מפתח API.
שלב 1: יצירת פרויקט Wander באמצעות תבנית המפות
- יוצרים פרויקט חדש ב-Android Studio.
- בוחרים בתבנית פעילות במפות Google.

- נותנים שם לפרויקט
Wander. - מגדירים את רמת ה-API המינימלית ל-API 19. מוודאים שהשפה היא Kotlin.
- לוחצים על סיום.
- אחרי שהאפליקציה מסיימת את הבנייה, בודקים את הפרויקט ואת הקבצים הבאים שקשורים למפות שנוצרו בשבילכם על ידי Android Studio:
google_maps_api.xml – קובץ תצורה זה משמש לאחסון מפתח ה-API. התבנית יוצרת שני קובצי google_maps_api.xml: אחד לניפוי באגים ואחד לפרסום. הקובץ של מפתח ה-API לאישור ניפוי הבאגים נמצא בתיקייה src/debug/res/values. הקובץ של מפתח ה-API לאישור הגרסה נמצא בתיקייה src/release/res/values. ב-codelab הזה, משתמשים רק באישור לניפוי באגים.
activity_maps.xml – קובץ הפריסה הזה מכיל רכיב fragment יחיד שממלא את כל המסך. הסיווג SupportMapFragment הוא סיווג משנה של הסיווג Fragment. SupportMapFragment היא הדרך הכי פשוטה להציב מפה באפליקציה. זהו רכיב wrapper של תצוגת מפה שמטפל אוטומטית בצרכים של מחזור החיים.
אפשר לכלול את SupportMapFragment בקובץ פריסה באמצעות תג <fragment> בכל ViewGroup, עם מאפיין name נוסף.
android:name="com.google.android.gms.maps.SupportMapFragment"
MapsActivity.java – הקובץ MapsActivity.kt יוצר מופע של SupportMapFragment בשיטה onCreate(), ומשתמש ב-getMapAsync() של המחלקה כדי לאתחל אוטומטית את מערכת המפות ואת התצוגה. הפעילות שמכילה את SupportMapFragment חייבת להטמיע את הממשק OnMapReadyCallback ואת השיטה onMapReady() של הממשק הזה. השיטה onMapReady() מופעלת כשהמפה נטענת.
שלב 2: קבלת מפתח API
- פותחים את גרסת הניפוי באגים של הקובץ google_maps_api.xml.
- בקובץ, מחפשים תגובה עם כתובת URL ארוכה. הפרמטרים של כתובת ה-URL כוללים מידע ספציפי על האפליקציה.
- מעתיקים את כתובת ה-URL ומדביקים אותה בדפדפן.
- פועלים לפי ההנחיות ליצירת פרויקט בדף APIs & Services. בגלל הפרמטרים בכתובת ה-URL שצוינה, הדף יודע להפעיל באופן אוטומטי את SDK של מפות ל-Android.
- לוחצים על Create an API Key (יצירת מפתח API).
- בדף הבא, עוברים לקטע API Keys (מפתחות API) ולוחצים על המפתח שיצרתם.
- לוחצים על Restrict Key (הגבלת המפתח) ובוחרים באפשרות Maps SDK for Android (SDK של מפות ל-Android) כדי להגביל את השימוש במפתח לאפליקציות ל-Android.
- מעתיקים את מפתח ה-API שנוצר. היא מתחילה ב-
AIza". - בקובץ
google_maps_api.xml, מדביקים את המפתח במחרוזתgoogle_maps_keyבמקום שבו מופיע הכיתובYOUR_KEY_HERE. - מריצים את האפליקציה. אמורה להופיע פעילות עם מפה מוטמעת וסמן שמוגדר בסידני, אוסטרליה. (הסמן של סידני הוא חלק מהתבנית ואפשר לשנות אותו בהמשך).

שלב 3: משנים את השם של mMap
ל-MapsActivity יש lateinit פרטי var בשם mMap, שהוא מסוג GoogleMap. כדי לפעול בהתאם למוסכמות למתן שמות ב-Kotlin, משנים את השם של mMap ל-map.
- ב-
MapsActivity, לוחצים לחיצה ימנית עלmMapולוחצים על Refactor > Rename...

- משנים את שם המשתנה ל-
map.
שימו לב שכל ההפניות אל mMap בפונקציה onMapReady() משתנות גם הן ל-map.
4. משימה: הוספת סוגי מפות
ב-מפות Google יש כמה סוגי מפות: רגילה, היברידית, לוויין, פני שטח ו'ללא' (אם לא רוצים מפה בכלל).
|
|
|
|
מפה רגילה | מפת לוויין | מפה היברידית | מפת פני השטח |
כל סוג של מפה מספק סוגים שונים של מידע. לדוגמה, כשמשתמשים במפות לניווט ברכב, כדאי לראות את שמות הרחובות, ולכן אפשר להשתמש באפשרות הרגילה. כשאתם יוצאים לטיול רגלי, מפת פני השטח יכולה לעזור לכם להחליט כמה עוד אתם צריכים לטפס כדי להגיע לפסגה.
במשימה הזו:
- מוסיפים סרגל אפליקציות עם תפריט אפשרויות שמאפשר למשתמש לשנות את סוג המפה.
- מזיזים את מיקום ההתחלה במפה למיקום הבית שלכם.
- הוספת תמיכה בסמנים, שמציינים מיקומים בודדים במפה ויכולים לכלול תווית.
הוספת תפריט לסוגי מפות
בשלב הזה מוסיפים סרגל אפליקציות עם תפריט אפשרויות שמאפשר למשתמש לשנות את סוג המפה.
- כדי ליצור קובץ XML חדש של תפריט, לוחצים לחיצה ימנית על ספריית res ובוחרים באפשרות New (חדש) > Android Resource File (קובץ משאבים של Android).
- בתיבת הדו-שיח, נותנים שם לקובץ
map_options. - בוחרים באפשרות תפריט בשדה 'סוג המשאב'.
- לוחצים על אישור.
- בכרטיסייה Code (קוד), מחליפים את הקוד בקובץ החדש בקוד הבא כדי ליצור את אפשרויות התפריט של המפה. סוג המפה 'ללא' מושמט כי התוצאה של 'ללא' היא היעדר מפה בכלל. בשלב הזה מתרחשת שגיאה, אבל פותרים אותה בשלב הבא.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/normal_map"
android:title="@string/normal_map"
app:showAsAction="never" />
<item
android:id="@+id/hybrid_map"
android:title="@string/hybrid_map"
app:showAsAction="never" />
<item
android:id="@+id/satellite_map"
android:title="@string/satellite_map"
app:showAsAction="never" />
<item
android:id="@+id/terrain_map"
android:title="@string/terrain_map"
app:showAsAction="never" />
</menu>
- ב-
strings.xml, מוסיפים משאבים למאפייניםtitleכדי לפתור את השגיאות.
<resources>
...
<string name="normal_map">Normal Map</string>
<string name="hybrid_map">Hybrid Map</string>
<string name="satellite_map">Satellite Map</string>
<string name="terrain_map">Terrain Map</string>
<string name="lat_long_snippet">Lat: %1$.5f, Long: %2$.5f</string>
<string name="dropped_pin">Dropped Pin</string>
<string name="poi">poi</string>
</resources>
- ב-
MapsActivity, מבטלים את השיטהonCreateOptionsMenu()ויוצרים אוביקט תצוגה (inflate) של התפריט מקובץ המשאביםmap_options.
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.map_options, menu)
return true
}
- ב-
MapsActivity.kt, מחליפים את השיטהonOptionsItemSelected(). משנים את סוג המפה באמצעות קבועים של סוג המפה כדי לשקף את הבחירה של המשתמש.
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
// Change the map type based on the user's selection.
R.id.normal_map -> {
map.mapType = GoogleMap.MAP_TYPE_NORMAL
true
}
R.id.hybrid_map -> {
map.mapType = GoogleMap.MAP_TYPE_HYBRID
true
}
R.id.satellite_map -> {
map.mapType = GoogleMap.MAP_TYPE_SATELLITE
true
}
R.id.terrain_map -> {
map.mapType = GoogleMap.MAP_TYPE_TERRAIN
true
}
else -> super.onOptionsItemSelected(item)
}
- מפעילים את האפליקציה.
- לוחצים על הסמל
כדי לשנות את סוג המפה. שימו לב איך המראה של המפה משתנה בין המצבים השונים.

5. משימה: הוספת סמנים
כברירת מחדל, הקריאה החוזרת onMapReady() כוללת קוד שמציב סמן בסידני שבאוסטרליה, המקום שבו נוצרו מפות Google. פונקציית הקריאה החוזרת שמוגדרת כברירת מחדל גם מפעילה אנימציה של המפה כדי להזיז אותה לסידני.
במשימה הזו, תגרמו למצלמה במפה לנוע לבית שלכם, להגדיל את התצוגה לרמה שתציינו ולהציב שם סמן.
שלב 1: מתקרבים לבית ומוסיפים סמן
- בקבצים
MapsActivity.kt, מחפשים את השיטהonMapReady(). מסירים את הקוד שגורם למיקום הסמן בסידני ולהזזת המצלמה. כך השיטה אמורה להיראות עכשיו.
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
}
- כדי למצוא את קווי הרוחב והאורך של הבית, פועלים לפי ההוראות האלה.
- יוצרים ערך לקו הרוחב וערך לקו האורך, ומזינים את הערכים המספריים שלהם.
val latitude = 37.422160
val longitude = -122.084270
- יוצרים אובייקט
LatLngחדש בשםhomeLatLng. באובייקטhomeLatLng, מעבירים את הערכים שיצרתם.
val homeLatLng = LatLng(latitude, longitude)
- יוצרים
valכדי להגדיר את רמת הזום הרצויה במפה. משתמשים ברמת זום של 15f.
val zoomLevel = 15f
רמת הזום קובעת עד כמה התצוגה של המפה מוגדלת. הרשימה הבאה נותנת לכם מושג לגבי רמת הפירוט שמוצגת בכל רמת זום:
-
1: עולם -
5: מסת יבשה/יבשת 10: עיר-
15: רחובות -
20: מבנים
- כדי להזיז את המצלמה אל
homeLatLng, קוראים לפונקציהmoveCamera()באובייקטmapומעבירים אליה אובייקטCameraUpdateבאמצעותCameraUpdateFactory.newLatLngZoom(). מעבירים את אובייקטhomeLatLngואתzoomLevel.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
- הוספת סמן למפה במיקום
homeLatLng.
map.addMarker(MarkerOptions().position(homeLatLng))
השיטה הסופית אמורה להיראות כך:
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
//These coordinates represent the latitude and longitude of the Googleplex.
val latitude = 37.422160
val longitude = -122.084270
val zoomLevel = 15f
val homeLatLng = LatLng(latitude, longitude)
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
map.addMarker(MarkerOptions().position(homeLatLng))
}
- מריצים את האפליקציה. המפה אמורה להסתובב למיקום הבית, להתקרב לרמה הרצויה ולהציב סמן על הבית.

שלב 2: מאפשרים למשתמשים להוסיף סמן באמצעות לחיצה ארוכה
בשלב הזה, מוסיפים סמן כשהמשתמש לוחץ לחיצה ארוכה על מיקום במפה.
- יוצרים stub של method ב-
MapsActivityבשםsetMapLongClick()שמקבלGoogleMapכארגומנט. - מצרפים מאזין
setOnMapLongClickListenerלאובייקט המפה.
private fun setMapLongClick(map:GoogleMap) {
map.setOnMapLongClickListener { }
}
- ב-
setOnMapLongClickListener(), מבצעים קריאה ל-methodaddMarker(). מעבירים אובייקט חדש שלMarkerOptionsעם המיקום שמוגדר ל-LatLngשהועבר.
private fun setMapLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latLng ->
map.addMarker(
MarkerOptions()
.position(latLng)
)
}
}
- בסוף השיטה
onMapReady(), קוראים ל-setMapLongClick()עםmap.
override fun onMapReady(googleMap: GoogleMap) {
...
setMapLongClick(map)
}
- מפעילים את האפליקציה.
- לוחצים לחיצה ארוכה על המפה כדי למקם סמן במיקום מסוים.
- מקישים על הסמן כדי למרכז אותו במסך.

שלב 3: מוסיפים חלון מידע לסמן
בשלב הזה מוסיפים InfoWindow שמציג את הקואורדינטות של הסמן כשמקישים על הסמן.
- ב-
setMapLongClick()setOnMapLongClickListener(), יוצריםvalעבורsnippet. תקציר הוא טקסט נוסף שמוצג אחרי הכותרת. בקטע התקציר מוצגים קווי הרוחב והאורך של סמן.
private fun setMapLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latLng ->
// A snippet is additional text that's displayed after the title.
val snippet = String.format(
Locale.getDefault(),
"Lat: %1$.5f, Long: %2$.5f",
latLng.latitude,
latLng.longitude
)
map.addMarker(
MarkerOptions()
.position(latLng)
)
}
}
- ב-
addMarker(), מגדירים אתtitleשל הסמן ל-Dropped Pin באמצעות משאב מחרוזותR.string.dropped_pin. - מגדירים את
snippetשל הסמן ל-snippet.
הפונקציה המלאה נראית כך:
private fun setMapLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latLng ->
// A Snippet is Additional text that's displayed below the title.
val snippet = String.format(
Locale.getDefault(),
"Lat: %1$.5f, Long: %2$.5f",
latLng.latitude,
latLng.longitude
)
map.addMarker(
MarkerOptions()
.position(latLng)
.title(getString(R.string.dropped_pin))
.snippet(snippet)
)
}
}
- מפעילים את האפליקציה.
- לוחצים לחיצה ארוכה על המפה כדי להציב סמן מיקום.
- מקישים על הסמן כדי להציג את חלון המידע.

שלב 4: הוספת מאזין לנקודות עניין
כברירת מחדל, נקודות עניין מופיעות במפה עם הסמלים שלהן. נקודות העניין כוללות פארקים, בתי ספר, בנייני ממשלה ועוד. כשסוג המפה מוגדר לnormal, גם נקודות עניין עסקיות מופיעות במפה. נקודות עניין עסקיות מייצגות עסקים, כמו חנויות, מסעדות ומלונות.
בשלב הזה מוסיפים GoogleMap.OnPoiClickListener למפה. המאזין לקליקים הזה מציב סמן במפה באופן מיידי כשהמשתמש לוחץ על נקודת עניין. בנוסף, מאזין הקליקים מציג חלון מידע שמכיל את שם הנקודה.
- יוצרים stub של method ב-
MapsActivityבשםsetPoiClick()שמקבלGoogleMapכארגומנט. - בשיטה
setPoiClick(), מגדיריםOnPoiClickListenerב-GoogleMapשמועבר.
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
}
}
- ב-
setOnPoiClickListener(), יוצריםval poiMarkerלסמן . - מגדירים אותו לסמן באמצעות
map.addMarker()עםMarkerOptions, ומגדירים אתtitleלשם של נקודת העניין.
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
val poiMarker = map.addMarker(
MarkerOptions()
.position(poi.latLng)
.title(poi.name)
)
}
}
- בפונקציה
setOnPoiClickListener(), קוראים ל-showInfoWindow()ב-poiMarkerכדי להציג מיד את חלון המידע.
poiMarker.showInfoWindow()
הקוד הסופי של הפונקציה setPoiClick() אמור להיראות כך.
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
val poiMarker = map.addMarker(
MarkerOptions()
.position(poi.latLng)
.title(poi.name)
)
poiMarker.showInfoWindow()
}
}
- בסוף
onMapReady(), מתקשרים אלsetPoiClick()ומעבירים אתmap.
override fun onMapReady(googleMap: GoogleMap) {
...
setPoiClick(map)
}
- מריצים את האפליקציה ומחפשים נקודת עניין, כמו פארק או בית קפה.
- מקישים על נקודת העניין כדי להציב עליה סמן ולהציג את השם שלה בחלון מידע.

6. משימה: התאמה של סגנון המפה
יש הרבה דרכים להתאים אישית את מפות Google, כך שהמפה תיראה ותורגש ייחודית.
אפשר להתאים אישית אובייקט MapFragment באמצעות מאפייני ה-XML שזמינים, כמו שמתאימים אישית כל מקטע אחר. עם זאת, בשלב הזה מתאימים אישית את המראה והתחושה של התוכן של MapFragment, באמצעות שיטות באובייקט GoogleMap.
כדי ליצור סגנון מותאם אישית למפה, יוצרים קובץ JSON שמציין איך התכונות במפה מוצגות. לא צריך ליצור את קובץ ה-JSON הזה באופן ידני. Google מספקת את אשף הסגנונות של פלטפורמת מפות Google, שיוצר את ה-JSON בשבילכם אחרי שאתם מעצבים את המפה באופן חזותי. במשימה הזו, תעצבו את המפה עם עיצוב רטרו, כלומר המפה תשתמש בצבעים וינטג' ותוסיפו כבישים צבעוניים.
שלב 1: יוצרים סגנון למפה
- בדפדפן, עוברים אל https://mapstyle.withgoogle.com/.
- בוחרים באפשרות יצירת סגנון.
- בוחרים באפשרות רטרו.

- לוחצים על אפשרויות נוספות.

- בוחרים באפשרות כביש > מילוי.
- משנים את צבע הכבישים לצבע שבוחרים (למשל, ורוד).

- לוחצים על סיום.

- מעתיקים את קוד ה-JSON מתיבת הדו-שיח שמופיעה, ואם רוצים, שומרים אותו בהערה בטקסט פשוט לשימוש בשלב הבא.

שלב 2: הוספת הסגנון למפה
- ב-Android Studio, בספרייה
res, יוצרים ספריית משאבים ונותנים לה את השםraw. משתמשים במשאבי ספרייה כמו קוד JSON.raw - יוצרים קובץ ב-
res/rawבשםmap_style.json. - מדביקים את קוד ה-JSON ששמרתם בקובץ המשאב החדש.
- ב-
MapsActivity, יוצרים משתנה מחלקהTAGמעל השיטהonCreate(). הפרמטר הזה משמש למטרות רישום ביומן.
private val TAG = MapsActivity::class.java.simpleName
- בנוסף, ב-
MapsActivity, צריך ליצור פונקציהsetMapStyle()שמקבלתGoogleMap. - ב-
setMapStyle(), מוסיפים בלוקtry{}. - בבלוק
try{}, יוצריםval successכדי שהסגנון יצליח. (מוסיפים את בלוק ה-catch הבא). - בבלוק
try{}, מגדירים את סגנון ה-JSON למפה, ומפעילים אתsetMapStyle()באובייקטGoogleMap. מעבירים אובייקטMapStyleOptions, שמעלה את קובץ ה-JSON. - מקצים את התוצאה ל-
success. השיטהsetMapStyle()מחזירה ערך בוליאני שמציין את סטטוס ההצלחה של ניתוח קובץ הסגנון והגדרת הסגנון.
private fun setMapStyle(map: GoogleMap) {
try {
// Customize the styling of the base map using a JSON object defined
// in a raw resource file.
val success = map.setMapStyle(
MapStyleOptions.loadRawResourceStyle(
this,
R.raw.map_style
)
)
}
}
- מוסיפים משפט if לערך
successשהוא false. אם העיצוב לא מצליח, מדפיסים יומן שבו מצוין שהניתוח נכשל.
private fun setMapStyle(map: GoogleMap) {
try {
...
if (!success) {
Log.e(TAG, "Style parsing failed.")
}
}
}
- מוסיפים בלוק
catch{}כדי לטפל במצב של קובץ סגנון חסר. בבלוקcatch, אם אי אפשר לטעון את הקובץ, מוצגת השגיאהResources.NotFoundException.
private fun setMapStyle(map: GoogleMap) {
try {
...
} catch (e: Resources.NotFoundException) {
Log.e(TAG, "Can't find style. Error: ", e)
}
}
השיטה המלאה צריכה להיראות כמו קטע הקוד הבא:
private fun setMapStyle(map: GoogleMap) {
try {
// Customize the styling of the base map using a JSON object defined
// in a raw resource file.
val success = map.setMapStyle(
MapStyleOptions.loadRawResourceStyle(
this,
R.raw.map_style
)
)
if (!success) {
Log.e(TAG, "Style parsing failed.")
}
} catch (e: Resources.NotFoundException) {
Log.e(TAG, "Can't find style. Error: ", e)
}
}
- לבסוף, מבצעים קריאה לשיטה
setMapStyle()בשיטהonMapReady()ומעבירים את האובייקטGoogleMap.
override fun onMapReady(googleMap: GoogleMap) {
...
setMapStyle(map)
}
- מפעילים את האפליקציה.
- מגדירים את המפה למצב
normalוסגנון העיצוב החדש אמור להיות גלוי עם עיצוב רטרו וכבישים בצבע שבחרתם.

שלב 3: עיצוב הסמן
אפשר להתאים אישית את המפה עוד יותר על ידי שינוי הסגנון של סמני המפה. בשלב הזה, משנים את הסמנים האדומים שמוגדרים כברירת מחדל למשהו מגניב יותר.
- בשיטה
onMapLongClick(), מוסיפים את שורת הקוד הבאה ל-MarkerOptions()של ה-constructor כדי להשתמש בסמן ברירת המחדל, אבל לשנות את הצבע לכחול.
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
עכשיו onMapLongClickListener() נראה כך:
map.setOnMapLongClickListener { latLng ->
// A snippet is additional text that's displayed after the title.
val snippet = String.format(
Locale.getDefault(),
"Lat: %1$.5f, Long: %2$.5f",
latLng.latitude,
latLng.longitude
)
map.addMarker(
MarkerOptions()
.position(latLng)
.title(getString(R.string.dropped_pin))
.snippet(snippet)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
)
}
- מריצים את האפליקציה. הסמנים שמופיעים אחרי לחיצה ארוכה מוצלים עכשיו בכחול. שימו לב שסמני הנקודות עדיין אדומים כי לא הוספתם סגנון לשיטה
onPoiClick().

7. משימה: הוספת שכבת-על
אחת הדרכים להתאמה אישית של מפת Google היא לצייר עליה. הטכניקה הזו שימושית אם רוצים להדגיש סוג מסוים של מיקום, כמו מקומות פופולריים לדיג.
- צורות: אפשר להוסיף למפה קווי פוליגון, פוליגונים ומעגלים.
GroundOverlayאובייקטים: שכבת-על של קרקע היא תמונה שמקובעת למפה. שלא כמו סמנים, שכבות-על של הקרקע מכוונות לפני השטח של כדור הארץ ולא למסך. סיבוב, הטיה או שינוי הזום של המפה משנים את הכיוון של התמונה. שכבות על של תמונות שימושיות כשרוצים להציג תמונה אחת באזור מסוים במפה.
שלב: הוספת שכבת-על של תמונה
במשימה הזו מוסיפים שכבת-על של תמונה בצורת Android למיקום הבית.
- מורידים את תמונת Android הזו ושומרים אותה בתיקייה
res/drawable. (חשוב לוודא ששם הקובץ הואandroid.png).

- ב-
onMapReady(), אחרי הקריאה להזזת המצלמה לעמדת המוצא, יוצרים אובייקטGroundOverlayOptions. - מקצים את האובייקט למשתנה שנקרא
androidOverlay.
val androidOverlay = GroundOverlayOptions()
- משתמשים בשיטה
BitmapDescriptorFactory.fromResource()כדי ליצור אובייקטBitmapDescriptorממשאב התמונה שהורד. - מעבירים את אובייקט
BitmapDescriptorשנוצר לשיטהimage()של אובייקטGroundOverlayOptions.
val androidOverlay = GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(R.drawable.android))
- יוצרים
float overlaySizeלרוחב במטרים של שכבת העל הרצויה. בדוגמה הזו, רוחב של100fמתאים.
מגדירים את המאפיין position לאובייקט GroundOverlayOptions על ידי הפעלת השיטה position(), ומעבירים את האובייקט homeLatLng ואת overlaySize.
val overlaySize = 100f
val androidOverlay = GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(R.drawable.android))
.position(homeLatLng, overlaySize)
- מתקשרים אל
addGroundOverlay()באובייקטGoogleMapומעבירים את האובייקטGroundOverlayOptions.
map.addGroundOverlay(androidOverlay)
- מפעילים את האפליקציה.
- כדי לראות את תמונת Android כשכבת-על, משנים את הערך של
zoomLevelל-18f.

8. משימה: הפעלת מעקב אחר מיקום
משתמשים לרוב במפות Google כדי לראות את המיקום הנוכחי שלהם. כדי להציג את מיקום המכשיר במפה, אפשר להשתמש בשכבת נתוני המיקום.
שכבת נתוני המיקום מוסיפה למפה את הסמל המיקום שלי.

כשהמשתמש מקיש על הכפתור, המפה מתמקדת במיקום המכשיר. המיקום מוצג כנקודה כחולה אם המכשיר נייח, וכשרון כחול אם המכשיר בתנועה.
במשימה הזו מפעילים את שכבת נתוני המיקום.
שלב: שליחת בקשה להרשאות מיקום
כדי להפעיל את מעקב המיקום במפות Google, צריך להוסיף שורת קוד אחת. עם זאת, אתם צריכים לוודא שהמשתמש העניק הרשאות מיקום (באמצעות מודל ההרשאות בזמן הריצה).
בשלב הזה, שולחים בקשה להרשאות מיקום ומפעילים את מעקב המיקום.
- בקובץ
AndroidManifest.xml, מוודאים שההרשאהFINE_LOCATIONכבר קיימת. ההרשאה הזו נוספה על ידי Android Studio כשבחרתם בתבנית של מפות Google.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- ב-
MapsActivity, יוצרים משתנה מחלקהREQUEST_LOCATION_PERMISSION.
private val REQUEST_LOCATION_PERMISSION = 1
- כדי לבדוק אם ההרשאות ניתנו, יוצרים שיטה ב-
MapsActivityבשםisPermissionGranted(). בשיטה הזו, בודקים אם המשתמש העניק את ההרשאה.
private fun isPermissionGranted() : Boolean {
return ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
- כדי להפעיל את מעקב המיקום באפליקציה, יוצרים שיטה ב-
MapsActivityבשםenableMyLocation()שלא מקבלת ארגומנטים ולא מחזירה כלום. בתוך הקובץ, בודקים את ההרשאהACCESS_FINE_LOCATION. אם ההרשאה ניתנה, מפעילים את שכבת המיקום. אם לא, צריך לבקש את ההרשאה.
private fun enableMyLocation() {
if (isPermissionGranted()) {
map.isMyLocationEnabled = true
}
else {
ActivityCompat.requestPermissions(
this,
arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_LOCATION_PERMISSION
)
}
}
- מתקשרים אל
enableMyLocation()מהקריאה החוזרתonMapReady()כדי להפעיל את שכבת המיקום.
override fun onMapReady(googleMap: GoogleMap) {
...
enableMyLocation()
}
- מבטלים את השיטה
onRequestPermissionsResult(). בודקים אםrequestCodeשווה ל-REQUEST_LOCATION_PERMISSION. אם כן, המשמעות היא שההרשאה ניתנה. אם ההרשאה ניתנה, צריך גם לבדוק אם המערךgrantResultsמכיל את הערךPackageManager.PERMISSION_GRANTEDבמשבצת הראשונה שלו. אם זה נכון, צריך להתקשר למספרenableMyLocation().
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray) {
if (requestCode == REQUEST_LOCATION_PERMISSION) {
if (grantResults.contains(PackageManager.PERMISSION_GRANTED)) {
enableMyLocation()
}
}
}
- מריצים את האפליקציה. אמור להופיע דו-שיח עם בקשה לגישה למיקום המכשיר. אפשר לאשר את ההרשאה.

המיקום הנוכחי של המכשיר מוצג במפה באמצעות נקודה כחולה. שימו לב שיש כפתור למיקום. אם מזיזים את המפה מהמיקום שלכם ולוחצים על הלחצן הזה, המפה מתמרכזת בחזרה למיקום של המכשיר.

9. קוד הפתרון
מורידים את הקוד של ה-Codelab המוגמר.
$ git clone https://github.com/googlecodelabs/android-kotlin-geo-maps
אפשר גם להוריד את המאגר כקובץ ZIP, לבטל את הדחיסה שלו ולפתוח אותו ב-Android Studio.
10. סיכום
מעולה! הוספתם מפת Google לאפליקציית Android Kotlin ועיצבתם אותה.
11. מידע נוסף
מסמכי התיעוד למפתחים בנושא Android:
מסמכי עזר:
12. ה-Codelab הבא
קישורים ל-codelab אחרים בקורס הזה מופיעים בדף הנחיתה של ה-codelab בנושא Android מתקדם ב-Kotlin.



