Поддержка непрерывности работы на разных устройствах в Google Books, Поддержка непрерывности работы на разных устройствах в Google Books, Поддержка непрерывности работы на разных устройствах в Google Books, Поддержка непрерывности работы на разных устройствах в Google Books

Пользователи часто начинают выполнение задач на своих телефонах Android — например, просматривают документы, сортируют сообщения или изучают различные элементы — а затем хотят перейти к GoogleBook с его большим дисплеем, физической клавиатурой и многооконным рабочим пространством.

Функция «Продолжить» в Android 17 (уровень API 37) и выше позволяет панели задач Google Books отображать значок приложения (так называемое предложение ) для активности, которую пользователь выполнял на ближайшем телефоне. Одним щелчком мыши пользователи могут продолжить свою активность в Google Books.

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

Выберите схему передачи управления.

Прежде чем включить функцию переключения между устройствами, определите, как должно открываться каждое действие в вашем мобильном приложении, когда пользователь выбирает предложение «Продолжить» в Google Books:

Процесс передачи управления Target на Googlebook Лучше всего подходит для Ключ API
Передача данных между приложениями Нативный Android-приложение, работающее в окне рабочего стола. Приложения, оптимизированные для больших экранов и оконного режима рабочего стола, доступны в Google Play. HandoffActivityData.Builder
Переключение между приложениями с резервным веб-интерфейсом. Если установлено нативное приложение Android, то в противном случае — URL-адрес в браузере по умолчанию на компьютере. Приложения, оптимизированные для работы в оконном режиме рабочего стола, но требующие надежного резервного варианта в браузере, если приложение не установлено на Google Books. setFallbackUri
Прямая передача данных в веб-браузер URL-адрес в браузере по умолчанию на компьютере (или перехваченный собственным приложением, если настроено использование ссылок в приложениях Android ). Рабочие процессы, в которых ваше веб-приложение является основным интерфейсом для настольных компьютеров. HandoffActivityData.createWebHandoff

Включить передачу управления для выполнения действия

Функция «Продолжить» по умолчанию отключена и настраивается для каждого действия. Выполните следующие действия для каждого действия отправки на телефоне:

  1. Вызовите setHandoffEnabled и передайте true после того, как активность загрузит состояние, необходимое для передачи управления. После включения система сможет запрашивать данные для передачи управления, пока активность находится на переднем плане или переходит в фоновый режим.
  2. Переопределите onHandoffActivityDataRequested , чтобы он возвращал ненулевой объект HandoffActivityData . Вы можете в любой момент запросить isHandoffEnabled , чтобы проверить, активна ли передача управления для данного действия.
import android.app.Activity
import android.app.HandoffActivityData
import android.app.HandoffActivityDataRequestInfo
import android.os.Bundle
import android.os.PersistableBundle

class DocumentEditorActivity : Activity() {

    private var documentId: String = "doc_42"
    private var scrollOffsetPx: Int = 0

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

        // Enable handoff once the activity is ready to transfer state.
        setHandoffEnabled(true, null)
    }

    override fun onHandoffActivityDataRequested(
        handoffRequestInfo: HandoffActivityDataRequestInfo
    ): HandoffActivityData {
        val extras = PersistableBundle().apply {
            putString(EXTRA_DOCUMENT_ID, documentId)
            putInt(EXTRA_SCROLL_OFFSET, scrollOffsetPx)
        }

        return HandoffActivityData.Builder(getComponentName())
            .setExtras(extras)
            .build()
    }

    companion object {
        const val EXTRA_DOCUMENT_ID = "extra_document_id"
        const val EXTRA_SCROLL_OFFSET = "extra_scroll_offset"
    }
}

Состояние активности пакета для передачи

Система вызывает onHandoffActivityDataRequested в двух сценариях:

  • Переключение на передний план: Действие находится на переднем плане телефона, и пользователь инициирует переключение с панели задач Google Books.
  • Захват состояния в фоновом режиме: действие на телефоне переходит в фоновый режим, и система кэширует данные, полученные при передаче управления, на случай, если пользователь позже выберет предложенный вариант в Google Books.

Проверьте, активен ли запрос на передачу управления.

Используйте isActiveRequest для проверки HandoffActivityDataRequestInfo , чтобы различать активную передачу данных, инициированную пользователем, и сохранение в фоновом режиме:

  • Если isActiveRequest возвращает true , это означает, что пользователь активно запросил продолжение работы на другом устройстве, пока активность видна.
  • Если isActiveRequest возвращает false , система кэширует состояние, поскольку активность прекращается.

Если вы отображаете на телефоне визуальный индикатор, подтверждающий перемещение задачи в Google Books, запланируйте асинхронное обновление пользовательского интерфейса, чтобы onHandoffActivityDataRequested возвращал значение без задержки.

Добавьте дополнительные государственные ресурсы и резервный веб-интерфейс.

В состав полезной нагрузки HandoffActivityData входит следующая информация:

  • Целевой компонент (необходим для передачи данных между приложениями): передайте this.getComponentName() ( ComponentName активности) или явно указанное ComponentName(this, TargetActivity::class.java) в HandoffActivityData.Builder , чтобы указать, какая активность запустится в GoogleBook.
  • Дополнительные параметры (необязательно): передайте объект PersistableBundle в функцию setExtras() , содержащий идентификаторы и координаты пользовательского интерфейса (например, идентификаторы открытых документов, активные клавиши Tab или позиции прокрутки). Размер объекта должен быть меньше 50 КБ.
  • Резервный URI (необязательно): передайте веб- Uri в функцию setFallbackUri , чтобы Googlebook мог открыть задачу в браузере по умолчанию, если ваше приложение для Android не установлено.
import android.app.Activity
import android.app.HandoffActivityData
import android.app.HandoffActivityDataRequestInfo
import android.app.HandoffActivityParams
import android.net.Uri
import android.os.Bundle
import android.os.PersistableBundle

class ArticleReaderActivity : Activity() {

    private var articleId: String = "android-desktop-windowing"
    private var readingProgressPercent: Int = 45

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

