Maps API для Wear OS

Оптимизируйте свои подборки Сохраняйте и классифицируйте контент в соответствии со своими настройками.
Карта, отображаемая на носимом устройстве

С помощью Maps SDK для Android можно добавить поддержку карт в приложение для носимых устройств с операционной системой Wear OS by Google. Пользователи приложения смогут определять свое положение на карте одним взглядом на экран. Они смогут пользоваться такими функциями карт, как маршруты, изменение масштаба, просмотр информации об объектах и т. п.

На этой странице описываются функциональные возможности API, доступные для носимых устройств, и приводятся рекомендации, которые помогут вам начать разработку приложения.

Начало работы с Wear OS

Приложения для носимых устройств с использованием Maps SDK для Android разрабатываются в целом так же, как и для любых других устройств Android. Различия обусловлены меньшими размерами носимых устройств и необходимостью оптимизировать интерфейс приложения и его производительность.

Инструмент Android Studio является рекомендуемой средой разработки приложений для Wear OS. Он поддерживает настройку проектов, включение библиотек и средства создания пакета приложения.

Мы подготовили общую информацию о дизайне приложений для Wear OS и рекомендации по разработке вашего первого приложения для носимых устройств.

Как создать свое первое приложение для работы с картами на Wear OS

В этом кратком руководстве предполагается следующее: вы знакомы с Maps SDK для Android; вы создали в своем приложении модуль для носимых устройств, следуя рекомендациям из руководства по разработке для Wear OS; вы хотите добавить поддержку карт в этот модуль.

Добавление зависимостей в модуль для носимых устройств

Убедитесь, что в файл 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.0.2'

    // 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 в своем объекте activity добавьте обратный вызов и задайте для него выполнение необходимого действия закрытия приложения, как показано ниже.

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

    // ...
}

      

Добавление карты

Используйте метод обратного вызова onMapReady(GoogleMap), чтобы получить дескриптор объекта GoogleMap. Обратный вызов выполняется тогда, когда карта готова к использованию. В методе обратного вызова вы можете поместить на карту маркеры или ломаные линии, добавить прослушиватели или переместить камеру. В приведенном ниже примере реализовано добавление маркера рядом с Сиднейским оперным театром.

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

      

Включение спящего режима

Maps SDK для Android поддерживает спящий режим в приложениях для носимых устройств. Приложения, поддерживающие спящий режим, называются всегда включенными. Спящий режим активируется, если пользователь не выполнял никаких действий в приложении в течение некоторого времени. Приложение в этом режиме остается на экране носимого устройства.

Maps SDK для Android поддерживает упрощенную прорисовку карты с приглушенными цветами в спящем режиме. Стиль карты автоматически изменяется, когда приложение переходит из интерактивного режима в спящий. В спящем режиме не отображаются какие-либо маркеры, объекты и элементы интерфейса. Это позволяет сократить энергопотребление и сделать стиль интерфейса похожим на стиль других приложений для спящего режима, таких как циферблаты часов.

Чтобы обеспечить поддержку спящего режима карты в вашем приложении, выполните следующие действия:

  1. Обновите Android SDK, включив в него платформу Android 6.0 (API уровня 23) или более поздней версии с API для поддержки перехода приложения в спящий режим. Подробнее о том, как обновить SDK, рассказывается в документации Android по добавлению пакетов SDK.
  2. В качестве целевой платформы своего приложения укажите Android версии 6.0 или более поздней, указав для параметра targetSdkVersion в манифесте приложения значение 23 или выше.
  3. Добавьте в файл build.gradle своего приложения зависимости для поддержки носимых устройств. См. пример.
  4. Укажите в манифесте своего приложения для носимых устройств общую библиотеку для поддержки носимых устройств согласно инструкциям.
  5. Добавьте разрешение WAKE_LOCK в манифесты носимых и мобильных устройств согласно инструкциям в этом уроке.
  6. В методе onCreate() своего класса activity вызовите метод AmbientModeSupport.attach(). Это сообщит операционной системе о том, что приложение должно быть всегда включено, поэтому при переходе устройства в энергосберегающий режим приложение должно перейти в спящий режим, а не вернуться к интерфейсу часов.
  7. Реализуйте интерфейс AmbientModeSupport.AmbientCallbackProvider в объекте Activity, чтобы он получал данные об изменении состояния спящего режима.
  8. Настройте для своей карты поддержку спящего режима. Для этого можно задать атрибут map:ambientEnabled="true" в XML-файле макета вашего объекта activity или сделать это программными средствами с помощью GoogleMapOptions.ambientEnabled(true). Эта настройка уведомляет API о том, что требуется предварительно загрузить необходимые фрагменты карты для использования в спящем режиме.
  9. Когда объект activity переключается в спящий режим, система вызывает метод onEnterAmbient() в заданном вами объекте AmbientCallback. Переопределите метод onEnterAmbient(), реализовав вызов метода SupportMapFragment.onEnterAmbient(ambientDetails) или MapView.onEnterAmbient(ambientDetails). API перейдет в неинтерактивный режим отрисовки карты с приглушенными цветами.
  10. Аналогичным образом в методе onExitAmbient() вызовите метод SupportMapFragment.onExitAmbient() или MapView.onExitAmbient(). API перейдет в нормальный режим отрисовки карты.

