میانای برنامه‌سازی کاربردی Maps در Wear OS

نقشه در دستگاه پوشیدنی

بااستفاده از «کیت توسعه نرم‌افزار Google Maps برای Android»، می‌توانید برنامه پوشیدنی مبتنی بر نقشه ایجاد کنید که مستقیماً در دستگاه‌های Wear OS by Google اجرا می‌شود. کاربران برنامه‌تان می‌توانند فقط با نگاه کردن به مچ دستشان، مکان خود را روی نقشه ببینند. برای مثال، آن‌ها می‌توانند موقعیت خود را روی مسیر ترسیم کنند، سپس برای دیدن جزئیات زوم‌پیش کنند، یا روی نشانگری تک‌ضرب بزنند تا پنجره اطلاعاتی را که برنامه‌تان ارائه کرده است ببینند.

این صفحه عملکرد میانای برنامه‌سازی کاربردی موجود در دستگاه Wear را شرح می‌دهد و به شما کمک می‌کند ساختن برنامه‌تان را شروع کنید.

شروع به کار با Wear OS

ساختن برنامه پوشیدنی با «کیت توسعه نرم‌افزار Google Maps برای Android» اساساً مشابه ساختن برنامه Google Maps برای هر دستگاه Android دیگری است. تفاوت در طراحی شما برای اندازه کوچک‌تر دستگاه پوشیدنی است تا قابلیت استفاده و عملکرد برنامه بهینه‌سازی شود.

استودیو Android ابزار توصیه‌شده برای توسعه Wear OS است، زیرا راه‌اندازی پروژه، گنجاندن کتابخانه، و راحتی بسته‌بندی را فراهم می‌کند.

برای راهنمایی عمومی درباره طراحی برنامه پوشیدنی، به دستورالعمل‌های طراحی Wear OS مراجعه کنید. برای دریافت راهنمایی درباره ایجاد اولین برنامه پوشیدنی، راهنمای ایجاد برنامه‌های پوشیدنی را ببینید.

ساختن اولین برنامه نقشه‌ها در Wear OS

این راهنمای سریع فرض می‌کند که با Maps SDK for Android آشنا هستید، راهنماهای Wear OS را برای ایجاد یک واحد پوشیدنی در برنامه‌تان دنبال کرده‌اید، و اکنون می‌خواهید نقشه‌ای به واحد پوشیدنی اضافه کنید.

درحال افزودن وابستگی‌ها برای واحد Wear

مطمئن شوید که وابستگی‌های زیر در فایل build.gradle.kts ماژول Wear OS برنامه‌تان گنجانده شده باشد:

dependencies {
    // ...
    // Modern Android projects use version catalogs to manage dependencies.  To include the necessary dependencies,
    // first add the following to your libs.versions.toml file:
    //
    // [versions]
    // playServicesMaps = "20.1.0"
    // wear = "1.4.0"
    // wearable = "2.9.0"
    //
    // [libraries]
    // play-services-maps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesMaps" }
    // wear = { group = "androidx.wear", name = "wear", version.ref = "wear" }
    // wearable-compile = { group = "com.google.android.wearable", name = "wearable", version.ref = "wearable" }
    // wearable-support = { group = "com.google.android.support", name = "wearable", version.ref = "wearable" }

    compileOnly(libs.wearable.compile)
    implementation(libs.wearable.support)
    implementation(libs.play.services.maps)

    // This dependency is necessary for ambient mode
    implementation(libs.wear)

    // Android Test Dependencies
    androidTestImplementation(libs.ext.junit)
    androidTestImplementation(libs.espresso.core)
    androidTestImplementation(libs.uiautomator)
    androidTestImplementation(libs.truth)
    androidTestImplementation(libs.junit)
    
    // If your project does not use a version catalog, you can use the following dependencies instead:
    //
    //    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:20.1.0")
    //    implementation("androidx.wear:wear:1.4.0")
    //    androidTestImplementation("androidx.test.ext:junit:1.3.0")
    //    androidTestImplementation("androidx.test.espresso:espresso-core:3.7.0")
    //    androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
    //    androidTestImplementation("com.google.truth:truth:1.4.5")
    //    androidTestImplementation("junit:junit:4.13.2")
}