        setHandoffEnabled(
            true,
            HandoffActivityParams.Builder()
                .setAllowHandoffWithoutPackageInstalled(true)
                .build()
        )
    }

    override fun onHandoffActivityDataRequested(
        handoffRequestInfo: HandoffActivityDataRequestInfo
    ): HandoffActivityData {
        if (handoffRequestInfo.isActiveRequest()) {
            window.decorView.post {
                onHandoffStartedToSecondaryDevice()
            }
        }

        val extras = PersistableBundle().apply {
            putString(EXTRA_ARTICLE_ID, articleId)
            putInt(EXTRA_READING_PROGRESS, readingProgressPercent)
        }

        val fallbackWebUri = Uri.Builder()
            .scheme("https")
            .authority("example.com")
            .appendPath("articles")
            .appendPath(articleId)
            .appendQueryParameter("progress", readingProgressPercent.toString())
            .build()

        return HandoffActivityData.Builder(getComponentName())
            .setExtras(extras)
            .setFallbackUri(fallbackWebUri)
            .build()
    }

    private fun onHandoffStartedToSecondaryDevice() {
        // Save local drafts and update phone UI without blocking handoff.
    }

    companion object {
        const val EXTRA_ARTICLE_ID = "extra_article_id"
        const val EXTRA_READING_PROGRESS = "extra_reading_progress"
    }
}

Настройте прямую передачу данных в веб-интерфейс.

Если вы используете веб-приложение на настольном компьютере в Google Books, передайте HandoffActivityParams с setAllowHandoffWithoutPackageInstalled(true) в метод setHandoffEnabled и вызовите HandoffActivityData.createWebHandoff вместо использования HandoffActivityData.Builder :

import android.app.Activity
import android.app.HandoffActivityData
import android.app.HandoffActivityDataRequestInfo
import android.app.HandoffActivityParams
import android.net.Uri
import android.os.Bundle

class WebDashboardActivity : Activity() {

    private var projectId: String = "proj_901"

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

        setHandoffEnabled(
            true,
            HandoffActivityParams.Builder()
                .setAllowHandoffWithoutPackageInstalled(true)
                .build()
        )
    }

    override fun onHandoffActivityDataRequested(
        handoffRequestInfo: HandoffActivityDataRequestInfo
    ): HandoffActivityData {
        val webUri = Uri.Builder()
            .scheme("https")
            .authority("app.example.com")
            .appendPath("projects")
            .appendPath(projectId)
            .build()

        return HandoffActivityData.createWebHandoff(webUri)
    }
}

Получение и восстановление состояния в Google Books

Когда пользователь выбирает подсказку «Продолжить» на панели задач Google Books, система запускает целевой ComponentName в окне рабочего стола и добавляет дополнительные компоненты PersistableBundle к Intent запуска.

В Google Books при обработке входящего вызова учитывайте особенности оконного режима и многопанельной компоновки рабочего стола:

  1. Извлечение дополнительных данных при передаче: В методах onCreate и onNewIntent принимающей активности извлеките дополнительные данные из входящего Intent . Обработка onNewIntent гарантирует, что если ваша активность использует режим запуска singleTop или перенаправляет на существующее окно рабочего стола, окно обновится до переданного элемента.
  2. Адаптируйте состояние к многопанельным макетам: состояние, занимавшее полноэкранный режим просмотра подробной информации на телефоне, часто соответствует выбранному элементу внутри макета списка с подробной информацией или вспомогательной панели в Google Books. Заполните как основной выбор в списке, так и панель с подробной информацией, чтобы окно на настольном компьютере имело полный контекст.
  3. Сохранение восстановленного состояния при изменении размера окна: сохраните переданное состояние в ViewModel ( SavedStateHandle ) или rememberSaveable в Jetpack Compose, чтобы произвольное изменение размера окна в Google Books не приводило к сбросу восстановленной сессии.
import android.app.Activity
import android.content.Intent
import android.os.Bundle

class DocumentEditorReceiverActivity : Activity() {

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

        // Restore from the handoff intent only on initial launch so subsequent
        // desktop window configuration changes use saved instance state.
        if (savedInstanceState == null) {
            handleHandoffIntent(intent)
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent)
        handleHandoffIntent(intent)
    }

    private fun handleHandoffIntent(incomingIntent: Intent?) {
        val documentId = incomingIntent?.getStringExtra(EXTRA_DOCUMENT_ID)
            ?: return
        val scrollOffsetPx = incomingIntent.getIntExtra(EXTRA_SCROLL_OFFSET, 0)

        openDocumentInDesktopWorkspace(
            documentId = documentId,
            initialScrollOffsetPx = scrollOffsetPx
        )
    }

    private fun openDocumentInDesktopWorkspace(
        documentId: String,
        initialScrollOffsetPx: Int
    ) {
        // Load the document into the list-detail layout and restore scroll position.
    }

    companion object {
        const val EXTRA_DOCUMENT_ID = "extra_document_id"
        const val EXTRA_SCROLL_OFFSET = "extra_scroll_offset"
    }
}

Проверьте возможность переключения между телефоном и Google Books.

Для комплексной проверки вашей реализации:

  1. Подготовьте оба устройства.
    • Войдите в одну и ту же учетную запись Google как на своем телефоне Android (с Android 17 или выше), так и на GoogleBook (или на тестовом устройстве, работающем в оконном режиме, как на рабочем столе).
    • Включите Bluetooth и подключите оба устройства к одной и той же сети Wi-Fi.
    • На обоих устройствах откройте «Настройки» > «Подключенные устройства» > «Параметры подключения» > «Службы между устройствами» > «Продолжить активность» , следуйте инструкциям по настройке и включите «Задачи» . Полные требования к среде см. в разделе «Настройка и тестирование» .
  2. Установите приложение
    • Для переключения между приложениями установите свою сборку как на телефон, так и на Google Books.
    • Для резервного веб-доступа или прямой передачи данных в веб-браузер установите свою сборку на телефон и оставьте приложение удаленным в Google Books, чтобы убедиться, что браузер открывает ожидаемый URL-адрес.
  3. Инициировать передачу управления
    • На телефоне откройте приложение и перейдите к активности, которая включает функцию Handoff (вызовите setHandoffEnabled(true, null) для переключения между приложениями или передайте HandoffActivityParams с помощью setAllowHandoffWithoutPackageInstalled(true) при тестировании с приложением, удаленным на Google Books).
    • В приложении Google Books найдите значок вашего приложения со значком «Продолжить» в правой части панели задач и выберите его.
  4. Проверка восстановления рабочего стола
    • Убедитесь, что ваше приложение открывается в окне рабочего стола (или вкладке браузера) точно на том же элементе и в том же месте прокрутки, что и на телефоне.
    • Измените размер окна приложения в Google Books и убедитесь, что восстановленный контент и выделение сохраняются при изменении размера окна.