Следующий пример кода активирует спящий режим в объекте activity:

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

      

Вы можете обновлять экран, когда приложение находится в спящем режиме. Подробнее о способах обновления контента и о спящем режиме в целом

Использование Просмотра улиц на Wear OS

Просмотр улиц полностью поддерживается на носимых устройствах.

Чтобы разрешить пользователям выходить из приложения при просмотре панорам Просмотра улиц, используйте интерфейс StreetViewPanorama.OnStreetViewPanoramaLongClickListener отслеживающий долгие нажатия. Когда пользователь совершит долгое нажатие на любую область изображения Просмотра улиц, вы получите событие onStreetViewPanoramaLongClick(StreetViewPanoramaOrientation). Вызовите метод DismissOverlayView.show(), чтобы показать кнопку выхода.

Пример кода

На сайте GitHub доступен пример приложения, который поможет вам начать разработку. В нем показано, как добавлять базовую карту в приложение для Wear OS.

Поддерживаемые функции в Maps API для Wear OS

В этом разделе описываются различия поддерживаемых функций для карт на носимых устройствах в сравнении с мобильными устройствами (телефонами и планшетами). Все функции API, не указанные ниже, должны работать так, как описано в документации к полноценному интерфейсу API.

Функции
Полностью интерактивный режим и упрощенный режим

Maps SDK для Android можно использовать как в полностью интерактивном, так и в упрощенном режиме. Упрощенный режим позволяет оптимизировать производительность на носимом устройстве и может использоваться, если приложению не нужно поддерживать различные варианты взаимодействия, такие как жесты, панорамирование или масштабирование карты.

В упрощенном режиме на носимых устройствах отключена функция запуска мобильного приложения "Google Карты" при нажатии на карту, показанную на экране. Включить эту функцию нельзя.

Полный список различий между полностью интерактивным и упрощенным режимами приведен в документации упрощенного режима.

Панель инструментов на карте Панель инструментов на карте отключена на носимых устройствах, и включить ее нельзя.
Элементы управления пользовательского интерфейса По умолчанию элементы управления пользовательского интерфейса отключены на носимых устройствах. Это относится к кнопкам масштабирования, компасу и кнопке "Мое местоположение". Их можно включить с помощью класса UiSettings.
Жесты Жесты с одним касанием работают обычным образом. Примеры жестов с одним касанием: перетаскивание прокручивает карту, двойное касание увеличивает масштаб, касание двумя пальцами уменьшает масштаб. Поддержка жестов с несколькими касаниями зависит от устройства. Примеры жестов с несколькими касаниями: нажатие двумя пальцами для наклона карты, сведение или разведение двух пальцев для масштабирования, вращение карты двумя пальцами.
Схемы зданий и строения Схемы зданий по умолчанию отключены на носимых устройствах. Их можно включить с помощью метода GoogleMap.setIndoorEnabled(true). Если схемы зданий включены, то на карте будет отображаться уровень этажа, выбираемый по умолчанию. Элемент интерфейса для выбора этажа не поддерживается на носимых устройствах.
Наложения фрагментов карты Наложения фрагментов карты не поддерживаются на носимых устройствах.

Рекомендации по разработке приложений с интеграцией API Карт для Wear OS

Для создания максимально удобного пользовательского интерфейса в вашем приложении соблюдайте следующие принципы:

  • Карта должна занимать значительную часть экрана. Это необходимо для того, чтобы карту было удобно использовать на носимом устройстве малого размера.
  • Дизайн приложения нужно продумать с учетом небольшой емкости аккумуляторов носимых устройств. Постоянно включенный экран и непрерывное отображение карты значительно сократят время работы устройства от аккумулятора.