Maps API ב-Wear OS

מפה במכשיר לביש

באמצעות ה-SDK של מפות Google ל-Android, אפשר ליצור אפליקציה לבישה מבוססת-מפה שפועלת ישירות במכשירי Wear OS by Google. משתמשי האפליקציה יכולים לראות את המיקום שלהם במפה פשוט להביט על פרקי כפות הידיים שלהם. הם יכולים לשרטט את המיקום במסלול, לדוגמה, ואז להגדיל את התצוגה כדי לראות פרטים, או להקיש על סמן כדי לראות את חלון המידע שהאפליקציה מספקת.

בדף הזה מתוארת הפונקציונליות של ה-API שזמינה במכשיר Wear ונעזור לכם להתחיל לפתח את האפליקציה.

תחילת העבודה ב-Wear OS

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

Android Studio הוא הכלי המומלץ לפיתוח של Wear OS, כי הוא מאפשר להגדיר פרויקטים, לכלול את הספרייה ולהשתמש באריזה.

לקבלת עזרה כללית בעיצוב אפליקציה לבישה, עיינו בהנחיות העיצוב של Wear OS. לקבלת עזרה ביצירת האפליקציה הראשונה לבישה, עיינו במדריך ליצירת אפליקציות לבישות.

פיתוח אפליקציית המפות הראשונה ב-Wear OS

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

מוסיפים יחסי תלות למודול Wear

חשוב לוודא שיחסי התלות הבאים כלולים בקובץ build.gradle במודול Wear OS של האפליקציה:

dependencies {
    // ...
    compileOnly 'com.google.android.wearable:wearable:2.9.0'
    implementation 'com.google.android.support:wearable:2.9.0'
    implementation 'com.google.android.gms:play-services-maps:18.2.0'

    // This dependency is necessary for ambient mode
    implementation 'androidx.wear:wear:1.3.0'
}

למידע נוסף על יחסי התלות, ניתן לעיין במדריך להוספת מודול של Wear OS לפרויקט הקיים.

הטמעה של תנועת החלקה לסגירה והגדרת צבע הרקע הראשוני

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

על מנת להגדיר צבע רקע ראשוני בהתאמה אישית, השתמשו במאפיין ה-XML של map:backgroundColor כדי להגדיר את הצבע שיוצג עד שאריחי המפה ייטענו בפועל.

מוסיפים את הרכיבים SwipeDismissFrameLayout ו-backgroundColor להגדרת הפריסה בתור המאגר של SupportMapFragment:

  <androidx.wear.widget.SwipeDismissFrameLayout
      android:id="@+id/map_container"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        map:backgroundColor="#fff0b2dd" />
  </androidx.wear.widget.SwipeDismissFrameLayout>

כשמקבלים את האובייקט SwipeDismissFrameLayout בפעילות, צריך להוסיף קריאה חוזרת (callback) ולהגדיר את התנהגות הקריאה החוזרת כדי לבצע את פעולת הסגירה הנדרשת, כפי שמוצג בהמשך:

Kotlin



class MainActivity : AppCompatActivity(), OnMapReadyCallback,
                     AmbientModeSupport.AmbientCallbackProvider {


    public override fun onCreate(savedState: Bundle?) {
        super.onCreate(savedState)

        // Set the layout. It only contains a SupportMapFragment and a DismissOverlay.
        setContentView(R.layout.activity_main)

        // Enable ambient support, so the map remains visible in simplified, low-color display
        // when the user is no longer actively using the app but the app is still visible on the
        // watch face.
        val controller = AmbientModeSupport.attach(this)
        Log.d(MainActivity::class.java.simpleName, "Is ambient enabled: " + controller.isAmbient)

        // Retrieve the containers for the root of the layout and the map. Margins will need to be
        // set on them to account for the system window insets.
        val mapFrameLayout = findViewById<SwipeDismissFrameLayout>(R.id.map_container)
        mapFrameLayout.addCallback(object : SwipeDismissFrameLayout.Callback() {
            override fun onDismissed(layout: SwipeDismissFrameLayout) {
                onBackPressed()
            }
        })

        // Obtain the MapFragment and set the async listener to be notified when the map is ready.
        mapFragment = supportFragmentManager
            .findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)
    }

    // ...
}

      