Дополнительные ресурсы

,

Пользователи часто начинают выполнение задач на своих телефонах Android — например, просматривают документы, сортируют сообщения или изучают различные элементы — а затем хотят перейти к GoogleBook с его большим дисплеем, физической клавиатурой и многооконным рабочим пространством.

Функция «Продолжить» в Android 17 (уровень API 37) и выше позволяет панели задач Google Books отображать значок приложения (так называемое предложение ) для активности, которую пользователь выполнял на ближайшем телефоне. Одним щелчком мыши пользователи могут продолжить свою активность в Google Books.

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

Выберите схему передачи управления.

Прежде чем включить функцию переключения между устройствами, определите, как должно открываться каждое действие в вашем мобильном приложении, когда пользователь выбирает предложение «Продолжить» в Google Books:

Процесс передачи управления Target на Googlebook Лучше всего подходит для Ключ API
Передача данных между приложениями Нативный Android-приложение, работающее в окне рабочего стола. Приложения, оптимизированные для больших экранов и оконного режима рабочего стола, доступны в Google Play. HandoffActivityData.Builder
Переключение между приложениями с резервным веб-интерфейсом. Если установлено нативное приложение Android, то в противном случае — URL-адрес в браузере по умолчанию на компьютере. Приложения, оптимизированные для работы в оконном режиме рабочего стола, но требующие надежного резервного варианта в браузере, если приложение не установлено на Google Books. setFallbackUri
Прямая передача данных в веб-браузер URL-адрес в браузере по умолчанию на компьютере (или перехваченный собственным приложением, если настроено использование ссылок в приложениях Android ). Рабочие процессы, в которых ваше веб-приложение является основным интерфейсом для настольных компьютеров. HandoffActivityData.createWebHandoff

Включить передачу управления для выполнения действия

Функция «Продолжить» по умолчанию отключена и настраивается для каждого действия. Выполните следующие действия для каждого действия отправки на телефоне:

  1. Вызовите setHandoffEnabled и передайте true после того, как активность загрузит состояние, необходимое для передачи управления. После включения система сможет запрашивать данные для передачи управления, пока активность находится на переднем плане или переходит в фоновый режим.
  2. Переопределите onHandoffActivityDataRequested , чтобы он возвращал ненулевой объект HandoffActivityData . Вы можете в любой момент запросить isHandoffEnabled , чтобы проверить, активна ли передача управления для данного действия.
import android.app.Activity
import android.app.HandoffActivityData
import android.app.HandoffActivityDataRequestInfo
import android.os.Bundle
import android.os.PersistableBundle

class DocumentEditorActivity : Activity() {

    private var documentId: String = "doc_42"
    private var scrollOffsetPx: Int = 0

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

        // Enable handoff once the activity is ready to transfer state.
        setHandoffEnabled(true, null)
    }

    override fun onHandoffActivityDataRequested(
        handoffRequestInfo: HandoffActivityDataRequestInfo
    ): HandoffActivityData {
        val extras = PersistableBundle().apply {
            putString(EXTRA_DOCUMENT_ID, documentId)
            putInt(EXTRA_SCROLL_OFFSET, scrollOffsetPx)
        }

        return HandoffActivityData.Builder(getComponentName())
            .setExtras(extras)
            .build()
    }

    companion object {
        const val EXTRA_DOCUMENT_ID = "extra_document_id"
        const val EXTRA_SCROLL_OFFSET = "extra_scroll_offset"
    }
}

Состояние активности пакета для передачи

Система вызывает onHandoffActivityDataRequested в двух сценариях:

  • Переключение на передний план: Действие находится на переднем плане телефона, и пользователь инициирует переключение с панели задач Google Books.
  • Захват состояния в фоновом режиме: действие на телефоне переходит в фоновый режим, и система кэширует данные, полученные при передаче управления, на случай, если пользователь позже выберет предложенный вариант в Google Books.

Проверьте, активен ли запрос на передачу управления.

Используйте isActiveRequest для проверки HandoffActivityDataRequestInfo , чтобы различать активную передачу данных, инициированную пользователем, и сохранение в фоновом режиме:

  • Если isActiveRequest возвращает true , это означает, что пользователь активно запросил продолжение работы на другом устройстве, пока активность видна.
  • Если isActiveRequest возвращает false , система кэширует состояние, поскольку активность прекращается.

Если вы отображаете на телефоне визуальный индикатор, подтверждающий перемещение задачи в Google Books, запланируйте асинхронное обновление пользовательского интерфейса, чтобы onHandoffActivityDataRequested возвращал значение без задержки.

Добавьте дополнительные государственные ресурсы и резервный веб-интерфейс.

В состав полезной нагрузки HandoffActivityData входит следующая информация:

  • Целевой компонент (необходим для передачи данных между приложениями): передайте this.getComponentName() ( ComponentName активности) или явно указанное ComponentName(this, TargetActivity::class.java) в HandoffActivityData.Builder , чтобы указать, какая активность запустится в GoogleBook.
  • Дополнительные параметры (необязательно): передайте объект PersistableBundle в функцию setExtras() , содержащий идентификаторы и координаты пользовательского интерфейса (например, идентификаторы открытых документов, активные клавиши Tab или позиции прокрутки). Размер объекта должен быть меньше 50 КБ.
  • Резервный URI (необязательно): передайте веб- Uri в функцию setFallbackUri , чтобы Googlebook мог открыть задачу в браузере по умолчанию, если ваше приложение для Android не установлено.
import android.app.Activity
import android.app.HandoffActivityData
import android.app.HandoffActivityDataRequestInfo
import android.app.HandoffActivityParams
import android.net.Uri
import android.os.Bundle
import android.os.PersistableBundle

class ArticleReaderActivity : Activity() {

    private var articleId: String = "android-desktop-windowing"
    private var readingProgressPercent: Int = 45

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

