Advanced Android 09.1: מפות Google

1. היי!

ה-codelab הזה הוא חלק מקורס ההדרכה Advanced Android Development שפותח על ידי צוות Google Developers Training. כדי להפיק את המרב מהקורס הזה, מומלץ לעבוד על ה-Codelabs לפי הסדר.

פרטים מלאים על הקורס זמינים במאמר סקירה כללית על פיתוח מתקדם ל-Android.

מבוא

פיתוח אפליקציות באמצעות מפות Google מאפשר לכם להוסיף לאפליקציה תכונות כמו תמונות לוויין, אמצעי בקרה חזקים בממשק המשתמש, מעקב אחר מיקום וסמני מיקום. אתם יכולים להוסיף ערך למפות Google הרגילות על ידי הצגת מידע ממערך הנתונים שלכם, כמו מיקומים של אזורים מוכרים לדיג או לטיפוס. אפשר גם ליצור משחקים שקשורים לעולם האמיתי, כמו Pokemon Go.

בשיעור המעשי הזה, תיצרו אפליקציה למפות Google בשם Wander.

מה שכדאי לדעת

חשוב שתכירו את:

  • פונקציונליות בסיסית של מפות Google.
  • הרשאות בזמן ריצה.
  • יצירה, בנייה והרצה של אפליקציות ב-Android Studio.
  • כולל ספריות חיצוניות בקובץ build.gradle.

מה תלמדו

  • שילוב של מפת Google באפליקציה.
  • הצגת סוגים שונים של מפות.
  • הגדרת סגנון למפת Google.
  • מוסיפים סמנים למפה.
  • מאפשרים למשתמש למקם סמן בנקודת עניין (POI).
  • מפעילים את המעקב אחר המיקום.
  • מפעילים את Google Street View.

הפעולות שתבצעו:

  • מקבלים מפתח API מ-Google API Console ורושמים את המפתח באפליקציה.
  • יוצרים את אפליקציית Wander, שכוללת מפה מוטמעת של Google.
  • להוסיף לאפליקציה תכונות בהתאמה אישית, כמו סמנים, סגנון ומעקב מיקום.
  • מפעילים את מעקב המיקום ואת Street View באפליקציה.

2. סקירה כללית של האפליקציה

בשיעור המעשי הזה תיצרו את אפליקציית Wander, שהיא מפה של Google עם סגנון. באפליקציית Wander אפשר להציב סמנים במיקומים, לראות את המיקום בזמן אמת ולצפות בתמונות פנורמיות של Street View.

מפת Google מסוגננת

‫Google Street View באפליקציית Android

3. משימה 1: הגדרת הפרויקט וקבלת מפתח API

כמו Places API, גם Google Maps API דורש מפתח API. כדי לקבל את מפתח ה-API, צריך לרשום את הפרויקט ב-Google API Console. מפתח ה-API קשור לאישור דיגיטלי שמקשר את האפליקציה ליוצר שלה. מידע נוסף על שימוש באישורים דיגיטליים ועל חתימה על האפליקציה זמין במאמר בנושא חתימה על האפליקציה.

בשלב המעשי הזה, משתמשים במפתח ה-API לאישור הניפוי באגים. אישור הניפוי באגים לא מאובטח מעצם הגדרתו, כפי שמתואר במאמר בנושא חתימה על גרסת build לניפוי באגים. אפליקציות ל-Android שפורסמו ומשתמשות ב-Google Maps API דורשות מפתח API שני: המפתח של אישור הפרסום. מידע נוסף על קבלת אישור הפצה זמין במאמר בנושא קבלת מפתח API.

‫Android Studio כולל תבנית של פעילות במפות Google, שמייצרת קוד תבנית שימושי. קוד התבנית כולל קובץ google_maps_api.xml שמכיל קישור שמפשט את קבלת מפתח API.

‫1.1 יצירת פרויקט Wander באמצעות תבנית של מפות

  1. יוצרים פרויקט חדש ב-Android Studio.
  2. נותנים לאפליקציה החדשה את השם Wander. מאשרים את הגדרות ברירת המחדל עד שמגיעים לדף הוספת פעילות.
  3. בוחרים בתבנית פעילות במפות Google.
  4. משאירים את שם הפעילות ושם הפריסה שמוגדרים כברירת מחדל.
  5. משנים את השם ל-Wander ולוחצים על סיום.

‫Android Studio יוצר כמה קבצים נוספים שקשורים למפות:

google_maps_api**.xml**

קובץ התצורה הזה משמש לאחסון מפתח ה-API. התבנית יוצרת שני קובצי google_maps_api.xml: אחד לניפוי באגים ואחד לפרסום. הקובץ של מפתח ה-API לאישור הניפוי באגים נמצא ב-src/debug/res/values. הקובץ של מפתח ה-API לאישור הגרסה נמצא בנתיב src/release/res/values. בשיעור המעשי הזה אנחנו משתמשים רק באישור לניפוי באגים.

