Maps API ב-Wear OS

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

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

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

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

בניית אפליקציה לבישה באמצעות SDK של מפות ל-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.1.0'

    // This dependency is necessary for ambient mode
    implementation 'androidx.wear:wear:1.2.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) והגדירו את התנהגות הקריאה החוזרת כדי לבצע את פעולת הסגירה הנדרשת, כפי שמתואר בהמשך:

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);
    }

    // ...
}

      

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)
    }

    // ...
}

      

הוספת מפה

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

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));
}

      

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))
}

      

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

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

ב-SDK של מפות ל-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. כשהפעילות עוברת למצב אווירה, המערכת קוראת ל-method onEnterAmbient() ב-AmbientCallback שאתם מספקים. משנים את onEnterAmbient() ומתקשרים ל-SupportMapFragment.onEnterAmbient(ambientDetails) או ל-MapView.onEnterAmbient(ambientDetails). ממשק ה-API עובר רינדור למודעה שאינה אינטראקטיבית ובצבע נמוך.
  10. באופן דומה, בonExitAmbient() התקשרו אל SupportMapFragment.onExitAmbient() או MapView.onExitAmbient(). ה-API עובר לעיבוד הרגיל של המפה.

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

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();
            }
        };
    }
}

      

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()
            }
        }
    }
}

      

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

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

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

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

קוד לדוגמה

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

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

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

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

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

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

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

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

שיטות מומלצות לפיתוח באמצעות ה-API של מפות Google ב-Wear OS

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

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