        setHandoffEnabled(
            true,
            HandoffActivityParams.Builder()
                .setAllowHandoffWithoutPackageInstalled(true)
                .build()
        )
    }

    override fun onHandoffActivityDataRequested(
        handoffRequestInfo: HandoffActivityDataRequestInfo
    ): HandoffActivityData {
        if (handoffRequestInfo.isActiveRequest()) {
            window.decorView.post {
                onHandoffStartedToSecondaryDevice()
            }
        }

        val extras = PersistableBundle().apply {
            putString(EXTRA_ARTICLE_ID, articleId)
            putInt(EXTRA_READING_PROGRESS, readingProgressPercent)
        }

        val fallbackWebUri = Uri.Builder()
            .scheme("https")
            .authority("example.com")
            .appendPath("articles")
            .appendPath(articleId)
            .appendQueryParameter("progress", readingProgressPercent.toString())
            .build()

        return HandoffActivityData.Builder(getComponentName())
            .setExtras(extras)
            .setFallbackUri(fallbackWebUri)
            .build()
    }

    private fun onHandoffStartedToSecondaryDevice() {
        // Save local drafts and update phone UI without blocking handoff.
    }

    companion object {
        const val EXTRA_ARTICLE_ID = "extra_article_id"
        const val EXTRA_READING_PROGRESS = "extra_reading_progress"
    }
}

Настройте прямую передачу данных в веб-интерфейс.

Если вы используете веб-приложение на настольном компьютере в Google Books, передайте HandoffActivityParams с setAllowHandoffWithoutPackageInstalled(true) в метод setHandoffEnabled и вызовите HandoffActivityData.createWebHandoff вместо использования HandoffActivityData.Builder :

import android.app.Activity
import android.app.HandoffActivityData
import android.app.HandoffActivityDataRequestInfo
import android.app.HandoffActivityParams
import android.net.Uri
import android.os.Bundle

class WebDashboardActivity : Activity() {

    private var projectId: String = "proj_901"

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

        setHandoffEnabled(
            true,
            HandoffActivityParams.Builder()
                .setAllowHandoffWithoutPackageInstalled(true)
                .build()
        )
    }

    override fun onHandoffActivityDataRequested(
        handoffRequestInfo: HandoffActivityDataRequestInfo
    ): HandoffActivityData {
        val webUri = Uri.Builder()
            .scheme("https")
            .authority("app.example.com")
            .appendPath("projects")
            .appendPath(projectId)
            .build()

        return HandoffActivityData.createWebHandoff(webUri)
    }
}

Получение и восстановление состояния в Google Books

Когда пользователь выбирает подсказку «Продолжить» на панели задач Google Books, система запускает целевой ComponentName в окне рабочего стола и добавляет дополнительные компоненты PersistableBundle к Intent запуска.

В Google Books при обработке входящего вызова учитывайте особенности оконного режима и многопанельной компоновки рабочего стола:

  1. Извлечение дополнительных данных при передаче: В методах onCreate и onNewIntent принимающей активности извлеките дополнительные данные из входящего Intent . Обработка onNewIntent гарантирует, что если ваша активность использует режим запуска singleTop или перенаправляет на существующее окно рабочего стола, окно обновится до переданного элемента.
  2. Адаптируйте состояние к многопанельным макетам: состояние, занимавшее полноэкранный режим просмотра подробной информации на телефоне, часто соответствует выбранному элементу внутри макета списка с подробной информацией или вспомогательной панели в Google Books. Заполните как основной выбор в списке, так и панель с подробной информацией, чтобы окно на настольном компьютере имело полный контекст.
  3. Сохранение восстановленного состояния при изменении размера окна: сохраните переданное состояние в ViewModel ( SavedStateHandle ) или rememberSaveable в Jetpack Compose, чтобы произвольное изменение размера окна в Google Books не приводило к сбросу восстановленной сессии.
import android.app.Activity
import android.content.Intent
import android.os.Bundle

class DocumentEditorReceiverActivity : Activity() {

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

        // Restore from the handoff intent only on initial launch so subsequent
        // desktop window configuration changes use saved instance state.
        if (savedInstanceState == null) {
            handleHandoffIntent(intent)
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent)
        handleHandoffIntent(intent)
    }

    private fun handleHandoffIntent(incomingIntent: Intent?) {
        val documentId = incomingIntent?.getStringExtra(EXTRA_DOCUMENT_ID)
            ?: return
        val scrollOffsetPx = incomingIntent.getIntExtra(EXTRA_SCROLL_OFFSET, 0)

        openDocumentInDesktopWorkspace(
            documentId = documentId,
            initialScrollOffsetPx = scrollOffsetPx
        )
    }

    private fun openDocumentInDesktopWorkspace(
        documentId: String,
        initialScrollOffsetPx: Int
    ) {
        // Load the document into the list-detail layout and restore scroll position.
    }

    companion object {
        const val EXTRA_DOCUMENT_ID = "extra_document_id"
        const val EXTRA_SCROLL_OFFSET = "extra_scroll_offset"
    }
}

Проверьте возможность переключения между телефоном и Google Books.

Для комплексной проверки вашей реализации:

  1. Подготовьте оба устройства.
    • Войдите в одну и ту же учетную запись Google как на своем телефоне Android (с Android 17 или выше), так и на GoogleBook (или на тестовом устройстве, работающем в оконном режиме, как на рабочем столе).
    • Включите Bluetooth и подключите оба устройства к одной и той же сети Wi-Fi.
    • На обоих устройствах откройте «Настройки» > «Подключенные устройства» > «Параметры подключения» > «Службы между устройствами» > «Продолжить активность» , следуйте инструкциям по настройке и включите «Задачи» . Полные требования к среде см. в разделе «Настройка и тестирование» .
  2. Установите приложение
    • Для переключения между приложениями установите свою сборку как на телефон, так и на Google Books.
    • Для резервного веб-доступа или прямой передачи данных в веб-браузер установите свою сборку на телефон и оставьте приложение удаленным в Google Books, чтобы убедиться, что браузер открывает ожидаемый URL-адрес.
  3. Инициировать передачу управления
    • На телефоне откройте приложение и перейдите к активности, которая включает функцию Handoff (вызовите setHandoffEnabled(true, null) для переключения между приложениями или передайте HandoffActivityParams с помощью setAllowHandoffWithoutPackageInstalled(true) при тестировании с приложением, удаленным на Google Books).
    • В приложении Google Books найдите значок вашего приложения со значком «Продолжить» в правой части панели задач и выберите его.
  4. Проверка восстановления рабочего стола
    • Убедитесь, что ваше приложение открывается в окне рабочего стола (или вкладке браузера) точно на том же элементе и в том же месте прокрутки, что и на телефоне.
    • Измените размер окна приложения в Google Books и убедитесь, что восстановленный контент и выделение сохраняются при изменении размера окна.