activity_maps.xml

קובץ הפריסה הזה מכיל רכיב fragment יחיד שממלא את כל המסך. הסיווג SupportMapFragment הוא סיווג משנה של הסיווג Fragment. אפשר לכלול את SupportMapFragment בקובץ פריסה באמצעות תג <fragment> בכל ViewGroup, עם מאפיין נוסף:

android:name="com.google.android.gms.maps.SupportMapFragment"

MapsActivity.java

קובץ MapsActivity.java יוצר מופע של המחלקה SupportMapFragment ומשתמש בשיטה getMapAsync() של המחלקה כדי להכין את מפת Google. הפעילות שמכילה את SupportMapFragment חייבת להטמיע את הממשק OnMapReadyCallback ואת השיטה onMapReady() של הממשק הזה. השיטה getMapAsync() מחזירה אובייקט GoogleMap, שמציין שהמפה נטענה.

‫1.2 קבלת מפתח ה-API

  1. פותחים את גרסת הניפוי של קובץ google_maps_api.xml.

הקובץ כולל תגובה עם כתובת URL ארוכה. הפרמטרים של כתובת ה-URL כוללים מידע ספציפי על האפליקציה.

  1. מעתיקים את כתובת ה-URL ומדביקים אותה בדפדפן.
  2. פועלים לפי ההנחיות כדי ליצור פרויקט ב-Google API Console. בגלל הפרמטרים בכתובת ה-URL שצוינה, קונסולה לממשקי API יודעת להפעיל באופן אוטומטי את Google Maps Android API
  3. יוצרים מפתח API ולוחצים על Restrict Key כדי להגביל את השימוש במפתח לאפליקציות ל-Android. מפתח ה-API שנוצר צריך להתחיל ב-AIza.
  4. בקובץ google_maps_api.xml, מדביקים את המפתח במחרוזת google_maps_key במקום שבו מופיע הכיתוב YOUR_KEY_HERE.
  5. מריצים את האפליקציה. במפה שמוטמעת בפעילות מוגדר סמן בסידני, אוסטרליה. (הסמן של סידני הוא חלק מהתבנית, ואפשר לשנות אותו בהמשך).

4. משימה 2: הוספה של סוגי מפות וסמנים

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

‫2.1 הוספת סוגי מפות

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

  1. כדי ליצור קובץ XML חדש של תפריט, לוחצים לחיצה ימנית על ספריית res ובוחרים באפשרות New > Android Resource File (חדש > קובץ משאבים של Android).
  2. בתיבת הדו-שיח, נותנים שם לקובץ map_options. בוחרים באפשרות תפריט בשדה 'סוג המשאב'. לוחצים על אישור.
  3. כדי ליצור את אפשרויות המפה, מחליפים את הקוד בקובץ החדש בקוד הבא. סוג המפה 'ללא' מושמט, כי התוצאה של 'ללא' היא היעדר מפה.
<?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>
  1. יוצרים משאבי מחרוזות למאפייני title.
  2. בקובץ MapsActivity, משנים את המחלקה כך שהיא תרחיב את המחלקה AppCompatActivity במקום להרחיב את המחלקה FragmentActivity. שימוש ב-AppCompatActivity יציג את סרגל האפליקציות, ולכן יציג את התפריט.
  3. ב-MapsActivity, מבטלים את השיטה onCreateOptionsMenu() ויוצרים אוביקט תצוגה (inflate) של הקובץ map_options:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
   MenuInflater inflater = getMenuInflater();
   inflater.inflate(R.menu.map_options, menu);
   return true;
}
  1. כדי לשנות את סוג המפה, משתמשים בשיטה setMapType() באובייקט GoogleMap ומעבירים את אחת הקבועים של סוג המפה.

מבטלים את השיטה onOptionsItemSelected(). מדביקים את הקוד הבא כדי לשנות את סוג המפה כשהמשתמש בוחר באחת מאפשרויות התפריט:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
       // Change the map type based on the user's selection.
       switch (item.getItemId()) {
           case R.id.normal_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
               return true;
           case R.id.hybrid_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
               return true;
           case R.id.satellite_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
               return true;
           case R.id.terrain_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
               return true;
           default:
               return super.onOptionsItemSelected(item);
       }
    }
  1. מריצים את האפליקציה ומשתמשים בתפריט בסרגל האפליקציות כדי לשנות את סוג המפה. שימו לב איך המראה של המפה משתנה.

