Maps API على Wear OS

خريطة على جهاز قابل للارتداء

باستخدام حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط Google" للتطبيقات المتوافقة مع Android، يمكنك إنشاء تطبيق مخصّص لجهاز قابل للارتداء يستند إلى الخرائط ويعمل مباشرةً على أجهزة Wear OS من Google. يمكن لمستخدمي تطبيقك الاطّلاع على موقعهم الجغرافي على الخريطة بمجرد إلقاء نظرة على معاصمهم. ويمكنهم تحديد موقعهم على مسار، على سبيل المثال، ثم التكبير للحصول على التفاصيل، أو النقر فوق علامة لرؤية نافذة معلومات يوفرها تطبيقك.

توضّح هذه الصفحة وظائف واجهة برمجة التطبيقات المتاحة على جهاز Wear OS وتساعدك في بدء إنشاء تطبيقك.

بدء استخدام Wear OS

إنّ إنشاء تطبيق مخصّص لجهاز قابل للارتداء باستخدام حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط Google" للتطبيقات المتوافقة مع Android هو نفسه بشكل أساسي إنشاء تطبيق "خرائط Google" لأي جهاز Android آخر. يتمثل الاختلاف في تصميمك للشكل الأصغر للجهاز القابل للارتداء، لتحسين قابلية استخدام التطبيق وأدائه.

استوديو Android هو الأداة المقترَحة لتطوير تطبيقات Wear OS، لأنّه يوفّر إعدادات المشروع وتضمين المكتبات وميزات الحزم.

للحصول على مساعدة عامة بشأن تصميم تطبيق مخصّص لجهاز قابل للارتداء، يُرجى الرجوع إلى إرشادات تصميم Wear OS. للحصول على مساعدة في إنشاء أول تطبيق مخصّص لجهاز قابل للارتداء، يُرجى الاطّلاع على دليل إنشاء تطبيقات مخصّصة للأجهزة القابلة للارتداء.

إنشاء أول تطبيق خرائط على Wear OS

يفترض هذا الدليل السريع أنّك على دراية بحزمة تطوير البرامج بالاستناد إلى بيانات خرائط Google للتطبيقات المتوافقة مع 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 للتطبيقات المتوافقة مع Android استخدام وضع عدم النشاط في التطبيقات المخصّصة للأجهزة القابلة للارتداء. تُسمى التطبيقات التي تتوافق مع وضع عدم النشاط أحيانًا تطبيقات التشغيل دائمًا. يتم تفعيل "وضع عدم النشاط" عندما يتوقف المستخدم عن استخدام التطبيق بشكل نشط، ويسمح للتطبيق بالبقاء مرئيًا على الجهاز القابل للارتداء.

توفّر حزمة تطوير البرامج بالاستناد إلى بيانات &quot;خرائط Google&quot; للتطبيقات المتوافقة مع Android عرضًا مبسطًا للخريطة بألوان منخفضة لاستخدامها في وضع عدم النشاط، ويتم تعديل نمط الخريطة تلقائيًا عندما ينتقل الجهاز من الوضع التفاعلي إلى وضع عدم النشاط. تختفي جميع العلامات والعناصر وعناصر التحكّم في واجهة المستخدم في وضع عدم النشاط. يؤدي ذلك إلى تقليل استهلاك الطاقة في تطبيقك وضمان مظهر وأسلوب متّسقَين مع التطبيقات الأخرى التي تتضمّن وضع "الإبقاء على الشاشة مفعَّلة"، مثل خلفيات شاشة الساعة.