Дополнительные ресурсы

,

Пользователи часто начинают выполнение задач на своих телефонах Android — например, просматривают документы, сортируют сообщения или изучают различные элементы — а затем хотят перейти к GoogleBook с его большим дисплеем, физической клавиатурой и многооконным рабочим пространством.

Функция «Продолжить» в Android 17 (уровень API 37) и выше позволяет панели задач Google Books отображать значок приложения (так называемое предложение ) для активности, которую пользователь выполнял на ближайшем телефоне. Одним щелчком мыши пользователи могут продолжить свою активность в Google Books.

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

Выберите схему передачи управления.

Прежде чем включить функцию переключения между устройствами, определите, как должно открываться каждое действие в вашем мобильном приложении, когда пользователь выбирает предложение «Продолжить» в Google Books:

Процесс передачи управления Target на Googlebook Лучше всего подходит для Ключ API
Передача данных между приложениями Нативный Android-приложение, работающее в окне рабочего стола. Приложения, оптимизированные для больших экранов и оконного режима рабочего стола, доступны в Google Play. HandoffActivityData.Builder
Переключение между приложениями с резервным веб-интерфейсом. Если установлено нативное приложение Android, то в противном случае — URL-адрес в браузере по умолчанию на компьютере. Приложения, оптимизированные для работы в оконном режиме рабочего стола, но требующие надежного резервного варианта в браузере, если приложение не установлено на Google Books. setFallbackUri
Прямая передача данных в веб-браузер URL-адрес в браузере по умолчанию на компьютере (или перехваченный собственным приложением, если настроено использование ссылок в приложениях Android ). Рабочие процессы, в которых ваше веб-приложение является основным интерфейсом для настольных компьютеров. HandoffActivityData.createWebHandoff

Включить передачу управления для выполнения действия

Функция «Продолжить» по умолчанию отключена и настраивается для каждого действия. Выполните следующие действия для каждого действия отправки на телефоне:

  1. Вызовите setHandoffEnabled и передайте true после того, как активность загрузит состояние, необходимое для передачи управления. После включения система сможет запрашивать данные для передачи управления, пока активность находится на переднем плане или переходит в фоновый режим.
  2. Переопределите onHandoffActivityDataRequested , чтобы он возвращал ненулевой объект HandoffActivityData . Вы можете в любой момент запросить isHandoffEnabled , чтобы проверить, активна ли передача управления для данного действия.
import android.app.Activity
import android.app.HandoffActivityData
import android.app.HandoffActivityDataRequestInfo
import android.os.Bundle
import android.os.PersistableBundle

class DocumentEditorActivity : Activity() {

    private var documentId: String = "doc_42"
    private var scrollOffsetPx: Int = 0

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

        // Enable handoff once the activity is ready to transfer state.
        setHandoffEnabled(true, null)
    }

    override fun onHandoffActivityDataRequested(
        handoffRequestInfo: HandoffActivityDataRequestInfo
    ): HandoffActivityData {
        val extras = PersistableBundle().apply {
            putString(EXTRA_DOCUMENT_ID, documentId)
            putInt(EXTRA_SCROLL_OFFSET, scrollOffsetPx)
        }

        return HandoffActivityData.Builder(getComponentName())
            .setExtras(extras)
            .build()
    }

    companion object {
        const val EXTRA_DOCUMENT_ID = "extra_document_id"
        const val EXTRA_SCROLL_OFFSET = "extra_scroll_offset"
    }
}

Состояние активности пакета для передачи

Система вызывает onHandoffActivityDataRequested в двух сценариях:

  • Переключение на передний план: Действие находится на переднем плане телефона, и пользователь инициирует переключение с панели задач Google Books.
  • Захват состояния в фоновом режиме: действие на телефоне переходит в фоновый режим, и система кэширует данные, полученные при передаче управления, на случай, если пользователь позже выберет предложенный вариант в Google Books.

Проверьте, активен ли запрос на передачу управления.

Используйте isActiveRequest для проверки HandoffActivityDataRequestInfo , чтобы различать активную передачу данных, инициированную пользователем, и сохранение в фоновом режиме:

  • Если isActiveRequest возвращает true , это означает, что пользователь активно запросил продолжение работы на другом устройстве, пока активность видна.
  • Если isActiveRequest возвращает false , система кэширует состояние, поскольку активность прекращается.

Если вы отображаете на телефоне визуальный индикатор, подтверждающий перемещение задачи в Google Books, запланируйте асинхронное обновление пользовательского интерфейса, чтобы onHandoffActivityDataRequested возвращал значение без задержки.

Добавьте дополнительные государственные ресурсы и резервный веб-интерфейс.

В состав полезной нагрузки HandoffActivityData входит следующая информация:

  • Целевой компонент (необходим для передачи данных между приложениями): передайте this.getComponentName() ( ComponentName активности) или явно указанное ComponentName(this, TargetActivity::class.java) в HandoffActivityData.Builder , чтобы указать, какая активность запустится в GoogleBook.
  • Дополнительные параметры (необязательно): передайте объект PersistableBundle в функцию setExtras() , содержащий идентификаторы и координаты пользовательского интерфейса (например, идентификаторы открытых документов, активные клавиши Tab или позиции прокрутки). Размер объекта должен быть меньше 50 КБ.
  • Резервный URI (необязательно): передайте веб- Uri в функцию setFallbackUri , чтобы Googlebook мог открыть задачу в браузере по умолчанию, если ваше приложение для Android не установлено.
import android.app.Activity
import android.app.HandoffActivityData
import android.app.HandoffActivityDataRequestInfo
import android.app.HandoffActivityParams
import android.net.Uri
import android.os.Bundle
import android.os.PersistableBundle

class ArticleReaderActivity : Activity() {

    private var articleId: String = "android-desktop-windowing"
    private var readingProgressPercent: Int = 45

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

