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.kts של מודול 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:19.0.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 בפעילות, מוסיפים פונקציית קריאה חוזרת ומגדירים את ההתנהגות של פונקציית הקריאה החוזרת כך שתבצע את פעולת הסגירה הנדרשת, כפי שמתואר בהמשך:

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

    // ...
}

      

הוספת מפה

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

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 של מפות ל-Android תומך במצב אווירה לאפליקציות ללבוש חכם. אפליקציות שתומכות במצב רגישות לסביבה נקראות לפעמים אפליקציות תמיד זמינות. מצב רגישות לסביבה מופעל כשהמשתמש כבר לא משתמש באפליקציה באופן פעיל, ומאפשר לאפליקציה להישאר גלויה במכשיר לביש.

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

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

  1. מעדכנים את Android SDK כך שיכלול את הפלטפורמה Android 6.0 (API 23) ואילך, שמספקת את ממשקי ה-API שמאפשרים לפעילויות לעבור למצב אווירה. במסמכי התיעוד של Android מוסבר איך מעדכנים את ה-SDK הוספת חבילות SDK.
  2. מוודאים שהפרויקט מטרגט ל-Android 6.0 ואילך, על ידי הגדרת הערך targetSdkVersion ל-23 ואילך במניפסט של האפליקציה.
  3. מוסיפים את יחסי התלות במכשירים לבישים לקובץ build.gradle.kts של האפליקציה. בדוגמה בדף הזה.
  4. מוסיפים את הרשומה של הספרייה המשותפת ללבוש חכם למניפסט של האפליקציה ללבוש חכם, כפי שמתואר בסדנת ההדרכה של Android בנושא שמירה על החשיפה של האפליקציה.
  5. מוסיפים את ההרשאה WAKE_LOCK למניפסטים של האפליקציות לנייד ולמכשירים לבישים, כפי שמתואר בסדנת הדרכה של Android בנושא שמירה על החשיפה של האפליקציה.
  6. ב-method‏ 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 של מפות ל-Android במצב אינטראקטיבי מלא או במצב טעינה מהירה. מומלץ להשתמש במצב בסיסי אם רוצים לבצע אופטימיזציה של הביצועים במכשיר לביש, והאפליקציה לא צריכה לתמוך באינטראקציה כמו תנועות או החלקה והגדלת המפה.

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

רשימה מלאה של ההבדלים בין מצב Lite למצב אינטראקטיבי מלא מופיעה במאמר העזרה בנושא מצב Lite.

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

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

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

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