Java


public class MainActivity extends AppCompatActivity implements OnMapReadyCallback,
    AmbientModeSupport.AmbientCallbackProvider {


    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);

        // Set the layout. It only contains a SupportMapFragment and a DismissOverlay.
        setContentView(R.layout.activity_main);

        // Enable ambient support, so the map remains visible in simplified, low-color display
        // when the user is no longer actively using the app but the app is still visible on the
        // watch face.
        AmbientModeSupport.AmbientController controller = AmbientModeSupport.attach(this);
        Log.d(MainActivity.class.getSimpleName(), "Is ambient enabled: " + controller.isAmbient());

        // Retrieve the containers for the root of the layout and the map. Margins will need to be
        // set on them to account for the system window insets.
        final SwipeDismissFrameLayout mapFrameLayout = (SwipeDismissFrameLayout) findViewById(
            R.id.map_container);
        mapFrameLayout.addCallback(new SwipeDismissFrameLayout.Callback() {
            @Override
            public void onDismissed(SwipeDismissFrameLayout layout) {
                onBackPressed();
            }
        });

        // Obtain the MapFragment and set the async listener to be notified when the map is ready.
        mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    // ...
}

      

הוספת מפה

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

Kotlin



private val sydney = LatLng(-33.85704, 151.21522)

override fun onMapReady(googleMap: GoogleMap) {
    // Add a marker with a title that is shown in its info window.
    googleMap.addMarker(
        MarkerOptions().position(sydney)
            .title("Sydney Opera House")
    )

    // Move the camera to show the marker.
    googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 10f))
}

      

Java


private static final LatLng SYDNEY = new LatLng(-33.85704, 151.21522);

@Override
public void onMapReady(@NonNull GoogleMap googleMap) {
    // Add a marker with a title that is shown in its info window.
    googleMap.addMarker(new MarkerOptions().position(SYDNEY)
        .title("Sydney Opera House"));

    // Move the camera to show the marker.
    googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(SYDNEY, 10));
}

      

הפעלת תאורת אווירה

ה-SDK של מפות Google ל-Android תומך במצב סביבה לאפליקציות לביש. אפליקציות שתומכות במצב רגישות לסביבה נקראות לפעמים תמיד באפליקציות. התכונה 'תאורת אווירה' מופעלת כשהמשתמש לא משתמש יותר באפליקציה באופן פעיל, והאפליקציה נשארת גלויה במכשיר הלביש.

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