‫2.2 הזזה של מיקום ברירת המחדל במפה

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

  1. בשיטה onMapReady(), מסירים את הקוד שמציב את הסמן בסידני ומזיז את המצלמה.
  2. נכנסים לכתובת www.google.com/maps בדפדפן ומחפשים את הבית.
  3. לוחצים לחיצה ימנית על המיקום ובוחרים באפשרות מה יש כאן?

קרוב לחלק התחתון של המסך, יופיע חלון קטן עם פרטי המיקום, כולל קו הרוחב וקו האורך.

  1. יוצרים אובייקט LatLng חדש בשם home. באובייקט LatLng, משתמשים בקואורדינטות שמצאתם במפות Google בדפדפן.
  2. יוצרים משתנה float בשם zoom ומגדירים את המשתנה לרמת הזום ההתחלתית הרצויה. הרשימה הבאה נותנת לכם מושג לגבי רמת הפירוט שמוצגת בכל רמת זום:
  • 1: עולם
  • 5: מסת יבשה/יבשת
  • 10: עיר
  • 15: רחובות
  • 20: מבנים
  1. יוצרים אובייקט CameraUpdate באמצעות CameraUpdateFactory.newLatLngZoom(), ומעבירים את האובייקט LatLng ואת המשתנה zoom. כדי להזיז את המצלמה ולשנות את מרחק התצוגה, קוראים ל-moveCamera() באובייקט GoogleMap ומעבירים את האובייקט החדש CameraUpdate:
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(home, zoom));
  1. מריצים את האפליקציה. המפה אמורה להזיז את התצוגה לבית שלכם ולהגדיל את התצוגה לרמה הרצויה.

‫2.3 הוספת סמני מפה

אפשר להשתמש בסמן כדי להבליט מיקום מסוים במפות Google. כדי ליצור סמן, משתמשים במחלקה Marker. סמן ברירת המחדל משתמש בסמל הרגיל של מפות Google: סַמָּן במפות Google

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

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

חלון מידע על סיכה שהוצבה

  1. יוצרים stub של method ב-MapsActivity בשם setMapLongClick() שמקבל final GoogleMap כארגומנט ומחזיר void:
private void setMapLongClick(final GoogleMap map) {}
  1. משתמשים בשיטה setOnMapLongClickListener() של האובייקט GoogleMap כדי למקם סמן במקום שבו המשתמש נוגע ומחזיק. מעבירים מופע חדש של OnMapLongClickListener שמבטל את השיטה onMapLongClick(). הארגומנט הנכנס הוא אובייקט LatLng שמכיל את הקואורדינטות של המיקום שהמשתמש לחץ עליו:
private void setMapLongClick(final GoogleMap map) {
   map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
       @Override
       public void onMapLongClick(LatLng latLng) {
       }
   });
}
  1. בתוך onMapLongClick(), מבצעים קריאה ל-method‏ addMarker(). מעבירים אובייקט חדש של MarkerOptions עם המיקום שמוגדר ל-LatLng שהועבר:
map.addMarker(new MarkerOptions().position(latLng));
  1. מבצעים קריאה ל-setMapLongClick() בסוף השיטה onMapReady(). כרטיס mMap.
  2. מריצים את האפליקציה. לוחצים לחיצה ארוכה על המפה כדי למקם סמן במיקום מסוים.
  3. מקישים על הסמן כדי למרכז אותו במסך.

לחצני הניווט מופיעים בצד ימין למטה של המסך, ומאפשרים למשתמש להשתמש באפליקציית מפות Google כדי לנווט למיקום המסומן.

כדי להוסיף חלון מידע לסמן:

  1. באובייקט MarkerOptions, מגדירים את השדה title ואת השדה snippet.
  2. ב-onMapLongClick(), מגדירים את השדה title לערך 'סיכה שהוצבה'. מגדירים את השדה snippet לקואורדינטות של המיקום בתוך השיטה addMarker().
map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
   @Override
   public void onMapLongClick(LatLng latLng) {
       String snippet = String.format(Locale.getDefault(),
               "Lat: %1$.5f, Long: %2$.5f",
               latLng.latitude,
               latLng.longitude);

       map.addMarker(new MarkerOptions()
               .position(latLng)
               .title(getString(R.string.dropped_pin))
               .snippet(snippet));
   }
});
  1. מפעילים את האפליקציה. לוחצים לחיצה ארוכה על המפה כדי להציב סמן מיקום. מקישים על הסמן כדי להציג את חלון המידע.

‫2.4 הוספת מאזין לנקודות עניין

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

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

סמן של נקודת עניין

  1. תצור מחזיק מקום (stub) של שיטה ב-MapsActivity בשם setPoiClick() שמקבלת final GoogleMap כארגומנט ומחזירה void:
private void setPoiClick(final GoogleMap map) {}
  1. בשיטה setPoiClick(), מגדירים OnPoiClickListener ב-GoogleMap שמועבר:
map.setOnPoiClickListener(new GoogleMap.OnPoiClickListener() {
   @Override
   public void onPoiClick(PointOfInterest poi) {
   }
});
  1. בשיטה onPoiClick(), ממקמים סמן במיקום של נקודת העניין. מגדירים את הכותרת לשם של נקודת העניין. שומרים את התוצאה במשתנה שנקרא poiMarker.
public void onPoiClick(PointOfInterest poi) {
   Marker poiMarker = mMap.addMarker(new MarkerOptions()
       .position(poi.latLng)
       .title(poi.name);
}
  1. מתקשרים אל showInfoWindow() בטלפון poiMarker כדי להציג מיד את חלון המידע.
poiMarker.showInfoWindow();
  1. התקשרת אל setPoiClick() בסוף onMapReady(). כרטיס mMap.
  2. מריצים את האפליקציה ומחפשים נקודת עניין כמו פארק. מקישים על נקודת העניין כדי להציב עליה סמן ולהציג את השם שלה בחלון מידע.

5. משימה 3: עיצוב המפה

יש הרבה דרכים להתאים אישית את מפות Google, כך שהמפה תיראה ותורגש ייחודית.

אפשר להתאים אישית אובייקט MapFragment באמצעות מאפייני ה-XML שזמינים, כמו שמתאימים אישית כל מקטע אחר. עם זאת, בשלב הזה מתאימים אישית את המראה והתחושה של התוכן של MapFragment, באמצעות שיטות באובייקט GoogleMap. אתם משתמשים באשף הסגנונות באינטרנט כדי להוסיף סגנון למפה ולהתאים אישית את הסמנים. אפשר גם להוסיף GroundOverlay למיקום הבית, שמשנה את הגודל שלו ומסתובב בהתאם למפה.

‫3.1 הוספת סגנון למפה

כדי ליצור סגנון מותאם אישית למפה, יוצרים קובץ JSON שמציין איך יוצגו הרכיבים במפה.לא צריך ליצור את קובץ ה-JSON הזה באופן ידני: Google מספקת את אשף הסגנונות, שיוצר את ה-JSON בשבילכם אחרי שאתם מעצבים את המפה באופן חזותי. בשיעור המעשי הזה, תעצבו את המפה ל'מצב לילה', כלומר המפה תשתמש בצבעים עמומים ובניגודיות נמוכה לשימוש בלילה.

  1. בדפדפן, עוברים אל https://mapstyle.withgoogle.com/.
  2. בוחרים באפשרות יצירת סגנון.
  3. בוחרים בעיצוב לילה.
  4. בתחתית התפריט, לוחצים על אפשרויות נוספות.
  5. בתחתית הרשימה סוג התכונה, בוחרים באפשרות מים > מילוי. משנים את צבע המים לכחול כהה (לדוגמה, ‎#160064).
  6. לוחצים על סיום. מעתיקים את קוד ה-JSON מהחלון הקופץ שמופיע.
  7. ב-Android Studio, יוצרים ספריית משאבים בשם raw בספרייה res. יוצרים קובץ ב-res/raw בשם map_style.json.
  8. מדביקים את קוד ה-JSON בקובץ המשאבים החדש.
  9. כדי להגדיר את הסגנון של ה-JSON במפה, קוראים ל-setMapStyle() באובייקט GoogleMap. מעבירים אובייקט MapStyleOptions, שמעלה את קובץ ה-JSON. השיטה setMapStyle() מחזירה ערך בוליאני שמציין אם העיצוב הצליח. אם אי אפשר לטעון את הקובץ, הפונקציה מחזירה Resources.NotFoundException.

מעתיקים את הקוד הבא לשיטה onMapReady() כדי להגדיר את הסגנון של המפה. יכול להיות שתצטרכו ליצור TAG מחרוזת בשביל הצהרות היומן:

     try {
        // Customize the styling of the base map using a JSON object defined
        // in a raw resource file.
        boolean success = googleMap.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
                   this, R.raw.map_style));

        if (!success) {
            Log.e(TAG, "Style parsing failed.");
        }
     } catch (Resources.NotFoundException e) {
        Log.e(TAG, "Can't find style. Error: ", e);
     }
  1. מריצים את האפליקציה. הסגנון החדש אמור להיות גלוי כשהמפה במצב normal.

מפת Google בסגנון מצב לילה

‫3.2 עיצוב הסמן

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

  1. בשיטה onMapLongClick(), מוסיפים את שורת הקוד הבאה לבונה MarkerOptions() כדי להשתמש בסמן ברירת המחדל אבל לשנות את הצבע לכחול:
.icon(BitmapDescriptorFactory.defaultMarker
       (BitmapDescriptorFactory.HUE_BLUE))
  1. מריצים את האפליקציה. הסמנים שמיקמתם מוצגים עכשיו בצבע כחול מוצלל, שמתאים יותר לעיצוב של מצב הלילה באפליקציה.

שימו לב שסמני הנקודות של העניין עדיין אדומים, כי לא הוספתם סגנון לשיטה onPoiClick().

‫3.3 הוספת שכבת-על

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

  • צורות: אפשר להוסיף למפה קווי פוליגון, פוליגונים ומעגלים.
  • TileOverlay אובייקטים: שכבה מעל קטעי המפה מגדירה קבוצה של תמונות שנוספות מעל קטעי המפה הבסיסיים. שכבות-על של משבצות שימושיות כשרוצים להוסיף למפה תמונות רבות. שכבה מעל קטעי המפה טיפוסית מכסה אזור גיאוגרפי גדול.
  • אובייקטים מסוג GroundOverlay: שכבת-על של קרקע היא תמונה שמוצמדת למפה. שלא כמו סמנים, שכבות-על של הקרקע מכוונות לפני השטח של כדור הארץ ולא למסך. סיבוב, הטיה או שינוי הזום של המפה משנים את הכיוון של התמונה. שכבות על של קרקע שימושיות כשרוצים להצמיד תמונה אחת לאזור מסוים במפה

בשלב הזה מוסיפים שכבת-על של קרקע בצורת Android למיקום הבית.

  1. מורידים את התמונה הזו של Android ושומרים אותה בתיקייה res/drawable.
  2. ב-onMapReady(), אחרי הקריאה להזזת המצלמה למיקום הבית, יוצרים אובייקט GroundOverlayOptions. הקצאת האובייקט למשתנה שנקרא homeOverlay:
GroundOverlayOptions homeOverlay = new GroundOverlayOptions();
  1. משתמשים ב- method‏ BitmapDescriptorFactory.fromResource() כדי ליצור אובייקט BitmapDescriptor מהתמונה שלמעלה. מעבירים את האובייקט לשיטה image() של האובייקט GroundOverlayOptions:
GroundOverlayOptions homeOverlay = new GroundOverlayOptions()
    .image(BitmapDescriptorFactory.fromResource(R.drawable.android));
  1. מגדירים את המאפיין position לאובייקט GroundOverlayOptions על ידי קריאה לשיטה position(). מעבירים את האובייקט home LatLng ואת הערך float לרוחב במטרים של שכבת העל הרצויה. בדוגמה הזו, רוחב של 100 מ' מתאים:
GroundOverlayOptions homeOverlay = new GroundOverlayOptions()
     .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
       .position(home, 100);
  1. שיחה למספר addGroundOverlay() באובייקט GoogleMap. מעבירים את אובייקט GroundOverlayOptions:
mMap.addGroundOverlay(homeOverlay);
  1. מריצים את האפליקציה. מתקרבים למיקום הבית, ותמונת Android מוצגת כשכבת-על.

6. משימה 4: הפעלת מעקב אחר המיקום ו-Street View

משתמשים לרוב משתמשים במפות Google כדי לראות את המיקום הנוכחי שלהם, ואפשר לקבל את מיקום המכשיר באמצעות Location Services API. כדי להציג את מיקום המכשיר במפה בלי להשתמש בנתוני Location, אפשר להשתמש בשכבת נתוני המיקום.

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

מפה של Google עם סגנון מותאם אישית ומעקב אחר מיקום

אפשר לספק מידע נוסף על מיקום באמצעות Google Street View, שכולל תמונה פנורמית עם אפשרות ניווט של מיקום נתון.

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

‫4.1 הפעלת מעקב אחר מיקום

כדי להפעיל את מעקב המיקום במפות Google, צריך להוסיף שורת קוד אחת. עם זאת, אתם צריכים לוודא שהמשתמש העניק הרשאות מיקום (באמצעות מודל ההרשאות בזמן הריצה).

בשלב הזה, שולחים בקשה להרשאות מיקום ומפעילים את מעקב המיקום.

  1. בקובץ AndroidManifest.xml, מוודאים שההרשאה FINE_LOCATION כבר קיימת. ההרשאה הזו נוספה על ידי Android Studio כשבחרתם בתבנית של מפות Google.
  2. כדי להפעיל את מעקב המיקום באפליקציה, צריך ליצור שיטה ב-MapsActivity בשם enableMyLocation() שלא מקבלת ארגומנטים ולא מחזירה כלום.
  3. מגדירים את השיטה enableMyLocation(). בודקים אם יש לכם הרשאה לACCESS_FINE_LOCATION. אם ההרשאה ניתנה, מפעילים את שכבת המיקום. אחרת, צריך לבקש את ההרשאה:
private void enableMyLocation() {
   if (ContextCompat.checkSelfPermission(this,
           Manifest.permission.ACCESS_FINE_LOCATION)
           == PackageManager.PERMISSION_GRANTED) {
       mMap.setMyLocationEnabled(true);
   } else {
       ActivityCompat.requestPermissions(this, new String[]
                       {Manifest.permission.ACCESS_FINE_LOCATION},
               REQUEST_LOCATION_PERMISSION);
   }
}
  1. מתקשרים אל enableMyLocation() מהקריאה החוזרת onMapReady() כדי להפעיל את שכבת המיקום.
  2. מבטלים את השיטה onRequestPermissionsResult(). אם ההרשאה ניתנה, מתקשרים אל enableMyLocation():
@Override
public void onRequestPermissionsResult(int requestCode,
       @NonNull String[] permissions,
       @NonNull int[] grantResults) {
   // Check if location permissions are granted and if so enable the
   // location data layer.
   switch (requestCode) {
       case REQUEST_LOCATION_PERMISSION:
           if (grantResults.length > 0
                   && grantResults[0]
                   == PackageManager.PERMISSION_GRANTED) {
               enableMyLocation();
               break;
           }
   }
}
  1. מריצים את האפליקציה. בפינה השמאלית העליונה מופיע עכשיו הלחצן המיקום שלי, שבו מוצג המיקום הנוכחי של המכשיר.

‫4.2 הפעלת Street View

מפות Google מספקת את Street View, תצוגה פנורמית של מיקום עם אמצעי בקרה לניווט לאורך נתיב ייעודי. אין כיסוי גלובלי של Street View.

בשלב הזה מפעילים פנורמה ב-Street View שמופעלת כשהמשתמש מקיש על חלון המידע של נקודת העניין. יש שני דברים שצריך לעשות:

  1. להבחין בין סמני נקודות עניין לבין סמנים אחרים, כי רוצים שהפונקציונליות של האפליקציה תפעל רק על סמני נקודות עניין. כך תוכלו להפעיל את Street View כשהמשתמש מקיש על חלון מידע של נקודת עניין, אבל לא כשהמשתמש מקיש על סוג אחר של סמן.

המחלקות Marker כוללות את השיטה setTag() שמאפשרת לצרף נתונים. (הנתונים יכולים להיות כל דבר שמתחיל מ-Object). תגדירו תג על הסמנים שנוצרים כשמשתמשים לוחצים על נקודות עניין.

  1. כשמשתמש מקיש על חלון מידע מתויג ב-OnInfoWindowClickListener, מחליפים את MapFragment ב-StreetViewPanoramaFragment. (הקוד שלמטה משתמש ב-SupportMapFragment וב-SupportStreetViewPanoramaFragment כדי לתמוך בגרסאות Android מתחת ל-API 12).

אם יש שינויים באחד מהקטעים בזמן הריצה, צריך להוסיף אותם בכיתת Activity שמכילה אותם, ולא באופן סטטי ב-XML.

תיוג הסמן של נקודת העניין

  1. בשיחה החוזרת onPoiClick(), התקשר אל setTag() בכתובת poiMarker. מעבירים מחרוזת שרירותית כלשהי:
poiMarker.setTag("poi");

החלפת SupportMapFragment סטטי במופע בזמן ריצה

  1. פותחים את activity_maps.xml ומשנים את הרכיב לפריסת מסגרת שתשמש כמאגר לרכיבי ה-Fragment:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/fragment_container"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />
  1. ב-onCreate() ב-MapsActivity, מסירים את הקוד שמאתר את SupportMapFragment לפי מזהה, כי כבר אין SupportMapFragment סטטי ב-XML. במקום זאת, יוצרים מופע חדש של זמן הריצה של SupportMapFragment על ידי קריאה ל-SupportMapFragment.newInstance():
SupportMapFragment mapFragment = SupportMapFragment.newInstance();
  1. מוסיפים את הפראגמנט ל-FrameLayout באמצעות טרנזקציית פראגמנט עם FragmentManager:
getSupportFragmentManager().beginTransaction()
       .add(R.id.fragment_container, mapFragment).commit();
  1. משאירים את שורת הקוד שמפעילה את הטעינה האסינכרונית של המפה:
mapFragment.getMapAsync(this);

הגדרת OnInfoWindowClickListener ובדיקת תג הסמן

  1. תצור מחזיק מקום לשיטה ב-MapsActivity בשם setInfoWindowClickToPanorama() שמקבלת GoogleMap כארגומנט ומחזירה void:
private void setInfoWindowClickToPanorama(GoogleMap map) {}
  1. הגדרת OnInfoWindowClickListener ל-GoogleMap:
map.setOnInfoWindowClickListener(
       new GoogleMap.OnInfoWindowClickListener() {
           @Override
           public void onInfoWindowClick(Marker marker) {
           }
       });
  1. בשיטה onInfoWindowClick(), בודקים אם הסמן מכיל את מחרוזת התג שהגדרתם בשיטה onPoiClick():
if (marker.getTag() == "poi") {}

החלפת SupportMapFragment ב-SupportStreetViewPanoramaFragment

  1. אם הסמן מכיל את התג, מציינים את המיקום של פנורמה ב-Street View באמצעות אובייקט StreetViewPanoramaOptions. מגדירים את המאפיין position של האובייקט למיקום של הסמן שהועבר:
StreetViewPanoramaOptions options =
       new StreetViewPanoramaOptions().position(
               marker.getPosition());
  1. יוצרים מופע חדש של SupportStreetViewPanoramaFragment ומעבירים את אובייקט options שיצרתם:
SupportStreetViewPanoramaFragment streetViewFragment
       = SupportStreetViewPanoramaFragment
       .newInstance(options);
  1. מתחילים טרנזקציה של מקטע. מחליפים את התוכן של מאגר הפרגמנט בפרגמנט החדש, streetViewFragment. מוסיפים את העסקה למקבץ הפעילויות הקודמות (back stack), כך שלחיצה על 'חזרה' תחזיר את המשתמש אל SupportMapFragment ולא תוציא אותו מהאפליקציה:
getSupportFragmentManager().beginTransaction()
       .replace(R.id.fragment_container,
               streetViewFragment)
       .addToBackStack(null).commit();
  1. התקשר אל setInfoWindowClickToPanorama(mMap) בonMapReady() אחרי השיחה אל setPoiClick().
  2. מפעילים את האפליקציה. מתקרבים לעיר שיש בה כיסוי של Street View, כמו מאונטיין ויו (שבה נמצא המטה של Google), ומחפשים נקודת עניין, כמו פארק. מקישים על נקודת העניין כדי להציב סמן ולהציג את חלון המידע. מקישים על חלון המידע כדי להיכנס למצב Street View של מיקום הסמן. לוחצים על הכפתור "הקודם" כדי לחזור למקטע המפה.

‫Google Street View באפליקציית Android

7. קוד הפתרון

קוד הפתרון Wander.

8. אתגר תכנות

בעיה: אם מקישים על חלון המידע של נקודת עניין במיקום שאין בו כיסוי של Street View, מופיע מסך שחור.

9. סיכום

  • כדי להשתמש ב-Maps API, צריך מפתח API מ-Google API Console.
  • ב-Android Studio, שימוש בתבנית Google Maps Activity יוצר Activity עם SupportMapFragment אחד בפריסת האפליקציה. בנוסף, התבנית מוסיפה את ACCESS_FINE_PERMISSION לקובץ מניפסט של אפליקציה, מטמיעה את OnMapReadyCallback בפעילות ומבטלת את השיטה הנדרשת onMapReady().

כדי לשנות את סוג המפה של GoogleMap בזמן ריצה, משתמשים בשיטה GoogleMap.setMapType(). מפת Google יכולה להיות אחד מסוגי המפות הבאים:

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

מידע על מפות Google:

  • סמן הוא אינדיקטור למיקום גיאוגרפי ספציפי.
  • כשמקישים על הסמן, התנהגות ברירת המחדל שלו היא להציג חלון מידע עם פרטים על המיקום.
  • כברירת מחדל, נקודות עניין מופיעות במפת הבסיס עם הסמלים המתאימים שלהן. נקודות העניין כוללות פארקים, בתי ספר, בנייני ממשלה ועוד.
  • בנוסף, נקודות עניין עסקיות (חנויות, מסעדות, מלונות ועוד) מופיעות כברירת מחדל במפה כשסוג המפה הוא normal.
  • אפשר לתעד קליקים על נקודות עניין באמצעות OnPoiClickListener.
  • אפשר לשנות את המראה של כמעט כל הרכיבים במפת Google באמצעות אשף הסגנונות. אשף הסגנונות יוצר קובץ JSON שמעבירים למפה של Google באמצעות השיטה setMapStyle().
  • אתם יכולים לשנות את צבע ברירת המחדל של הסמנים או להחליף את סמל ברירת המחדל של הסמן בתמונה בהתאמה אישית.