        setHandoffEnabled(
            true,
            HandoffActivityParams.Builder()
                .setAllowHandoffWithoutPackageInstalled(true)
                .build()
        )
    }

    override fun onHandoffActivityDataRequested(
        handoffRequestInfo: HandoffActivityDataRequestInfo
    ): HandoffActivityData {
        if (handoffRequestInfo.isActiveRequest()) {
            window.decorView.post {
                onHandoffStartedToSecondaryDevice()
            }
        }

        val extras = PersistableBundle().apply {
            putString(EXTRA_ARTICLE_ID, articleId)
            putInt(EXTRA_READING_PROGRESS, readingProgressPercent)
        }

        val fallbackWebUri = Uri.Builder()
            .scheme("https")
            .authority("example.com")
            .appendPath("articles")
            .appendPath(articleId)
            .appendQueryParameter("progress", readingProgressPercent.toString())
            .build()

        return HandoffActivityData.Builder(getComponentName())
            .setExtras(extras)
            .setFallbackUri(fallbackWebUri)
            .build()
    }

    private fun onHandoffStartedToSecondaryDevice() {
        // Save local drafts and update phone UI without blocking handoff.
    }

    companion object {
        const val EXTRA_ARTICLE_ID = "extra_article_id"
        const val EXTRA_READING_PROGRESS = "extra_reading_progress"
    }
}

Настройте прямую передачу данных в веб-интерфейс.

Если вы используете веб-приложение на настольном компьютере в Google Books, передайте HandoffActivityParams с setAllowHandoffWithoutPackageInstalled(true) в метод setHandoffEnabled и вызовите HandoffActivityData.createWebHandoff вместо использования HandoffActivityData.Builder :

import android.app.Activity
import android.app.HandoffActivityData
import android.app.HandoffActivityDataRequestInfo
import android.app.HandoffActivityParams
import android.net.Uri
import android.os.Bundle

class WebDashboardActivity : Activity() {

    private var projectId: String = "proj_901"

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

        setHandoffEnabled(
            true,
            HandoffActivityParams.Builder()
                .setAllowHandoffWithoutPackageInstalled(true)
                .build()
        )
    }

    override fun onHandoffActivityDataRequested(
        handoffRequestInfo: HandoffActivityDataRequestInfo
    ): HandoffActivityData {
        val webUri = Uri.Builder()
            .scheme("https")
            .authority("app.example.com")
            .appendPath("projects")
            .appendPath(projectId)
            .build()

        return HandoffActivityData.createWebHandoff(webUri)
    }
}

Получение и восстановление состояния в Google Books

Когда пользователь выбирает подсказку «Продолжить» на панели задач Google Books, система запускает целевой ComponentName в окне рабочего стола и добавляет дополнительные компоненты PersistableBundle к Intent запуска.

В Google Books при обработке входящего вызова учитывайте особенности оконного режима и многопанельной компоновки рабочего стола:

  1. Извлечение дополнительных данных при передаче: В методах onCreate и onNewIntent принимающей активности извлеките дополнительные данные из входящего Intent . Обработка onNewIntent гарантирует, что если ваша активность использует режим запуска singleTop или перенаправляет на существующее окно рабочего стола, окно обновится до переданного элемента.
  2. Адаптируйте состояние к многопанельным макетам: состояние, занимавшее полноэкранный режим просмотра подробной информации на телефоне, часто соответствует выбранному элементу внутри макета списка с подробной информацией или вспомогательной панели в Google Books. Заполните как основной выбор в списке, так и панель с подробной информацией, чтобы окно на настольном компьютере имело полный контекст.
  3. Сохранение восстановленного состояния при изменении размера окна: сохраните переданное состояние в ViewModel ( SavedStateHandle ) или rememberSaveable в Jetpack Compose, чтобы произвольное изменение размера окна в Google Books не приводило к сбросу восстановленной сессии.
import android.app.Activity
import android.content.Intent
import android.os.Bundle

class DocumentEditorReceiverActivity : Activity() {

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

        // Restore from the handoff intent only on initial launch so subsequent
        // desktop window configuration changes use saved instance state.
        if (savedInstanceState == null) {
            handleHandoffIntent(intent)
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent)
        handleHandoffIntent(intent)
    }

    private fun handleHandoffIntent(incomingIntent: Intent?) {
        val documentId = incomingIntent?.getStringExtra(EXTRA_DOCUMENT_ID)
            ?: return
        val scrollOffsetPx = incomingIntent.getIntExtra(EXTRA_SCROLL_OFFSET, 0)

        openDocumentInDesktopWorkspace(
            documentId = documentId,
            initialScrollOffsetPx = scrollOffsetPx
        )
    }

    private fun openDocumentInDesktopWorkspace(
        documentId: String,
        initialScrollOffsetPx: Int
    ) {
        // Load the document into the list-detail layout and restore scroll position.
    }

    companion object {
        const val EXTRA_DOCUMENT_ID = "extra_document_id"
        const val EXTRA_SCROLL_OFFSET = "extra_scroll_offset"
    }
}

Проверьте возможность переключения между телефоном и Google Books.

Для комплексной проверки вашей реализации:

  1. Подготовьте оба устройства.
    • Войдите в одну и ту же учетную запись Google как на своем телефоне Android (с Android 17 или выше), так и на GoogleBook (или на тестовом устройстве, работающем в оконном режиме, как на рабочем столе).
    • Включите Bluetooth и подключите оба устройства к одной и той же сети Wi-Fi.
    • На обоих устройствах откройте «Настройки» > «Подключенные устройства» > «Параметры подключения» > «Службы между устройствами» > «Продолжить активность» , следуйте инструкциям по настройке и включите «Задачи» . Полные требования к среде см. в разделе «Настройка и тестирование» .
  2. Установите приложение
    • Для переключения между приложениями установите свою сборку как на телефон, так и на Google Books.
    • Для резервного веб-доступа или прямой передачи данных в веб-браузер установите свою сборку на телефон и оставьте приложение удаленным в Google Books, чтобы убедиться, что браузер открывает ожидаемый URL-адрес.
  3. Инициировать передачу управления
    • На телефоне откройте приложение и перейдите к активности, которая включает функцию Handoff (вызовите setHandoffEnabled(true, null) для переключения между приложениями или передайте HandoffActivityParams с помощью setAllowHandoffWithoutPackageInstalled(true) при тестировании с приложением, удаленным на Google Books).
    • В приложении Google Books найдите значок вашего приложения со значком «Продолжить» в правой части панели задач и выберите его.
  4. Проверка восстановления рабочего стола
    • Убедитесь, что ваше приложение открывается в окне рабочего стола (или вкладке браузера) точно на том же элементе и в том же месте прокрутки, что и на телефоне.
    • Измените размер окна приложения в Google Books и убедитесь, что восстановленный контент и выделение сохраняются при изменении размера окна.