برای اطلاعات بیشتر درباره وابستگی‌ها، راهنمای افزودن واحد 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(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 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.
        try {
            val controller = AmbientModeSupport.attach(this)
            Log.d(MainActivity::class.java.simpleName, "Is ambient enabled: " + controller.isAmbient)
        } catch (e: Exception) {
            Log.w(MainActivity::class.java.simpleName, "Ambient mode unavailable on this device: ${e.message}")
        }

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

    // ...
}

      

جاوا

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.
        try {
            AmbientModeSupport.AmbientController controller = AmbientModeSupport.attach(this);
            Log.d(
                    MainActivity.class.getSimpleName(),
                    "Is ambient enabled: " + controller.isAmbient());
        } catch (Exception e) {
            Log.w(
                    MainActivity.class.getSimpleName(),
                    "Ambient mode unavailable on this device: " + e.getMessage());
        }

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

      

جاوا

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


      

فعال کردن حالت محیطی

کیت توسعه نرم‌افزار Google Maps برای Android از حالت محیطی برای برنامه‌های پوشیدنی پشتیبانی می‌کند. برنامه‌هایی که از حالت محیطی پشتیبانی می‌کنند گاهی برنامه‌های همیشه روشن نامیده می‌شوند. وقتی کاربر دیگر به‌طور فعال از برنامه استفاده نمی‌کند، «حالت گزینشی» فعال می‌شود و به برنامه اجازه می‌دهد در دستگاه پوشیدنی نمایان بماند.

کیت توسعه نرم‌افزار Google Maps برای Android یک رندرینگ ساده‌شده و کم‌رنگ از نقشه برای استفاده در حالت محیطی ارائه می‌دهد و سبک نقشه به‌طور خودکار وقتی دستگاه از حالت تعاملی به حالت محیطی تغییر می‌کند، تنظیم می‌شود. همه نشانگرها، اشیا، و کنترل‌های میانای کاربر در حالت محیطی ناپدید می‌شوند. این کار مصرف برق برنامه‌تان را کاهش می‌دهد و ظاهر و حسی سازگار با دیگر برنامه‌های محیطی، مثل صفحه‌های ساعت، ایجاد می‌کند.