עוד מידע חשוב:

  • כדי להצמיד תמונה למיקום גיאוגרפי, משתמשים בשכבת-על של הקרקע.
  • משתמשים באובייקט GroundOverlayOptions כדי לציין את התמונה, את הגודל שלה במטרים ואת המיקום שלה. מעבירים את האובייקט הזה אל השיטה GoogleMap.addGroundOverlay() כדי להגדיר את שכבת העל במפה.
  • אם לאפליקציה שלכם יש הרשאה ACCESS_FINE_LOCATION, אתם יכולים להפעיל את מעקב המיקום באמצעות השיטה mMap.setMyLocationEnabled(true).
  • ‫Google Street View מספק תצוגות פנורמיות של 360 מעלות מכבישים ייעודיים בכל היקף גיאוגרפי.
  • משתמשים בשיטה StreetViewPanoramaFragment.newInstance() כדי ליצור קטע חדש של Street View.
  • כדי לציין את האפשרויות של התצוגה, משתמשים באובייקט StreetViewPanoramaOptions. מעבירים את האובייקט לשיטה newInstance().

10. מידע נוסף

מסמכי התיעוד בנושא המושג הזה זמינים במאמר 9.1: Google Maps API.

מסמכי התיעוד למפתחים בנושא Android:

מסמכי עזר:

11. שיעורי בית

בקטע הזה מפורטות משימות אפשריות לשיעורי בית לתלמידים שעובדים על ה-Codelab הזה כחלק מקורס בהנחיית מדריך. המורה צריך:

  • אם צריך, מקצים שיעורי בית.
  • להסביר לתלמידים איך להגיש שיעורי בית.
  • בודקים את שיעורי הבית.

המדריכים יכולים להשתמש בהצעות האלה כמה שרוצים, ומומלץ להם להקצות כל שיעורי בית אחרים שהם חושבים שמתאימים.

אם אתם עובדים על ה-Codelab הזה לבד, אתם יכולים להשתמש בשיעורי הבית האלה כדי לבדוק את הידע שלכם.

פיתוח והרצה של אפליקציה

  1. יוצרים אפליקציה חדשה שמשתמשת בתבנית הפעילות של מפות Google, שנטענת כשמפעילים את האפליקציה.
  2. אחרי שמפת Google נטענת, מעבירים את המצלמה למיקום בית הספר, למיקום הבית או למיקום אחר שחשוב לכם.
  3. מוסיפים שני סמנים למפה, אחד במיקום בית הספר ואחד בבית או במיקום משמעותי אחר.
  4. אתם יכולים לשנות את צבע ברירת המחדל של סמלי הסמנים או להחליף את סמל ברירת המחדל בתמונה בהתאמה אישית.

הערה: אפשר לעיין במסמכי התיעוד של onMapReady (GoogleMap googleMap).

עונים על השאלות הבאות

שאלה 1

איזו שיטה מופעלת כשהמפה נטענת ומוכנה לשימוש באפליקציה?

שאלה 2

אילו רכיבי Android אפשר להשתמש בהם כדי לכלול את מפות Google באפליקציה?

  • MapView וגם MapFragment
  • MapFragment וגם MapActivity
  • MapView וגם MapActivity
  • רק MapFragment

שאלה 3

אילו סוגי מפות מוצעים בממשק ה-API של מפות Google ל-Android?

  • רגילה, היברידית, טופוגרפית, לווינית ומפת דרכים
  • רגיל, היברידי, טופוגרפי, לוויין ו'ללא'
  • היברידית, פני השטח, לוויין, מפת דרכים ו'ללא'
  • רגיל, פני שטח, לוויין, מפת תמונות ו'ללא'

שאלה 4

איזה ממשק מטמיעים כדי להוסיף פונקציונליות של לחיצה על נקודת עניין (POI)?

  • GoogleMap.OnPoiListener
  • GoogleMap.OnPoiClickListener
  • GoogleMap.OnPoiClick
  • GoogleMap.OnPoiClicked

שליחת האפליקציה למתן ציונים

הנחיות למעריכים

בודקים אם האפליקציה כוללת את התכונות הבאות:

  • כשמפעילים את האפליקציה, מפת Google מוצגת בצורה תקינה, מה שמצביע על כך שמפתח ה-API נוצר בצורה תקינה.
  • אחרי שהמפה של Google נטענת, המצלמה עוברת למיקום הבית או בית הספר של התלמיד/ה. בקוד, השלב הזה צריך להתרחש בשיטת הקריאה החוזרת onMapReady (GoogleMap googleMap).
  • סמנים מוצגים במיקום בית הספר של התלמיד/ה ובמיקום אחר, כמו הבית של התלמיד/ה.
  • שני הסמנים מותאמים אישית. לדוגמה, הסמנים משתמשים בצבע שונה מצבע ברירת המחדל האדום, או שהם משתמשים בסמל בהתאמה אישית.

12. ה-Codelab הבא

כדי לראות את כל ה-codelabs בקורס Advanced Android Development (פיתוח מתקדם ל-Android), אפשר להיכנס אל דף הנחיתה של Advanced Android Development codelabs.