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

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

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

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

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

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

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

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

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

این راهنمای سریع فرض می‌کند که با «کیت توسعه نرم‌افزار Maps ویژه 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.0.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.0.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، می‌توانید اشاره کشیدن برای بستن را پیاده‌سازی کنید و به کاربران راهی برای خروج از برنامه با کشیدن انگشت از لبه سمت چپ صفحه بدهید.

برای تنظیم رنگ پس‌زمینه اولیه سفارشی، از ویژگی map:backgroundColor XML برای تعریف رنگی که تا زمان بار شدن کاشی‌های نقشه واقعی نمایش داده می‌شود استفاده کنید.

عناصر 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 را دریافت کنید. وقتی نقشه آماده استفاده باشد، بازخوانی راه‌اندازی می‌شود. در روش 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))
}

      

جاوا

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 (API 23) یا بالاتر باشد، که APIهایی را ارائه می‌دهد که به فعالیت‌ها اجازه می‌دهد به حالت محیطی بروند. برای کسب اطلاعات درباره نحوه به‌روزرسانی کیت توسعه نرم‌افزار، به سند Android درباره افزودن بسته‌های کیت توسعه نرم‌افزار مراجعه کنید.
  2. با تنظیم کردن targetSdkVersion روی ۲۳ یا بالاتر در مانیفست برنامه، مطمئن شوید که پروژه شما Android 6.0 یا بالاتر را هدف‌یابی می‌کند.
  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) انجام دهید. این تنظیم به API اطلاع می‌دهد که باید کاشی‌های نقشه لازم را برای استفاده در حالت محیطی ازقبل بار کند.
  9. وقتی فعالیت به حالت محیطی تغییر می‌کند، سیستم روش onEnterAmbient() را در AmbientCallback که ارائه می‌دهید فراخوانی می‌کند. onEnterAmbient() را لغو کنید و با SupportMapFragment.onEnterAmbient(ambientDetails) یا MapView.onEnterAmbient(ambientDetails) تماس بگیرید. API به پردازشی غیرتعاملی و کم‌رنگ از نقشه تغییر می‌کند.
  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 {
        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()
            }
        }
    }
}

      

جاوا

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، قصد راه‌اندازی برنامه تلفن همراه Google Maps وقتی کاربر روی نقشه تک‌ضرب می‌زند غیرفعال است و نمی‌توان آن را در دستگاه پوشیدنی فعال کرد.

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

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

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

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

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