Дополнительные ресурсы

,

Пользователи часто начинают выполнение задач на своих телефонах Android — например, просматривают документы, сортируют сообщения или изучают различные элементы — а затем хотят перейти к GoogleBook с его большим дисплеем, физической клавиатурой и многооконным рабочим пространством.

Функция «Продолжить» в Android 17 (уровень API 37) и выше позволяет панели задач Google Books отображать значок приложения (так называемое предложение ) для активности, которую пользователь выполнял на ближайшем телефоне. Одним щелчком мыши пользователи могут продолжить свою активность в Google Books.

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

Выберите схему передачи управления.

Прежде чем включить функцию переключения между устройствами, определите, как должно открываться каждое действие в вашем мобильном приложении, когда пользователь выбирает предложение «Продолжить» в Google Books:

Процесс передачи управления Target на Googlebook Лучше всего подходит для Ключ API
Передача данных между приложениями Нативный Android-приложение, работающее в окне рабочего стола. Приложения, оптимизированные для больших экранов и оконного режима рабочего стола, доступны в Google Play. HandoffActivityData.Builder
Переключение между приложениями с резервным веб-интерфейсом. Если установлено нативное приложение Android, то в противном случае — URL-адрес в браузере по умолчанию на компьютере. Приложения, оптимизированные для работы в оконном режиме рабочего стола, но требующие надежного резервного варианта в браузере, если приложение не установлено на Google Books. setFallbackUri
Прямая передача данных в веб-браузер URL-адрес в браузере по умолчанию на компьютере (или перехваченный собственным приложением, если настроено использование ссылок в приложениях Android ). Рабочие процессы, в которых ваше веб-приложение является основным интерфейсом для настольных компьютеров. HandoffActivityData.createWebHandoff

Включить передачу управления для выполнения действия

Функция «Продолжить» по умолчанию отключена и настраивается для каждого действия. Выполните следующие действия для каждого действия отправки на телефоне:

  1. Вызовите setHandoffEnabled и передайте true после того, как активность загрузит состояние, необходимое для передачи управления. После включения система сможет запрашивать данные для передачи управления, пока активность находится на переднем плане или переходит в фоновый режим.
  2. Переопределите onHandoffActivityDataRequested , чтобы он возвращал ненулевой объект HandoffActivityData . Вы можете в любой момент запросить isHandoffEnabled , чтобы проверить, активна ли передача управления для данного действия.
import android.app.Activity
import android.app.HandoffActivityData
import android.app.HandoffActivityDataRequestInfo
import android.os.Bundle
import android.os.PersistableBundle

class DocumentEditorActivity : Activity() {

    private var documentId: String = "doc_42"
    private var scrollOffsetPx: Int = 0

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

        // Enable handoff once the activity is ready to transfer state.
        setHandoffEnabled(true, null)
    }

    override fun onHandoffActivityDataRequested(
        handoffRequestInfo: HandoffActivityDataRequestInfo
    ): HandoffActivityData {
        val extras = PersistableBundle().apply {
            putString(EXTRA_DOCUMENT_ID, documentId)
            putInt(EXTRA_SCROLL_OFFSET, scrollOffsetPx)
        }

        return HandoffActivityData.Builder(getComponentName())
            .setExtras(extras)
            .build()
    }

    companion object {
        const val EXTRA_DOCUMENT_ID = "extra_document_id"
        const val EXTRA_SCROLL_OFFSET = "extra_scroll_offset"
    }
}

Состояние активности пакета для передачи

Система вызывает onHandoffActivityDataRequested в двух сценариях:

  • Переключение на передний план: Действие находится на переднем плане телефона, и пользователь инициирует переключение с панели задач Google Books.
  • Захват состояния в фоновом режиме: действие на телефоне переходит в фоновый режим, и система кэширует данные, полученные при передаче управления, на случай, если пользователь позже выберет предложенный вариант в Google Books.

Проверьте, активен ли запрос на передачу управления.

Используйте isActiveRequest для проверки HandoffActivityDataRequestInfo , чтобы различать активную передачу данных, инициированную пользователем, и сохранение в фоновом режиме:

  • Если isActiveRequest возвращает true , это означает, что пользователь активно запросил продолжение работы на другом устройстве, пока активность видна.
  • Если isActiveRequest возвращает false , система кэширует состояние, поскольку активность прекращается.

Если вы отображаете на телефоне визуальный индикатор, подтверждающий перемещение задачи в Google Books, запланируйте асинхронное обновление пользовательского интерфейса, чтобы onHandoffActivityDataRequested возвращал значение без задержки.

Добавьте дополнительные государственные ресурсы и резервный веб-интерфейс.

В состав полезной нагрузки HandoffActivityData входит следующая информация:

  • Целевой компонент (необходим для передачи данных между приложениями): передайте this.getComponentName() ( ComponentName активности) или явно указанное ComponentName(this, TargetActivity::class.java) в HandoffActivityData.Builder , чтобы указать, какая активность запустится в GoogleBook.
  • Дополнительные параметры (необязательно): передайте объект PersistableBundle в функцию setExtras() , содержащий идентификаторы и координаты пользовательского интерфейса (например, идентификаторы открытых документов, активные клавиши Tab или позиции прокрутки). Размер объекта должен быть меньше 50 КБ.
  • Резервный URI (необязательно): передайте веб- Uri в функцию setFallbackUri , чтобы Googlebook мог открыть задачу в браузере по умолчанию, если ваше приложение для Android не установлено.
import android.app.Activity
import android.app.HandoffActivityData
import android.app.HandoffActivityDataRequestInfo
import android.app.HandoffActivityParams
import android.net.Uri
import android.os.Bundle
import android.os.PersistableBundle

class ArticleReaderActivity : Activity() {

    private var articleId: String = "android-desktop-windowing"
    private var readingProgressPercent: Int = 45

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