כדי לוודא שהאפליקציה שלכם משתמשת במצב רגישות לסביבה של המפה:

  1. צריך לעדכן את Android SDK כך שיכלול את הפלטפורמה Android 6.0 (API 23) ואילך, שמספקת את ממשקי ה-API שמאפשרים לפעילויות לעבור למצב רגישות לסביבה. למידע על עדכון ה-SDK, תוכלו לקרוא את מאמרי העזרה של Android על הוספת חבילות SDK.
  2. כדי לוודא שהפרויקט מטרגט את Android 6.0 ואילך, צריך להגדיר את targetSdkVersion ל-23 ואילך במניפסט האפליקציה.
  3. מוסיפים את יחסי התלות של הגאדג'טים הלבישים לקובץ build.gradle של האפליקציה. ראו דוגמה לדף זה.
  4. מוסיפים את רשומת הספרייה המשותפת הלבישה לקובץ המניפסט של האפליקציה הלביש, כפי שמתואר בשיעור האימון של Android בנושא שמירה על הצגת האפליקציה.
  5. מוסיפים את ההרשאה WAKE_LOCK לקובצי המניפסט של האפליקציה הידניים או הלבישים, כפי שמתואר בשיעור האימון של Android בנושא איך לוודא שהאפליקציה נשארת גלויה.
  6. בשיטה onCreate() של הפעילות, קוראים ל-method AmbientModeSupport.attach(). זה אומר למערכת ההפעלה שהאפליקציה פועלת כל הזמן, ולכן כשהמכשיר מכובה אותו הוא צריך לעבור למצב רגישות לסביבה במקום לחזור לתצוגת השעון.
  7. צריך להטמיע את הממשק של AmbientModeSupport.AmbientCallbackProvider בפעילות כדי שיוכל לקבל שינויים במצב האווירה.
  8. עליך להגדיר את המפה לתמיכה במצב רגישות לסביבה. תוכלו לעשות זאת על ידי הגדרת המאפיין map:ambientEnabled="true" בקובץ פריסת ה-XML של הפעילות, או לעשות זאת באופן פרוגרמטי על ידי הגדרת GoogleMapOptions.ambientEnabled(true). ההגדרה הזו מעדכנת את ה-API שעליו לטעון מראש את אריחי המפה הנדרשים לשימוש במצב רגישות לסביבה.
  9. כשהפעילות עוברת למצב רגישות לסביבה, המערכת מפעילה את השיטה onEnterAmbient() ב-AmbientCallback שמספקים. ניתן לבטל את הפעולה של onEnterAmbient() ולהתקשר אל SupportMapFragment.onEnterAmbient(ambientDetails) או אל MapView.onEnterAmbient(ambientDetails). ה-API מחליף את רינדור המפה לא אינטראקטיבי ובצבע נמוך.
  10. באופן דומה, ב-onExitAmbient() מפעילים את SupportMapFragment.onExitAmbient() או MapView.onExitAmbient(). ה-API עובר לעיבוד הרגיל של המפה.

דוגמת הקוד הבאה מפעילה תאורת אווירה בפעילות:

Kotlin



class AmbientActivity : AppCompatActivity(), AmbientModeSupport.AmbientCallbackProvider {

    private lateinit var mapFragment: SupportMapFragment

    public override fun onCreate(savedState: Bundle?) {
        super.onCreate(savedState)

        // Set the layout. It only contains a SupportMapFragment and a DismissOverlay.
        setContentView(R.layout.activity_main)

        // Enable ambient support, so the map remains visible in simplified, low-color display
        // when the user is no longer actively using the app but the app is still visible on the
        // watch face.
        val controller = AmbientModeSupport.attach(this)
        Log.d(AmbientActivity::class.java.simpleName, "Is ambient enabled: " + controller.isAmbient)

        // Obtain the MapFragment and set the async listener to be notified when the map is ready.
        mapFragment = supportFragmentManager
            .findFragmentById(R.id.map) as SupportMapFragment
    }

    override fun getAmbientCallback(): AmbientModeSupport.AmbientCallback {
        return object : AmbientModeSupport.AmbientCallback() {
            /**
             * Starts ambient mode on the map.
             * The API swaps to a non-interactive and low-color rendering of the map when the user is no
             * longer actively using the app.
             */
            override fun onEnterAmbient(ambientDetails: Bundle) {
                super.onEnterAmbient(ambientDetails)
                mapFragment.onEnterAmbient(ambientDetails)
            }

            /**
             * Exits ambient mode on the map.
             * The API swaps to the normal rendering of the map when the user starts actively using the app.
             */
            override fun onExitAmbient() {
                super.onExitAmbient()
                mapFragment.onExitAmbient()
            }
        }
    }
}

      

Java