برای اطمینان از اینکه برنامه‌تان از حالت محیطی نقشه استفاده می‌کند، مراحل زیر را دنبال کنید:

  1. کیت توسعه نرم‌افزار Android خود را به‌روز کنید تا پلاتفرم Android 6.0 (میانای برنامه‌سازی کاربردی ۲۳) یا بالاتر را دربرگیرد. این پلاتفرم میاناهای برنامه‌سازی کاربردی‌ای را ارائه می‌دهد که به فعالیت‌ها اجازه می‌دهد به حالت محیطی بروند. برای کسب اطلاعات درباره نحوه به‌روزرسانی کیت توسعه نرم‌افزار، به سند Android درباره افزودن بسته‌های کیت توسعه نرم‌افزار مراجعه کنید.
  2. با تنظیم targetSdkVersion روی ۲۳ یا بالاتر در مانیفست برنامه، مطمئن شوید پروژه‌تان Android نسخه ۶.۰ یا بالاتر را هدف قرار می‌دهد.
  3. وابستگی‌های پوشیدنی را به فایل build.gradle.kts برنامه‌تان اضافه کنید. نمونه موجود در این صفحه را ببینید.
  4. همان‌طور که در کلاس آموزشی Android درباره نمایان نگه داشتن برنامه توضیح داده شده است، ورودی کتابخانه مشترک پوشیدنی را به مانیفست برنامه پوشیدنی اضافه کنید.
  5. اجازه WAKE_LOCK را به مانیفست‌های برنامه پوشیدنی و دستی اضافه کنید، همان‌طور که در کلاس آموزشی Android درباره نمایان نگه داشتن برنامه توضیح داده شده است.
  6. در روش onCreate() فعالیتتان، روش AmbientModeSupport.attach() را فراخوانی کنید. این کار به سیستم‌عامل می‌گوید که برنامه همیشه روشن است، بنابراین وقتی دستگاه خاموش می‌شود، باید به‌جای بازگشت به صفحه ساعت، وارد حالت محیطی شود.
  7. میانای AmbientModeSupport.AmbientCallbackProvider را در «فعالیت» خود پیاده‌سازی کنید تا بتواند تغییرات وضعیت حالت محیطی را دریافت کند.
  8. نقشه را برای پشتیبانی از حالت محیطی تنظیم کنید. می‌توانید این کار را با تنظیم کردن مشخصه map:ambientEnabled="true" در فایل چیدمان XML فعالیت انجام دهید، یا آن را به‌صورت برنامه‌نویسی‌شده با تنظیم کردن GoogleMapOptions.ambientEnabled(true) انجام دهید. این تنظیم به میانای برنامه‌سازی کاربردی اطلاع می‌دهد که باید کاشی‌های نقشه لازم را برای استفاده در حالت محیطی ازپیش بار کند.
  9. وقتی فعالیت به حالت محیطی تغییر می‌کند، سیستم روش onEnterAmbient() را در AmbientCallback که ارائه می‌دهید فراخوانی می‌کند. onEnterAmbient() را لغو کنید و با SupportMapFragment.onEnterAmbient(ambientDetails) یا MapView.onEnterAmbient(ambientDetails) تماس بگیرید. میانای برنامه‌سازی کاربردی به پرداخت غیرتعاملی و کم‌رنگ نقشه تغییر می‌کند.
  10. به‌طور مشابه، در onExitAmbient() با SupportMapFragment.onExitAmbient() یا MapView.onExitAmbient() تماس بگیرید. میانای برنامه‌سازی کاربردی به رندر کردن عادی نقشه تغییر می‌کند.

نمونه کد زیر حالت محیطی را در فعالیت فعال می‌کند:

Kotlin