اتّبِع الخطوات التالية للتأكّد من أنّ تطبيقك يستخدم وضع عدم النشاط في الخريطة:

  1. حدِّث حزمة تطوير البرامج (SDK) لنظام التشغيل Android لتشمل نظام التشغيل Android 6.0 (المستوى 23 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث، والذي يوفّر واجهات برمجة التطبيقات التي تسمح بالانتقال إلى وضع عدم النشاط. للحصول على معلومات حول كيفية تحديث حزمة SDK، يُرجى الاطّلاع على مستندات Android حول إضافة حزم SDK.
  2. تأكَّد من أنّ مشروعك يستهدف الإصدار 6.0 من نظام التشغيل Android أو الإصدارات الأحدث، وذلك من خلال ضبط targetSdkVersion على 23 أو قيمة أعلى في ملف بيان التطبيق.
  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 أساسية على Wear OS.

الوظائف المتوافقة في Maps API على Wear OS

يوضّح هذا القسم الاختلافات في الوظائف المتاحة للخرائط على الأجهزة القابلة للارتداء مقارنةً بالأجهزة المحمولة (الهواتف والأجهزة اللوحية). يُفترض أن تعمل جميع ميزات واجهة برمجة التطبيقات غير المذكورة أدناه على النحو الموضّح في مستندات واجهة برمجة التطبيقات الكاملة.

الوظائف
وضع التفاعل الكامل والوضع البسيط

يمكنك استخدام حزمة تطوير البرامج بالاستناد إلى بيانات &quot;خرائط Google&quot; للتطبيقات المتوافقة مع Android في الوضع التفاعلي الكامل أو في الوضع البسيط. ننصحك باستخدام &quot;الوضع البسيط&quot; إذا أردت تحسين الأداء على الجهاز القابل للارتداء ولم يكن تطبيقك بحاجة إلى إتاحة التفاعل، مثل الإيماءات أو العرض الشامل للخرائط وتكبيرها أو تصغيرها.

في الوضع المبسّط، يتم إيقاف نية تشغيل تطبيق "خرائط Google" للأجهزة الجوّالة عندما ينقر المستخدم على الخريطة، ولا يمكن تفعيلها على جهاز قابل للارتداء.

للحصول على قائمة كاملة بالاختلافات بين الوضع البسيط والوضع التفاعلي بالكامل، يُرجى الاطّلاع على مستندات الوضع البسيط.

شريط أدوات الخريطة شريط أدوات الخريطة غير مفعَّل ولا يمكن تفعيله على جهاز قابل للارتداء.
عناصر التحكّم في واجهة المستخدم يتم تلقائيًا إيقاف عناصر التحكّم في واجهة المستخدم على الأجهزة القابلة للارتداء. ويشمل ذلك عناصر التحكّم في التكبير/التصغير والبوصلة وموقعي الجغرافي. ويمكنك تفعيلها باستخدام فئة UiSettings كالمعتاد.
الإيماءات تعمل الإيماءات بلمسة واحدة على النحو المتوقّع. ومن الأمثلة على ذلك اللمس والسحب لتحريك الخريطة، والنقر مرّتين للتكبير، والنقر بإصبعين للتصغير. يختلف مدى توفّر الإيماءات عبر اللمس بأكثر من إصبع حسب جهاز المستخدم. تشمل أمثلة الإيماءات عبر اللمس بأكثر من إصبع الدفع بإصبعين لإمالة الخريطة، والتصغير أو التكبير بإصبعين، والتدوير بإصبعين.
الخرائط الداخلية والمباني يتم إيقاف الخرائط الداخلية تلقائيًا على الأجهزة القابلة للارتداء. ويمكنك تفعيلها من خلال استدعاء GoogleMap.setIndoorEnabled(true). إذا كانت الخرائط الداخلية مفعَّلة، ستعرض الخريطة مستوى الطابق التلقائي. لا يتوفّر عنصر في واجهة المستخدم أداة اختيار المستوى على الأجهزة القابلة للارتداء.
تراكبات المربّعات تراكبات المربّعات غير متاحة على الأجهزة القابلة للارتداء.

أفضل الممارسات للتطوير باستخدام Maps API على Wear OS

كيفية تقديم أفضل تجربة للمستخدم في تطبيقك:

  • يجب أن تشغل الخريطة جزءًا كبيرًا من الشاشة. هذا الإجراء ضروري لتحسين قابلية استخدام الخريطة على الأجهزة القابلة للارتداء ذات التصميم الصغير.
  • عند تصميم تجربة المستخدم لتطبيقك، ضع في اعتبارك أنّ الجهاز القابل للارتداء يتضمّن بطارية منخفضة الطاقة. سيؤثر إبقاء الشاشة نشطة والخريطة مرئية في أداء البطارية.