public class AmbientActivity extends AppCompatActivity implements
    AmbientModeSupport.AmbientCallbackProvider {

    private SupportMapFragment mapFragment;

    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);

        // Set the layout. It only contains a SupportMapFragment and a DismissOverlay.
        setContentView(R.layout.activity_main);

        // Enable ambient support, so the map remains visible in simplified, low-color display
        // when the user is no longer actively using the app but the app is still visible on the
        // watch face.
        AmbientModeSupport.AmbientController controller = AmbientModeSupport.attach(this);
        Log.d(AmbientActivity.class.getSimpleName(), "Is ambient enabled: " + controller.isAmbient());

        // Obtain the MapFragment and set the async listener to be notified when the map is ready.
        mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    }

    @Override
    public AmbientCallback getAmbientCallback() {
        return new AmbientCallback() {
            /**
             * Starts ambient mode on the map.
             * The API swaps to a non-interactive and low-color rendering of the map when the user is no
             * longer actively using the app.
             */
            @Override
            public void onEnterAmbient(Bundle ambientDetails) {
                super.onEnterAmbient(ambientDetails);
                mapFragment.onEnterAmbient(ambientDetails);
            }

            /**
             * Exits ambient mode on the map.
             * The API swaps to the normal rendering of the map when the user starts actively using the app.
             */
            @Override
            public void onExitAmbient() {
                super.onExitAmbient();
                mapFragment.onExitAmbient();
            }
        };
    }
}

      

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

שימוש ב-Street View ב-Wear OS

Street View נתמך באופן מלא במכשירים לבישים.

כדי לאפשר למשתמשים לצאת מהאפליקציה כשהם צופים בפנורמה של Street View, השתמשו בממשק StreetViewPanorama.OnStreetViewPanoramaLongClickListener כדי להאזין לתנועה שנמשכת לחיצה ארוכה. כשמשתמש לוחץ לחיצה ארוכה במקום כלשהו על תמונת Street View, מתקבל אירוע onStreetViewPanoramaLongClick(StreetViewPanoramaOrientation). צריך להתקשר אל DismissOverlayView.show() כדי להציג לחצן יציאה.

קוד לדוגמה

ב-GitHub יש אפליקציה לדוגמה, ואתם יכולים להשתמש בה כנקודת התחלה לאפליקציה. הדוגמה מראה איך מגדירים מפה בסיסית של Google ב-Wear OS.

פונקציונליות נתמכת ב-Maps API ב-Wear OS

בקטע הזה מפורטים ההבדלים בפונקציונליות הנתמכת של מפות במכשירים לבישים בהשוואה למכשירים ניידים (טלפונים וטאבלטים). כל תכונות ה-API שאינן מפורטות בהמשך אמורות לפעול כפי שתועד עבור ה-API המלא.

פונקציונליות
מצב אינטראקטיבי לחלוטין ומצב בסיסי

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

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

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

סרגל הכלים של המפה סרגל הכלים של המפה מושבת ולא ניתן להפעיל אותו במכשיר לביש.
פקדים בממשק המשתמש הפקדים של ממשק המשתמש מושבתים כברירת מחדל במכשירים לבישים. ההגדרות האלה כוללות את הזום, המצפן ופקדי המיקום. אפשר להפעיל אותם באמצעות המחלקה UiSettings כרגיל.
תנועות תנועות בנגיעה אחת פועלות כצפוי. לדוגמה, אפשר לגעת ולגרור כדי להזיז את המפה, להקיש הקשה כפולה כדי להתקרב או להקיש עם שתי אצבעות כדי להתרחק. התמיכה בתנועות בשיטת 'ריבוי נקודות מגע' משתנה בהתאם למכשיר של המשתמש. דוגמאות לתנועות עם מספר נקודות מגע כוללות דחיפה של שתי אצבעות כדי להטות את המפה, תנועת צביטה כדי לשנות את מרחק התצוגה וסיבוב עם שתי אצבעות.
מפות פנים ובניינים מפות פנים מושבתות כברירת מחדל במכשיר לביש. כדי להפעיל אותם, מתקשרים אל GoogleMap.setIndoorEnabled(true). אם מפות פנים מופעלות, במפה תוצג ברירת המחדל של מפלס הקומה. רכיב ממשק המשתמש של בוחר הרמות לא נתמך במכשירים לבישים.
שכבות-על של משבצות שכבות-על של משבצות לא נתמכות במכשירים לבישים.

שיטות מומלצות לפיתוח עם Maps API ב-Wear OS

איך לספק את חוויית המשתמש הטובה ביותר באפליקציה:

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