class AmbientActivity :
    AppCompatActivity(),
    AmbientModeSupport.AmbientCallbackProvider {

    private lateinit var mapFragment: SupportMapFragment

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

        // 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.
        try {
            val controller = AmbientModeSupport.attach(this)
            Log.d(AmbientActivity::class.java.simpleName, "Is ambient enabled: " + controller.isAmbient)
        } catch (e: Exception) {
            Log.w(AmbientActivity::class.java.simpleName, "Ambient mode unavailable on this device: ${e.message}")
        }

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

      

جاوا

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.
        try {
            AmbientModeSupport.AmbientController controller = AmbientModeSupport.attach(this);
            Log.d(
                    AmbientActivity.class.getSimpleName(),
                    "Is ambient enabled: " + controller.isAmbient());
        } catch (Exception e) {
            Log.w(
                    AmbientActivity.class.getSimpleName(),
                    "Ambient mode unavailable on this device: " + e.getMessage());
        }

        // 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 را در نمایان نگه داشتن برنامه ببینید.

استفاده از «نمای خیابان» در Wear OS

نمای خیابان به‌طور کامل در دستگاه‌های پوشیدنی پشتیبانی می‌شود.

برای اینکه به کاربران اجازه دهید هنگام مشاهده تمام‌نمای «نمای خیابان» از برنامه خارج شوند، از میانای StreetViewPanorama.OnStreetViewPanoramaLongClickListener برای گوش دادن به اشاره کلیک طولانی استفاده کنید. وقتی کاربر روی جایی در تصویر «نمای خیابان» کلیک طولانی می‌کند، رویداد onStreetViewPanoramaLongClick(StreetViewPanoramaOrientation) را دریافت خواهید کرد. برای نمایش دکمه خروج، DismissOverlayView.show() را فراخوانی کنید.

کدگذاری نمونه

برنامه نمونه‌ای در GitHub دردسترس است که می‌توانید از آن به‌عنوان نقطه شروعی برای برنامه‌تان استفاده کنید. این نمونه به شما نشان می‌دهد که چگونه یک Google Map پایه را در Wear OS راه‌اندازی کنید.

عملکردهای پشتیبانی‌شده در Maps API در Wear OS

این بخش تفاوت‌های عملکرد پشتیبانی‌شده برای نقشه‌ها در دستگاه‌های پوشیدنی را در مقایسه با دستگاه‌های دستی (تلفن‌ها و رایانه‌های لوحی) شرح می‌دهد. همه ویژگی‌های API که در زیر ذکر نشده‌اند باید طبق مستندات API کامل کار کنند.

کارکرد
حالت کاملاً تعاملی و حالت ساده‌شده

می‌توانید از کیت توسعه نرم‌افزار Google Maps برای Android در حالت کاملاً تعاملی یا در حالت Lite استفاده کنید. اگر می‌خواهید عملکرد را در دستگاه پوشیدنی بهینه‌سازی کنید و برنامه‌تان نیازی به پشتیبانی از تعاملاتی مثل اشاره‌ها یا حرکت دادن و بزرگ‌نمایی نقشه ندارد، حالت Lite را درنظر بگیرید.

در حالت Lite، هدف از راه‌اندازی برنامه تلفن همراه Google Maps وقتی کاربر روی نقشه تک‌ضرب می‌زند غیرفعال است و نمی‌توان آن را در دستگاه پوشیدنی فعال کرد.

برای مشاهده فهرست کامل تفاوت‌های بین حالت ساده و حالت کاملاً تعاملی، به اسناد حالت ساده مراجعه کنید.

نوارابزار نقشه نوارابزار نقشه غیرفعال است و نمی‌توان آن را در دستگاه پوشیدنی فعال کرد.
کنترل‌های میانای کاربر کنترل‌های میانای کاربر به‌طور پیش‌فرض در دستگاه‌های پوشیدنی غیرفعال است. این شامل کنترل‌های بزرگ‌نمایی، قطب‌نما، و مکان من می‌شود. می‌توانید آن‌ها را بااستفاده از کلاس UiSettings مثل همیشه فعال کنید.
اشاره‌ها اشاره‌های تک‌لمسی طبق انتظار کار می‌کنند. نمونه‌هایی از این اشاره‌ها عبارت‌اند از لمس کردن و کشیدن برای حرکت دادن نقشه، دو تک‌ضرب زدن برای بزرگ‌نمایی، و تک‌ضرب زدن با دو انگشت برای کوچک‌نمایی. پشتیبانی از اشاره‌های چندلمسی بسته به دستگاه کاربر متفاوت است. نمونه‌هایی از اشاره‌های چندلمسی شامل فشار دادن با دو انگشت برای کج کردن نقشه، نزدیک کردن انگشتان برای بزرگ‌نمایی، و چرخش با دو انگشت است.
نقشه‌های داخلی و ساختمان‌ها نقشه‌های داخلی به‌طور پیش‌فرض در دستگاه پوشیدنی غیرفعال است. می‌توانید با تماس گرفتن با GoogleMap.setIndoorEnabled(true) آن‌ها را فعال کنید. اگر نقشه‌های داخلی فعال باشد، نقشه سطح طبقه پیش‌فرض را نشان می‌دهد. عنصر میانای کاربر انتخابگر سطح در دستگاه‌های پوشیدنی پشتیبانی نمی‌شود.
رونهادهای کاشی هم‌پوشانی‌های کاشی در دستگاه‌های پوشیدنی پشتیبانی نمی‌شوند.

روال‌های مطلوب برای توسعه با Maps API در Wear OS

نحوه ارائه بهترین تجربه کاربری در برنامه:

  • نقشه باید بخش بزرگی از صفحه‌نمایش را اشغال کند. این کار برای بهینه‌سازی قابلیت استفاده از نقشه در ضریب شکل کوچک دستگاه پوشیدنی ضروری است.
  • هنگام طراحی تجربه کاربری برنامه‌تان، این واقعیت را درنظر بگیرید که دستگاه پوشیدنی شارژ باتری کمی دارد. فعال نگه داشتن صفحه‌نمایش و نمایان بودن نقشه بر عملکرد باتری تأثیر می‌گذارد.