        setHandoffEnabled(
            true,
            HandoffActivityParams.Builder()
                .setAllowHandoffWithoutPackageInstalled(true)
                .build()
        )
    }

    override fun onHandoffActivityDataRequested(
        handoffRequestInfo: HandoffActivityDataRequestInfo
    ): HandoffActivityData {
        if (handoffRequestInfo.isActiveRequest()) {
            window.decorView.post {
                onHandoffStartedToSecondaryDevice()
            }
        }

        val extras = PersistableBundle().apply {
            putString(EXTRA_ARTICLE_ID, articleId)
            putInt(EXTRA_READING_PROGRESS, readingProgressPercent)
        }

        val fallbackWebUri = Uri.Builder()
            .scheme("https")
            .authority("example.com")
            .appendPath("articles")
            .appendPath(articleId)
            .appendQueryParameter("progress", readingProgressPercent.toString())
            .build()

        return HandoffActivityData.Builder(getComponentName())
            .setExtras(extras)
            .setFallbackUri(fallbackWebUri)
            .build()
    }

    private fun onHandoffStartedToSecondaryDevice() {
        // Save local drafts and update phone UI without blocking handoff.
    }

    companion object {
        const val EXTRA_ARTICLE_ID = "extra_article_id"
        const val EXTRA_READING_PROGRESS = "extra_reading_progress"
    }
}

Настройте прямую передачу данных в веб-интерфейс.

Если вы используете веб-приложение на настольном компьютере в Google Books, передайте HandoffActivityParams с setAllowHandoffWithoutPackageInstalled(true) в метод setHandoffEnabled и вызовите HandoffActivityData.createWebHandoff вместо использования HandoffActivityData.Builder :

import android.app.Activity
import android.app.HandoffActivityData
import android.app.HandoffActivityDataRequestInfo
import android.app.HandoffActivityParams
import android.net.Uri
import android.os.Bundle

class WebDashboardActivity : Activity() {

    private var projectId: String = "proj_901"

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

        setHandoffEnabled(
            true,
            HandoffActivityParams.Builder()
                .setAllowHandoffWithoutPackageInstalled(true)
                .build()
        )
    }

    override fun onHandoffActivityDataRequested(
        handoffRequestInfo: HandoffActivityDataRequestInfo
    ): HandoffActivityData {
        val webUri = Uri.Builder()
            .scheme("https")
            .authority("app.example.com")
            .appendPath("projects")
            .appendPath(projectId)
            .build()

        return HandoffActivityData.createWebHandoff(webUri)
    }
}

Получение и восстановление состояния в Google Books

Когда пользователь выбирает подсказку «Продолжить» на панели задач Google Books, система запускает целевой ComponentName в окне рабочего стола и добавляет дополнительные компоненты PersistableBundle к Intent запуска.

В Google Books при обработке входящего вызова учитывайте особенности оконного режима и многопанельной компоновки рабочего стола:

  1. Извлечение дополнительных данных при передаче: В методах onCreate и onNewIntent принимающей активности извлеките дополнительные данные из входящего Intent . Обработка onNewIntent гарантирует, что если ваша активность использует режим запуска singleTop или перенаправляет на существующее окно рабочего стола, окно обновится до переданного элемента.
  2. Адаптируйте состояние к многопанельным макетам: состояние, занимавшее полноэкранный режим просмотра подробной информации на телефоне, часто соответствует выбранному элементу внутри макета списка с подробной информацией или вспомогательной панели в Google Books. Заполните как основной выбор в списке, так и панель с подробной информацией, чтобы окно на настольном компьютере имело полный контекст.
  3. Сохранение восстановленного состояния при изменении размера окна: сохраните переданное состояние в ViewModel ( SavedStateHandle ) или rememberSaveable в Jetpack Compose, чтобы произвольное изменение размера окна в Google Books не приводило к сбросу восстановленной сессии.
import android.app.Activity
import android.content.Intent
import android.os.Bundle

class DocumentEditorReceiverActivity : Activity() {

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

        // Restore from the handoff intent only on initial launch so subsequent
        // desktop window configuration changes use saved instance state.
        if (savedInstanceState == null) {
            handleHandoffIntent(intent)
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent)
        handleHandoffIntent(intent)
    }

    private fun handleHandoffIntent(incomingIntent: Intent?) {
        val documentId = incomingIntent?.getStringExtra(EXTRA_DOCUMENT_ID)
            ?: return
        val scrollOffsetPx = incomingIntent.getIntExtra(EXTRA_SCROLL_OFFSET, 0)

        openDocumentInDesktopWorkspace(
            documentId = documentId,
            initialScrollOffsetPx = scrollOffsetPx
        )
    }

    private fun openDocumentInDesktopWorkspace(
        documentId: String,
        initialScrollOffsetPx: Int
    ) {
        // Load the document into the list-detail layout and restore scroll position.
    }

    companion object {
        const val EXTRA_DOCUMENT_ID = "extra_document_id"
        const val EXTRA_SCROLL_OFFSET = "extra_scroll_offset"
    }
}

Проверьте возможность переключения между телефоном и Google Books.

Для комплексной проверки вашей реализации:

  1. Подготовьте оба устройства.
    • Войдите в одну и ту же учетную запись Google как на своем телефоне Android (с Android 17 или выше), так и на GoogleBook (или на тестовом устройстве, работающем в оконном режиме, как на рабочем столе).
    • Включите Bluetooth и подключите оба устройства к одной и той же сети Wi-Fi.
    • На обоих устройствах откройте «Настройки» > «Подключенные устройства» > «Параметры подключения» > «Службы между устройствами» > «Продолжить активность» , следуйте инструкциям по настройке и включите «Задачи» . Полные требования к среде см. в разделе «Настройка и тестирование» .
  2. Установите приложение
    • Для переключения между приложениями установите свою сборку как на телефон, так и на Google Books.
    • Для резервного веб-доступа или прямой передачи данных в веб-браузер установите свою сборку на телефон и оставьте приложение удаленным в Google Books, чтобы убедиться, что браузер открывает ожидаемый URL-адрес.
  3. Инициировать передачу управления
    • На телефоне откройте приложение и перейдите к активности, которая включает функцию Handoff (вызовите setHandoffEnabled(true, null) для переключения между приложениями или передайте HandoffActivityParams с помощью setAllowHandoffWithoutPackageInstalled(true) при тестировании с приложением, удаленным на Google Books).
    • В приложении Google Books найдите значок вашего приложения со значком «Продолжить» в правой части панели задач и выберите его.
  4. Проверка восстановления рабочего стола
    • Убедитесь, что ваше приложение открывается в окне рабочего стола (или вкладке браузера) точно на том же элементе и в том же месте прокрутки, что и на телефоне.
    • Измените размер окна приложения в Google Books и убедитесь, что восстановленный контент и выделение сохраняются при изменении размера окна.

Дополнительные ресурсы