ה-codelab הזה הוא חלק מהקורס Advanced Android in Kotlin (פיתוח מתקדם ל-Android ב-Kotlin). כדי להפיק את המרב מהקורס הזה, מומלץ לעבוד על ה-codelabs לפי הסדר, אבל זה לא חובה. כל ה-codelab של הקורס מפורטים בדף הנחיתה של ה-codelab בנושא Android מתקדם ב-Kotlin.
פיתוח אפליקציות באמצעות מפות Google מאפשר לכם להוסיף לאפליקציה תכונות כמו תמונות לוויין, אמצעי בקרה חזקים בממשק המשתמש של המפות, מעקב אחר מיקום וסמני מיקום. אתם יכולים להוסיף ערך למפות Google הרגילות על ידי הצגת מידע ממערך הנתונים שלכם, כמו מיקומים של אזורים מוכרים לדיג או לטיפוס. אפשר גם ליצור משחקים שבהם השחקן חוקר את העולם הפיזי, כמו משחקי חפש את המטמון או משחקי מציאות רבודה.
בשיעור הזה תיצרו אפליקציה של מפות Google בשם Wander, שמציגה מפות בהתאמה אישית ומראה את מיקום המשתמש.
דרישות מוקדמות
ידע בנושאים הבאים:
- איך ליצור אפליקציית Android בסיסית ולהריץ אותה באמצעות Android Studio.
- איך ליצור ולנהל משאבים, כמו מחרוזות.
- איך לבצע רפקטורינג של קוד ולשנות את השם של משתנים באמצעות Android Studio.
- איך משתמשים במפת Google בתור משתמש.
- איך מגדירים הרשאות בזמן ריצה.
מה תלמדו
- איך מקבלים מפתח API מ-Google API Console ורושמים את המפתח באפליקציה
- איך משלבים מפת Google באפליקציה
- איך מציגים סוגים שונים של מפות
- איך משנים את הסגנון של מפת Google
- איך מוסיפים סמנים למפה
- איך מאפשרים למשתמש להציב סמן על נקודת עניין (POI)
- איך מפעילים את המעקב אחר המיקום
- איך יוצרים את אפליקציית
Wander
עם מפת Google מוטמעת - איך ליצור תכונות מותאמות אישית לאפליקציה, כמו סמנים וסגנונות
- איך מפעילים מעקב מיקום באפליקציה
ב-codelab הזה יוצרים את אפליקציית Wander
, שמציגה מפת Google עם סגנון מותאם אישית. אפליקציית Wander מאפשרת להוסיף סמנים למיקומים, להוסיף שכבות-על ולראות את המיקום שלכם בזמן אמת.
נדרש מפתח API לשימוש ב-Maps SDK ל-Android. כדי לקבל את מפתח ה-API, צריך לרשום את הפרויקט בדף API & Services. מפתח ה-API קשור לאישור דיגיטלי שמקשר את האפליקציה ליוצר שלה. מידע נוסף על שימוש בתעודות דיגיטליות ועל חתימה על האפליקציה זמין במאמר בנושא חתימה על האפליקציה.
ב-codelab הזה משתמשים במפתח ה-API לאישור הניפוי באגים. אישור הניפוי באגים לא מאובטח מעצם הגדרתו, כפי שמתואר במאמר חתימה על גרסת ניפוי הבאגים. אפליקציות ל-Android שפורסמו ומשתמשות ב-Maps SDK for 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 שצוינה, הדף יודע להפעיל אוטומטית את Maps 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
.
ב-Google Maps יש כמה סוגי מפות: רגילה, היברידית, לוויין, פני שטח ו'ללא' (אם לא רוצים מפה בכלל).
מפה רגילה | מפת לוויין | מפה היברידית | מפת פני השטח |
כל סוג של מפה מספק סוגים שונים של מידע. לדוגמה, כשמשתמשים במפות לניווט ברכב, כדאי לראות את שמות הרחובות, ולכן אפשר להשתמש באפשרות הרגילה. כשאתם יוצאים לטיול רגלי, מפת הטופוגרפיה יכולה לעזור לכם להבין כמה עוד אתם צריכים לטפס כדי להגיע לפסגה.
במשימה הזו:
- מוסיפים סרגל אפליקציות עם תפריט אפשרויות שמאפשר למשתמש לשנות את סוג המפה.
- מזיזים את מיקום ההתחלה במפה למיקום הבית שלכם.
- הוספת תמיכה בסמנים, שמציינים מיקומים בודדים במפה ויכולים לכלול תווית.
הוספת תפריט לסוגי מפות
בשלב הזה מוסיפים סרגל אפליקציות עם תפריט אפשרויות שמאפשר למשתמש לשנות את סוג המפה.
- כדי ליצור קובץ XML חדש של תפריט, לוחצים לחיצה ימנית על ספריית res ובוחרים באפשרות New > Android Resource File (קובץ משאב של Android).
- בתיבת הדו-שיח, נותנים שם לקובץ
map_options
. - בוחרים באפשרות תפריט בשדה 'סוג המשאב'.
- לוחצים על אישור.
- בכרטיסייה קוד, מחליפים את הקוד בקובץ החדש בקוד הבא כדי ליצור את אפשרויות התפריט של המפה. סוג המפה 'none' לא נכלל כי הוא גורם לכך שלא מוצגת מפה בכלל. בשלב הזה מתרחשת שגיאה, אבל פותרים אותה בשלב הבא.
<?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()
ומנפחים את התפריט מקובץ המשאבים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)
}
- מפעילים את האפליקציה.
- לוחצים על
כדי לשנות את סוג המפה. שימו לב איך המפה נראית במצבים השונים.
כברירת מחדל, הקריאה החוזרת 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
: World -
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 של שיטה ב-
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: הוספת מאזין לנקודות עניין
כברירת מחדל, נקודות עניין (POI) מופיעות במפה עם הסמלים המתאימים שלהן. נקודות העניין כוללות פארקים, בתי ספר, בנייני ממשלה ועוד. כשסוג המפה מוגדר לnormal
, גם נקודות עניין עסקיות מופיעות במפה. נקודות עניין עסקיות מייצגות עסקים, כמו חנויות, מסעדות ומלונות.
בשלב הזה מוסיפים GoogleMap.OnPoiClickListener
למפה. המאזין לקליקים הזה מציב סמן במפה באופן מיידי כשמשתמש לוחץ על נקודת עניין. בנוסף, מאזין הקליקים מציג חלון מידע שמכיל את שם הנקודה.
- יוצרים stub של שיטה ב-
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)
}
- מריצים את האפליקציה ומחפשים נקודת עניין, כמו פארק או בית קפה.
- מקישים על הנקודה כדי להציב עליה סמן ולהציג את השם שלה בחלון מידע.
יש הרבה דרכים להתאים אישית את מפות Google, כך שהמפה תיראה ותורגש ייחודית.
אפשר להתאים אישית אובייקט MapFragment
באמצעות מאפייני ה-XML שזמינים, כמו שמתאימים אישית כל קטע אחר. עם זאת, בשלב הזה מתאימים אישית את המראה והתחושה של התוכן של MapFragment
באמצעות שיטות באובייקט GoogleMap
.
כדי ליצור סגנון מותאם אישית למפה, יוצרים קובץ JSON שמציין איך התכונות במפה מוצגות. לא צריך ליצור את קובץ ה-JSON הזה באופן ידני. Google מספקת את אשף הסגנונות של הפלטפורמה של מפות Google, שיוצר את ה-JSON בשבילכם אחרי שאתם מעצבים את המפה באופן ויזואלי. במשימה הזו, תעצבו את המפה עם עיצוב רטרו, כלומר המפה תשתמש בצבעי וינטג' ותוסיפו כבישים צבעוניים.
שלב 1: יוצרים סגנון למפה
- בדפדפן, עוברים אל https://mapstyle.withgoogle.com/.
- בוחרים באפשרות יצירת סגנון.
- בוחרים באפשרות רטרו.
- לוחצים על אפשרויות נוספות.
- ברשימה סוג התכונה, בוחרים באפשרות כביש > מילוי.
- משנים את צבע הכבישים לצבע הרצוי (למשל, ורוד).
- לוחצים על סיום.
- מעתיקים את קוד ה-JSON מתיבת הדו-שיח שמופיעה, ואם רוצים, שומרים אותו בהערה בטקסט פשוט לשימוש בשלב הבא.
שלב 2: הוספת הסגנון למפה
- ב-Android Studio, בספרייה
res
, יוצרים ספריית משאבים ונותנים לה את השםraw
. משתמשים במשאבי הספרייהraw
כמו קוד JSON. - יוצרים קובץ ב-
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()
.
אחת הדרכים להתאים אישית את מפת 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.
משתמשים לרוב במפות 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()
}
}
}
- מריצים את האפליקציה. אמור להופיע תיבת דו-שיח עם בקשה לגישה למיקום המכשיר. אפשר לאשר את ההרשאה.
המיקום הנוכחי של המכשיר מוצג במפה באמצעות נקודה כחולה. שימו לב שיש כפתור למיקום. אם מרחיקים את המפה מהמיקום שלכם ולוחצים על הלחצן הזה, המפה מתמרכזת בחזרה למיקום של המכשיר.
מורידים את הקוד של ה-codelab המוגמר.
$ git clone https://github.com/googlecodelabs/android-kotlin-geo-maps
אפשר גם להוריד את המאגר כקובץ ZIP, לבטל את הדחיסה שלו ולפתוח אותו ב-Android Studio.
- כדי להשתמש ב-Maps API, צריך מפתח API מ-Google API Console.
- ב-Android Studio, שימוש בתבנית Google Maps Activity יוצר
Activity
עםSupportMapFragment
יחיד בפריסת האפליקציה. בנוסף, התבנית מוסיפה אתACCESS_FINE_PERMISSION
למניפסט של האפליקציה, מטמיעה אתOnMapReadyCallback
בפעילות ומבטלת את השיטה הנדרשתonMapReady()
.
כדי לשנות את סוג המפה של GoogleMap
בזמן ריצה, משתמשים בשיטה GoogleMap.setMapType()
. מפה של Google יכולה להיות אחד מסוגי המפות הבאים:
- רגילה: מפת דרכים רגילה. התצוגה הזו מציגה כבישים, חלק מהמאפיינים שנבנו על ידי בני אדם ומאפיינים טבעיים חשובים כמו נהרות. אפשר לראות גם את התוויות של הכבישים והמאפיינים.
- משולב: נתונים של צילומי לוויין עם מפות דרכים. אפשר לראות גם את התוויות של הכבישים והמאפיינים.
- לוויין: נתוני תמונה. לא רואים את התוויות של הכבישים והמאפיינים.
- פני השטח: נתונים טופוגרפיים. המפה כוללת צבעים, קווי מתאר ותוויות, והצללה פרספקטיבית. אפשר לראות גם חלק מהכבישים והתוויות.
- ללא: אין משבצות של מפת בסיס.
מידע על מפות Google:
- סמן הוא אינדיקטור למיקום גיאוגרפי ספציפי.
- כשמקישים על הסמן, התנהגות ברירת המחדל שלו היא להציג חלון מידע עם פרטים על המיקום.
- כברירת מחדל, נקודות עניין (POI) מופיעות במפת הבסיס יחד עם הסמלים המתאימים שלהן. נקודות העניין כוללות פארקים, בתי ספר, בנייני ממשלה ועוד.
- בנוסף, נקודות עניין עסקיות (חנויות, מסעדות, בתי מלון ועוד) מופיעות במפה כברירת מחדל כשסוג המפה הוא
normal
. - אפשר לתעד קליקים על נקודות עניין באמצעות
OnPoiClickListener
. - אפשר לשנות את המראה של כמעט כל הרכיבים במפת Google באמצעות אשף הסגנונות. אשף הסגנונות יוצר קובץ JSON שמעבירים למפה של Google באמצעות השיטה
setMapStyle()
. - אתם יכולים לשנות את צבע ברירת המחדל של הסמנים או להחליף את סמל ברירת המחדל של הסמן בתמונה מותאמת אישית.
עוד מידע חשוב:
- כדי להצמיד תמונה למיקום גיאוגרפי, משתמשים בשכבת-על של תמונה על הקרקע.
- משתמשים באובייקט
GroundOverlayOptions
כדי לציין את התמונה, את הגודל שלה במטרים ואת המיקום שלה. מעבירים את האובייקט הזה לשיטהGoogleMap.addGroundOverlay()
כדי להגדיר את שכבת העל במפה. - אם לאפליקציה שלכם יש הרשאה
ACCESS_FINE_LOCATION
, אתם יכולים להפעיל את מעקב המיקום על ידי הגדרתmap.isMyLocationEnabled = true
. - הנושא הזה לא מכוסה ב-codelab הזה, אבל אפשר לספק מידע נוסף על מיקום באמצעות Google Street View, שכולל תמונה פנורמית עם אפשרות ניווט של מיקום נתון.
מסמכי תיעוד למפתחי Android:
מאמרי עזרה:
קישורים למדריכי Codelab נוספים בקורס הזה מופיעים בדף הנחיתה של מדריכי Codelab בנושא Android מתקדם ב-Kotlin.