blob: b45766c169a18d3bc8b69a8105667409742de3e5 [file] [log] [blame]
page.title=Поддержка многооконного режима
page.metaDescription=Новые возможности в Android N для одновременного отображения нескольких приложений.
page.keywords="multi-window", "android N", "split screen", "free-form"
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Содержание документа</h2>
<ol>
<li><a href="#overview">Обзор</a></li>
<li><a href="#lifecycle">Жизненный цикл многооконного режима</a></li>
<li><a href="#configuring">Настройка приложения для многооконного
режима</a></li>
<li><a href="#running">Запуск приложения в многооконном режиме</a></li>
<li><a href="#testing">Тестирование приложения в многооконном режиме</a></li>
</ol>
<h2>См. также:</h2>
<ol>
<li><a class="external-link" href="https://github.com/googlesamples/android-MultiWindowPlayground">Пример
многооконного демонстрационного приложения</a></li>
</ol>
</div>
</div>
<p>
В Android N добавлена поддержка отображения нескольких приложений
одновременно. На мобильных устройствах два приложения могут быть запущены рядом
или друг над другом в режиме <em>разделения экрана</em>. На телевизорах приложения могут
использовать режим <em>"картинка в картинке"</em>, чтобы воспроизводить видео,
пока пользователи работают с другим приложением.
</p>
<p>
Если вы создаете приложение с использованием N Preview SDK, вы можете указать, как оно
будет действовать в многооконном режиме. Например, можно задать минимальные
допустимые размеры окна приложения. Также можно отключить многооконный режим для приложения,
чтобы оно отображалось только в полноэкранном
режиме.
</p>
<h2 id="overview">Обзор</h2>
<p>
В Android N несколько приложений могут одновременно находиться на экране. Например,
пользователь может разделить экран, чтобы просматривать веб-страницу
слева и писать сообщение электронной почты справа. Возможности пользователя зависят от
устройства.
</p>
<ul>
<li>На мобильных устройствах с Android N доступен режим
разделения экрана. В этом режиме два приложения отображаются рядом
или друг над другом. Пользователь может перетащить
линию разделения, чтобы увеличить окно одного приложения и уменьшить окно другого.
</li>
<li>На устройствах Nexus Player с Android N для приложений
будет доступен <a href="picture-in-picture.html">режим "картинка в картинке"</a>, который
позволит приложению отображать контент, пока пользователь просматривает
другие приложения или взаимодействует с ними.
</li>
<li>Производители более крупных устройств могут активировать
режим произвольной формы, где пользователь может любым образом изменять размер каждого окна. В этом случае
помимо режима разделения экрана
на устройстве будет доступен и этот режим.
</li>
</ul>
<img src="{@docRoot}preview/images/mw-splitscreen.png" alt="" width="650" srcset="{@docRoot}preview/images/mw-splitscreen.png 1x,
{@docRoot}preview/images/mw-splitscreen_2x.png 2x," id="img-split-screen" />
<p class="img-caption">
<strong>Рис. 1.</strong> Два приложения отображаются рядом в режиме разделения экрана.
</p>
<p>
Пользователь может перейти в многооконный режим следующими способами.
</p>
<ul>
<li>Если пользователь откроет <a href="{@docRoot}guide/components/recents.html">экран
обзора</a> и длительно нажмет
название операции, ее можно будет перетащить в выделенную часть
экрана и переключить в многооконный режим.
</li>
<li>Если пользователь длительно нажмет кнопку "Обзор", устройство
переключит текущую операцию в многооконный режим и откроет экран обзора,
где пользователь сможет выбрать другую операцию для совместного отображения.
</li>
</ul>
<p>
Пользователи могут <a href="{@docRoot}guide/topics/ui/drag-drop.html">перетаскивать</a>
данные между окнами операций в режиме
совместного отображения. (Ранее перетаскивать данные можно было только в рамках
одной операции).
</p>
<h2 id="lifecycle">Жизненный цикл многооконного режима</h2>
<p>
Многооконный режим не меняет <a href="{@docRoot}training/basics/activity-lifecycle/index.html">жизненный
цикл операции</a>.
</p>
<p>
В этом режиме в каждый момент времени активной
является только последняя операция, с которой взаимодействовал пользователь. Такая операция считается <em>самой верхней</em>.
Все другие операции приостановлены, даже если они отображаются.
Однако система отдает приостановленным, но видимым операциям более
высокий приоритет, чем невидимым. Если пользователь взаимодействует с
одной из приостановленных операций, она возобновляется, а прежняя самая верхняя
операция приостанавливается.
</p>
<p class="note">
<strong>Примечание.</strong> В многооконном режиме приложение может быть приостановлено
и по-прежнему видимо для пользователя. Приложению может потребоваться
продолжать свои операции, даже если оно приостановлено. Например, видимое приостановленное приложение,
воспроизводящее видео, будет по-прежнему показывать видео. Поэтому
мы <em>не</em> рекомендуем приостанавливать воспроизведение
в обработчиках {@link android.app.Activity#onPause onPause()} таких приложений.
Вместо этого следует приостановить видео в {@link android.app.Activity#onStop
onStop()} и возобновить воспроизведение в {@link android.app.Activity#onStart
onStart()}.
</p>
<p>
Если пользователь переводит приложение в многооконный режим, система
уведомляет операцию об изменении конфигурации, как указано в документе <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Обработка изменений
во время выполнения</a>. По сути это изменение так же действует
на жизненный цикл операции, как уведомление приложения системой
о переходе устройства из вертикальной ориентации в
горизонтальную, только изменяются размеры экрана, а не ориентация. Как описано в документе <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Обработка изменений
во время выполнения</a>, операция может обработать изменение
конфигурации самостоятельно или может позволить системе
удалить окно операции и создать его заново с новыми размерами.
</p>
<p>
Если пользователь увеличивает одну из сторон окна, система меняет
размер окна операции в соответствии с действием пользователя и применяет <a href="{@docRoot}guide/topics/resources/runtime-changes.html">изменения в режиме выполнения</a>
по мере необходимости. Если приложение не успевает отрисовать новые области, система
временно заполняет их цветом, заданным атрибутом {@link
android.R.attr#windowBackground windowBackground} или атрибутом стиля
<code>windowBackgroundFallback</code> по умолчанию.
</p>
<h2 id="configuring">Настройка приложения для многооконного режима</h2>
<p>
Если ваше приложение предназначено для Android N, вы
можете указать, каким образом поддерживают поддерживают ли) операции вашего приложения многооконный режим. Атрибуты управления размером и макетом устанавливаются
в манифесте.
Настройки атрибутов корневой операции применяются
ко всем операциям в ее стеке задач.
</p>
<p class="note">
<strong>Примечание.</strong> Если приложение с поддержкой различной
ориентации было создано с версией SDK,
более ранней, чем Android N, и пользователь запустит это приложение в многооконном режиме, система принудительно изменит размер приложения. Система отображает диалоговое окно
с предупреждением о том, что приложение может работать непредвиденным образом. Система
<em>не</em> меняет размер окна для приложений с
фиксированной ориентацией. Если пользователь попытается открыть такое приложение
в многооконном режиме, оно займет весь экран.
</p>
<h4 id="resizeableActivity">android:resizeableActivity</h4>
<p>
Установите этот атрибут в узле <code>&lt;activity&gt;</code> или
<code>&lt;application&gt;</code> манифеста, чтобы включить или отключить многооконный
режим:
</p>
<pre>
android:resizeableActivity=["true" | "false"]
</pre>
<p>
Если для этого атрибута задано значение true, операцию можно запускать
в режимах разделения экрана и произвольной формы. Если для атрибута задано значение false,
операция не поддерживает многооконный режим. Если значение равно false и
пользователь пытается запустить операцию в многооконном режиме, она
занимает весь экран.
</p>
<p>
Если приложение предназначено для Android N, но
значение для этого атрибута не было указано, то по умолчанию используется значение true.
</p>
<h4 id="supportsPictureInPicture">android:supportsPictureInPicture</h4>
<p>
Установите этот атрибут в узле <code>&lt;activity&gt;</code> манифеста,
чтобы указать, поддерживает ли операция режим "картинка в картинке". Этот
атрибут не принимается во внимание, если для <code>android:resizeableActivity</code> установлено значение false.
</p>
<pre>
android:supportsPictureInPicture=["true" | "false"]
</pre>
<h3 id="layout">Атрибуты макета</h3>
<p>
В Android N элемент манифеста <code>&lt;layout&gt;</code> поддерживает
несколько атрибутов, которые определяют поведение
операции в многооконном режиме.
</p>
<dl>
<dt>
<code>android:defaultWidth</code>
</dt>
<dd>
Ширина окна операции по умолчанию в режиме произвольной формы.
</dd>
<dt>
<code>android:defaultHeight</code>
</dt>
<dd>
Высота окна операции по умолчанию в режиме произвольной формы.
</dd>
<dt>
<code>android:gravity</code>
</dt>
<dd>
Начальная позиция окна операции в режиме произвольной формы. Допустимые значения
см. в описании класса {@link android.view.Gravity}.
</dd>
<dt>
<code>android:minimalSize</code>
</dt>
<dd>
Минимальные значения высоты и ширины окна операции в режимах разделения экрана
и произвольной формы. Если пользователь перемещает разделительную линию
в режиме разделения экрана, чтобы сделать размер окна операции
меньше указанного минимума, система обрезает его до запрошенного пользователем размера.
</dd>
</dl>
<p>
В следующем примере кода показано, как задать размер и
позицию окна операции по умолчанию, а также ее минимальный размер в
режиме произвольной формы:
</p>
<pre>
&lt;activity android:name=".MyActivity"&gt;
&lt;layout android:defaultHeight="500dp"
android:defaultWidth="600dp"
android:gravity="top|end"
android:minimalSize="450dp" /&gt;
&lt;/activity&gt;
</pre>
<h2 id="running">Запуск приложения в многооконном режиме</h2>
<p>
Android N предоставляет новые возможности для поддержки
приложений в многооконном режиме.
</p>
<h3 id="disabled-features">Недоступные возможности в многооконном режиме</h3>
<p>
Некоторые возможности отключены или игнорируются в многооконном
режиме, потому что они не имеют смысла для операции, которая отображается
на экране устройства одновременно с другими операциями или приложениями. Ниже приведены примеры таких возможностей.
<ul>
<li>Отключены некоторые параметры настройки <a href="{@docRoot}training/system-ui/index.html">системного интерфейса</a>.
Например, приложения не могут
скрыть строку состояния, если они не работают в полноэкранном режиме.
</li>
<li>Система не учитывает изменения атрибута <code><a href=
"{@docRoot}guide/topics/manifest/activity-element.html#screen"
>android:screenOrientation</a></code>.
</li>
</ul>
<h3 id="change-notification">Уведомления об изменениях и запросы в многооконном режиме</h3>
<p>
Для поддержки многооконного режима в класс {@link android.app.Activity}
были добавлены следующие методы. Подробнее о каждом из них см. в
<a href="{@docRoot}preview/setup-sdk.html#docs-dl">справочнике по N Preview SDK</a>.
</p>
<dl>
<dt>
<code>Activity.inMultiWindow()</code>
</dt>
<dd>
Вызовите этот метод, чтобы узнать, находится ли операция в многооконном режиме.
</dd>
<dt>
<code>Activity.inPictureInPicture()</code>
</dt>
<dd>
Вызовите этот метод, чтобы узнать, находится ли операция в режиме "картинка в картинке".
<p class="note">
<strong>Примечание.</strong> Режим "картинка в картинке" это частный
случай многооконного режима. Если метод <code>myActivity.inPictureInPicture()</code>
возвращает значение true, <code>myActivity.inMultiWindow()</code> также возвращает
true.
</p>
</dd>
<dt>
<code>Activity.onMultiWindowChanged()</code>
</dt>
<dd>
Система вызывает этот метод, когда операция переходит в многооконный
режим или выходит из него. Система передает методу значение true, если
операция входит в многооконный режим, и значение false, если
она выходит из него.
</dd>
<dt>
<code>Activity.onPictureInPictureChanged()</code>
</dt>
<dd>
Система вызывает этот метод, когда операция переходит в режим
"картинка в картинке". Система передает методу значение true,
если операция входит в режим "картинка в картинке", и значение false,
если она выходит из него.
</dd>
</dl>
<p>
Также существуют версии {@link android.app.Fragment} для этих методов,
например, <code>Fragment.inMultiWindow()</code>.
</p>
<h3 id="entering-pip">Переход в режим "картинка в картинке"</h3>
<p>
Чтобы перевести операцию в режим "картинка в картинке",
вызовите новый метод <code>Activity.enterPictureInPicture()</code>. Этот метод игнорируется, если
устройство не поддерживает режим "картинка в картинке". Дополнительная информация содержится в документации
<a href="picture-in-picture.html">Режим "картинка в картинке"</a>.
</p>
<h3 id="launch">Запуск новых операций в многооконном режиме</h3>
<p>
При запуске новой операции можно сообщить системе, что окно новой
операции следует показать рядом с текущим, если это возможно. Для этого
используйте флаг
<code>Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT</code>. Этот
флаг запрашивает следующее поведение.
</p>
<ul>
<li>Если устройство находится в режиме разделения экрана, система пытается
создать окно новой операции рядом с окном запустившей ее операции,
чтобы разместить две операции на экране. Не гарантируется, что система сможет это сделать, но если
это возможно, операции отображаются рядом друг с другом.
</li>
<li>Если устройство не находится в режиме разделения экрана, этот флаг не учитывается.
</li>
</ul>
<p>
Если при запуске
новой операции устройство находится в режиме произвольной формы, вы можете задать размеры и позицию окна новой операции,
вызвав метод <code>ActivityOptions.setLaunchBounds()</code>. Этот метод игнорируется, если
устройство не находится в многооконном режиме.
</p>
<p class="note">
<strong>Примечание.</strong> Если запустить операцию в стеке задач,
она заменит операцию на экране, унаследовав все ее
свойства многооконного режима. Чтобы запустить новую операцию в отдельном
окне в многооконном режиме, ее следует запустить в новом стеке задач.
</p>
<h3 id="dnd">Поддержка перетаскивания</h3>
<p>
Пользователи могут <a href="{@docRoot}guide/topics/ui/drag-drop.html">перетаскивать</a> данные
между окнами операций в режиме
совместного отображения. (Ранее перетаскивать данные можно было только в рамках
одной операции). Поэтому вы можете реализовать функции перетаскивания
в своем приложении, если оно еще их не поддерживает.
</p>
<p>
В N Preview SDK пакет <a href="{@docRoot}reference/android/view/package-summary.html"><code>android.view</code></a>
расширен для поддержки перетаскивания между приложениями. Дополнительная информация о нижеприведенных классах
и методах содержится в <a href="{@docRoot}preview/setup-sdk.html#docs-dl">справочнике по N
Preview SDK</a>.
</p>
<dl>
<dt>
<code>android.view.DropPermissions</code>
</dt>
<dd>
Объект токена для указания разрешений
приложению, в которое перетаскиваются данные.
</dd>
<dt>
<code>View.startDragAndDrop()</code>
</dt>
<dd>
Новый псевдоним для {@link android.view.View#startDrag View.startDrag()}. Чтобы
разрешить перетаскивание между операциями, передайте
новый флаг <code>View.DRAG_FLAG_GLOBAL</code>. Если вам нужно предоставить принимающей операции разрешения на чтение или запись URI,
передайте новый флаг
<code>View.DRAG_FLAG_GLOBAL_URI_READ</code> или
<code>View.DRAG_FLAG_GLOBAL_URI_WRITE</code> соответственно.
</dd>
<dt>
<code>View.cancelDragAndDrop()</code>
</dt>
<dd>
Отменяет текущую операцию перетаскивания. Этот метод может вызвать только
приложение, в котором была инициирована операция перетаскивания.
</dd>
<dt>
<code>View.updateDragShadow()</code>
</dt>
<dd>
Заменяет тень текущей операции перетаскивания. Этот метод может вызвать только приложение,
в котором была инициирована операция перетаскивания.
</dd>
<dt>
<code>Activity.requestDropPermissions()</code>
</dt>
<dd>
Запрашивает разрешения для URI контента, переданных в объекте {@link
android.content.ClipData} в {@link android.view.DragEvent}.
</dd>
</dl>
<h2 id="testing">Тестирование приложения в многооконном режиме</h2>
<p>
Независимо от того, обновляете ли вы свое приложение для Android N, вам необходимо
подтвердить его поведение в многооконном
режиме на тот случай, если пользователь попытается запустить его в этом режиме на устройстве с Android N.
</p>
<h3 id="configuring">Настройка тестового устройства</h3>
<p>
Если установить Android N на устройстве, режим разделения
экрана будет поддерживаться автоматически.
</p>
<h3 id="test-non-n">Если приложение было создано без использования N Preview SDK</h3>
<p>
Если вы не применяли N Preview SDK для создания приложения и пользователь
попытается запустить его в многооконном режиме, система принудительно
изменит размер окна приложения, если его ориентация не зафиксирована.
</p>
<p>
Если для приложения не задана фиксированная ориентация, вам
следует запустить его на устройстве с Android N и попытаться
перевести его в режим разделения экрана. Убедитесь, что приложение
работает нормально после принудительного изменения размера.
</p>
<p>
Если для приложения задана фиксированная ориентация, попытайтесь
перевести его в многооконный режим. Убедитесь, что при этом
приложение остается в полноэкранном режиме.
</p>
<h3 id="test-mw">Если приложение поддерживает многооконный режим</h3>
<p>
Если вы использовали N Preview SDK для создания приложения и не
отключили поддержку многооконного режима, проверьте работу
приложения, как описано далее, в режимах разделения экрана и произвольной формы.
</p>
<ul>
<li>Запустите приложение в полноэкранном режиме, а затем переключитесь
в многооконный режим долгим нажатием кнопки "Обзор". Убедитесь, что приложение корректно переключается между режимами.
</li>
<li>Запустите приложение непосредственно в многооконном режиме
и убедитесь, что оно работает нормально. Вы можете запустить приложение в многооконном режиме, нажав
кнопку "Обзор", затем длительно нажав строку заголовка приложения и
перетащив ее в одну из выделенных областей на экране.
</li>
<li>Измените размер окна приложения в режиме разделения экрана, перетащив линию разделения.
Убедитесь, что изменение размера не приводит к сбою и что необходимые
элементы интерфейса остаются видимыми.
</li>
<li>Если вы указали минимальные размеры окна приложения, попытайтесь
установить размер меньше минимального. Убедитесь в невозможности установить размер
меньше указанного минимума.
</li>
<li>Во время всех тестов следите за производительностью приложения — она должна быть приемлемой. Например,
убедитесь, что после изменения размера окна приложения не возникает большой
задержки обновления интерфейса.
</li>
</ul>
<h4 id="test-checklist">Контрольный список тестирования</h4>
<p>
Для проверки производительности приложения в многооконном режиме
выполните следующие операции. Попытайтесь выполнить их в режиме разделения экрана и
в многооконном режиме, если не указано иное.
</p>
<ul>
<li>Перейдите в многооконный режим и выйдите из него.
</li>
<li>Переключитесь из своего приложения в другое приложение и убедитесь,
что приложение работает нормально, если оно видимо, но не активно. Например, если приложение
показывает видео, оно должно продолжать воспроизведение, когда
пользователь работает с другим приложением.
</li>
<li>В режиме разделения экрана попробуйте перемещать линию
разделения, увеличивая и уменьшая окно приложения. Попробуйте выполнить эти операции, когда окна двух
приложений находятся рядом и друг над другом. Убедитесь, что приложение не завершается с ошибкой,
необходимые элементы видны и изменение размера не занимает
слишком много времени.
</li>
<li>Быстро измените размер окна приложения несколько раз подряд. Убедитесь, что
приложение не зависает и не вызывает утечку памяти. Информация о проверке использования памяти
приложением содержится в документе <a href="{@docRoot}tools/debugging/debugging-memory.html">
Анализ использования оперативной памяти</a>.
</li>
<li>Поработайте с приложением в различных оконных конфигурациях и
убедитесь, что оно ведет себя должным образом. Текст должен легко читаться, а
элементы интерфейса не должны быть слишком маленькими.
</li>
</ul>
<h3 id="test-disabled-mw">Если вы отключили поддержку многооконного режима</h3>
<p>
Если вы отключили поддержку многооконного режима,
установив атрибут <code>android:resizableActivity="false"</code>, запустите
приложение на устройстве с Android N и
попытайтесь перевести его в режимы произвольной формы и разделения экрана. Убедитесь, что при этом
приложение остается в полноэкранном режиме.
</p>