"Multi-Window Support" page. Bug: 31750518 Change-Id: Ib23093a88a7c5df13cce04e6b2ea55f2d8547910
607 lines
21 KiB
Plaintext
607 lines
21 KiB
Plaintext
page.title=Multi-Window Support
|
||
page.metaDescription=New support in Android N for showing more than one app at a time.
|
||
page.keywords="multi-window", "android N", "split screen", "free-form"
|
||
|
||
@jd:body
|
||
|
||
<div id="qv-wrapper">
|
||
<div id="qv">
|
||
<h2>In this document</h2>
|
||
<ol>
|
||
<li><a href="#overview">Overview</a></li>
|
||
<li><a href="#lifecycle">Multi-Window Lifecycle</a></li>
|
||
<li><a href="#configuring">Configuring Your App for Multi-Window
|
||
Mode</a></li>
|
||
<li><a href="#running">Running Your App in Multi-Window Mode</a></li>
|
||
<li><a href="#testing">Testing Your App's Multi-Window Support</a></li>
|
||
</ol>
|
||
<h2>See Also</h2>
|
||
<ol>
|
||
<li><a href="{@docRoot}training/tv/playback/picture-in-picture.html">Adding
|
||
Picture-in-Picture</a></li>
|
||
<li><a class="external-link"
|
||
href="https://github.com/googlesamples/android-MultiWindowPlayground">Multi-Window
|
||
Playground sample app</a></li>
|
||
<li><a class="external-link"
|
||
href="https://medium.com/google-developers/5-tips-for-preparing-for-multi-window-in-android-n-7bed803dda64"
|
||
>Five Tips for Preparing for Multi-Window in Android N</a></li>
|
||
</ol>
|
||
</div>
|
||
</div>
|
||
|
||
<p>
|
||
Android 7.0 adds support for displaying more than one app at the
|
||
same time. On handheld devices, two apps can run side-by-side or
|
||
one-above-the-other in <em>split-screen</em> mode. On TV devices, apps can
|
||
use <em>picture-in-picture</em> mode to continue video playback while users
|
||
are interacting with another app.
|
||
</p>
|
||
|
||
<p>
|
||
If your app targets Android 7.0 (API level 24) or higher, you can configure how your app
|
||
handles multi-window display. For example, you can specify your activity's
|
||
minimum allowable dimensions. You can also disable multi-window display for
|
||
your app, ensuring that the system only shows your app in full-screen
|
||
mode.
|
||
</p>
|
||
|
||
<h2 id="overview">Overview</h2>
|
||
|
||
<p>
|
||
Android 7.0 allows several apps to share the screen at once. For
|
||
example, a user could split the screen, viewing a web page on the left side
|
||
while composing an email on the right side. The user experience depends on
|
||
the device:
|
||
</p>
|
||
|
||
<ul>
|
||
<li>Handheld devices running Android 7.0 offer split-screen
|
||
mode. In this mode, the system fills the screen with two apps, showing them
|
||
either side-by-side or one-above-the-other. The user can drag the dividing
|
||
line separating the two to make one app larger and the other smaller.
|
||
</li>
|
||
|
||
<li>On TV devices, apps can put themselves
|
||
in <a href="picture-in-picture.html">picture-in-picture mode</a>, allowing
|
||
them to continue showing content while the user browses or interacts with
|
||
other apps.
|
||
</li>
|
||
|
||
<li>Manufacturers of larger devices can choose to enable freeform
|
||
mode, in which the user can freely resize each activity. If the
|
||
manufacturer enables this feature, the device offers freeform mode in addition
|
||
to split-screen mode.
|
||
</li>
|
||
</ul>
|
||
|
||
<img src="{@docRoot}images/android-7.0/mw-splitscreen.png" alt="" width="650"
|
||
srcset="{@docRoot}images/android-7.0/mw-splitscreen.png 1x,
|
||
{@docRoot}images/android-7.0/mw-splitscreen_2x.png 2x,"
|
||
id="img-split-screen" />
|
||
<p class="img-caption">
|
||
<strong>Figure 1.</strong> Two apps running side-by-side in split-screen mode.
|
||
</p>
|
||
|
||
<p>
|
||
The user can switch into multi-window mode in the following ways:
|
||
</p>
|
||
|
||
<ul>
|
||
<li>If the user opens the <a href="{@docRoot}guide/components/recents.html">Overview
|
||
screen</a> and performs a long press on an
|
||
activity title, they can drag that activity to a highlighted portion of the
|
||
screen to put the activity in multi-window mode.
|
||
</li>
|
||
|
||
<li>If the user performs a long press on the Overview button, the device puts
|
||
the current activity in multi-window mode, and opens the Overview screen to
|
||
let the user choose another activity to share the screen.
|
||
</li>
|
||
</ul>
|
||
|
||
<p>
|
||
Users can <a href="{@docRoot}guide/topics/ui/drag-drop.html">drag and
|
||
drop</a> data from one activity to another while the activities are sharing
|
||
the screen.
|
||
|
||
<h2 id="lifecycle">Multi-Window Lifecycle</h2>
|
||
|
||
<p>
|
||
Multi-window mode does not change the <a href=
|
||
"{@docRoot}training/basics/activity-lifecycle/index.html">activity
|
||
lifecycle</a>.
|
||
</p>
|
||
|
||
<p>
|
||
In multi-window mode, only the activity the user has most recently interacted
|
||
with is active at a given time. This activity is considered <em>topmost</em>.
|
||
All other activities are in the paused state, even if they are visible.
|
||
However, the system gives these paused-but-visible activities higher priority
|
||
than activities that are not visible. If the user interacts with one of the
|
||
paused activities, that activity is resumed, and the previously topmost
|
||
activity is paused.
|
||
</p>
|
||
|
||
<p class="note">
|
||
<strong>Note:</strong> In multi-window mode, an app can be in the paused
|
||
state and still be visible to the user. An app might need to continue its
|
||
activities even while paused. For example, a video-playing app that is in
|
||
paused mode but is visible should continue showing its video. For this
|
||
reason, we recommend that activities that play video <em>not</em> pause the
|
||
video in their {@link android.app.Activity#onPause onPause()} handlers.
|
||
Instead, they should pause video in {@link android.app.Activity#onStop
|
||
onStop()}, and resume playback in {@link android.app.Activity#onStart
|
||
onStart()}.
|
||
</p>
|
||
|
||
<p>
|
||
When the user puts an app into multi-window mode, the system notifies the
|
||
activity of a configuration change, as specified in <a href=
|
||
"{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime
|
||
Changes</a>. This also happens when the user resizes the app, or puts the app
|
||
back into full-screen mode.
|
||
Essentially, this change has the same activity-lifecycle
|
||
implications as when the system notifies the app that the device has switched
|
||
from portrait to landscape mode, except that the device dimensions are
|
||
changed instead of just being swapped. As discussed in <a href=
|
||
"{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime
|
||
Changes</a>, your activity can handle the configuration change itself, or it
|
||
can allow the system to destroy the activity and recreate it with the new
|
||
dimensions.
|
||
</p>
|
||
|
||
<p>
|
||
If the user is resizing a window and makes it larger in either dimension, the
|
||
system resizes the activity to match the user action and issues <a href=
|
||
"{@docRoot}guide/topics/resources/runtime-changes.html">runtime changes</a>
|
||
as needed. If the app lags behind in drawing in newly-exposed areas, the
|
||
system temporarily fills those areas with the color specified by the {@link
|
||
android.R.attr#windowBackground windowBackground} attribute or by the default
|
||
<code>windowBackgroundFallback</code> style attribute.
|
||
</p>
|
||
|
||
<h2 id="configuring">Configuring Your App for Multi-Window Mode</h2>
|
||
|
||
<p>
|
||
If your app targets API level 24 or higher, you can configure how and
|
||
whether your app's activities support multi-window display. You can set
|
||
attributes in your manifest to control both size and layout.
|
||
A root activity's attribute settings apply to all activities
|
||
within its task stack. For example, if the root activity has
|
||
<code>android:resizeableActivity</code> set to true, then all activities
|
||
in the task stack are resizable.
|
||
</p>
|
||
|
||
<p class="note">
|
||
<strong>Note:</strong> If you build a multi-orientation app that targets API
|
||
level 23 or lower, and the user uses the app in
|
||
multi-window mode, the system forcibly resizes the app. The system presents a
|
||
dialog box warning the user that the app may behave unexpectedly. The system
|
||
does <em>not</em> resize fixed-orientation apps; if
|
||
the user attempts to open a fixed-orientation app under multi-window mode,
|
||
the app takes over the whole screen.
|
||
</p>
|
||
|
||
<h4 id="resizeableActivity">android:resizeableActivity</h4>
|
||
|
||
<p>
|
||
Set this attribute in your manifest's <a href=
|
||
"{@docRoot}guide/topics/manifest/activity-element"><code><activity></code></a>
|
||
or <a href=
|
||
"{@docRoot}guide/topics/manifest/application-element"><code><application></code></a>
|
||
element to enable or disable multi-window display:
|
||
</p>
|
||
|
||
<pre>
|
||
android:resizeableActivity=["true" | "false"]
|
||
</pre>
|
||
|
||
<p>
|
||
If this attribute is set to true, the activity can be launched in
|
||
split-screen and freeform modes. If the attribute is set to false, the
|
||
activity does not support multi-window mode. If this value is false, and the
|
||
user attempts to launch the activity in multi-window mode, the activity takes
|
||
over the full screen.
|
||
</p>
|
||
|
||
<p>
|
||
If your app targets API level 24, but you do not specify a value
|
||
for this attribute, the attribute's value defaults to true.
|
||
</p>
|
||
|
||
<h4 id="supportsPictureInPicture">android:supportsPictureInPicture</h4>
|
||
|
||
<p>
|
||
Set this attribute in your manifest's <a href=
|
||
"{@docRoot}guide/topics/manifest/activity-element"><code><activity></code></a>
|
||
node to indicate whether the activity supports <a href=
|
||
"{@docRoot}training/tv/playback/picture-in-picture.html">Picture-in-Picture</a>
|
||
display. This attribute is ignored if <code>android:resizeableActivity</code>
|
||
is false.
|
||
</p>
|
||
|
||
<pre>
|
||
android:supportsPictureInPicture=["true" | "false"]
|
||
</pre>
|
||
|
||
<h3 id="layout">Layout attributes</h3>
|
||
|
||
<p>
|
||
With Android 7.0, the <code><layout></code> manifest element
|
||
supports several attributes that affect how an activity behaves in
|
||
multi-window mode:
|
||
</p>
|
||
|
||
<dl>
|
||
<dt>
|
||
<code>android:defaultWidth</code>
|
||
</dt>
|
||
|
||
<dd>
|
||
Default width of the activity when launched in freeform mode.
|
||
</dd>
|
||
|
||
<dt>
|
||
<code>android:defaultHeight</code>
|
||
</dt>
|
||
|
||
<dd>
|
||
Default height of the activity when launched in freeform mode.
|
||
</dd>
|
||
|
||
<dt>
|
||
<code>android:gravity</code>
|
||
</dt>
|
||
|
||
<dd>
|
||
Initial placement of the activity when launched in freeform mode. See the
|
||
{@link android.view.Gravity} reference for suitable values.
|
||
</dd>
|
||
|
||
<dt>
|
||
<code>android:minHeight</code>, <code>android:minWidth</code>
|
||
</dt>
|
||
|
||
<dd>
|
||
Minimum height and minimum width for the activity in both split-screen
|
||
and freeform modes. If the user moves the divider in split-screen mode
|
||
to make an activity smaller than the specified minimum, the system crops
|
||
the activity to the size the user requests.
|
||
</dd>
|
||
</dl>
|
||
|
||
<p>
|
||
For example, the following code shows how to specify an activity's default
|
||
size and location, and its minimum size, when the activity is displayed in
|
||
freeform mode:
|
||
</p>
|
||
|
||
<pre>
|
||
<activity android:name=".MyActivity">
|
||
<layout android:defaultHeight="500dp"
|
||
android:defaultWidth="600dp"
|
||
android:gravity="top|end"
|
||
android:minHeight="450dp"
|
||
android:minWidth="300dp" />
|
||
</activity>
|
||
</pre>
|
||
|
||
<h2 id="running">Running Your App in Multi-Window Mode</h2>
|
||
|
||
<p>
|
||
Beginning with Android 7.0, the system offers functionality to support apps
|
||
that can run in multi-window mode.
|
||
</p>
|
||
|
||
<h3 id="disabled-features">Disabled features in multi-window mode</h3>
|
||
|
||
<p>
|
||
Certain features are disabled or ignored when a device is in multi-window
|
||
mode, because they don’t make sense for an activity which may be sharing the
|
||
device screen with other activities or apps. Such features include:
|
||
|
||
<ul>
|
||
<li>Some <a href="{@docRoot}training/system-ui/index.html">System UI</a>
|
||
customization options are disabled; for example, apps cannot hide the status
|
||
bar if they are not running in full-screen mode.
|
||
</li>
|
||
|
||
<li>The system ignores changes to the <code><a href=
|
||
"{@docRoot}guide/topics/manifest/activity-element.html#screen"
|
||
>android:screenOrientation</a></code> attribute.
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 id="change-notification">Multi-window change notification and querying</h3>
|
||
|
||
<p>
|
||
{@link android.app.Activity} offers the following methods to support
|
||
multi-window display.
|
||
</p>
|
||
|
||
<dl>
|
||
<dt>
|
||
{@link android.app.Activity#isInMultiWindowMode isInMultiWindowMode()}
|
||
</dt>
|
||
|
||
<dd>
|
||
Call to find out if the activity is in multi-window mode.
|
||
</dd>
|
||
|
||
<dt>
|
||
{@link android.app.Activity#isInPictureInPictureMode
|
||
isInPictureInPictureMode()}
|
||
</dt>
|
||
|
||
<dd>
|
||
Call to find out if the activity is in <a href=
|
||
"{@docRoot}training/tv/playback/picture-in-picture.jd">picture-in-picture</a>
|
||
mode.
|
||
<p class="note">
|
||
<strong>Note:</strong> Picture-in-picture mode is a special case of
|
||
multi-window mode. If <code>myActivity.isInPictureInPictureMode()</code>
|
||
returns true, then <code>myActivity.isInMultiWindowMode()</code> also
|
||
returns true.
|
||
</p>
|
||
</dd>
|
||
|
||
<dt>
|
||
{@link android.app.Activity#onMultiWindowModeChanged
|
||
onMultiWindowModeChanged()}
|
||
</dt>
|
||
|
||
<dd>
|
||
The system calls this method whenever the activity goes into or out of
|
||
multi-window mode. The system passes the method a value of true if the
|
||
activity is entering multi-window mode, and false if the activity is
|
||
leaving multi-window mode.
|
||
</dd>
|
||
|
||
<dt>
|
||
{@link android.app.Activity#onPictureInPictureModeChanged
|
||
onPictureInPictureModeChanged()}
|
||
</dt>
|
||
|
||
<dd>
|
||
The system calls this method whenever the activity goes into or out of
|
||
picture-in-picture mode. The system passes the method a value of true if
|
||
the activity is entering picture-in-picture mode, and false if the activity
|
||
is leaving picture-in-picture mode.
|
||
</dd>
|
||
</dl>
|
||
|
||
<p>
|
||
The {@link android.app.Fragment} class exposes versions of many of these
|
||
methods, for example {@link android.app.Fragment#onMultiWindowModeChanged
|
||
Fragment.onMultiWindowModeChanged()}.
|
||
</p>
|
||
|
||
<h3 id="entering-pip">Entering picture-in-picture mode</h3>
|
||
|
||
<p>
|
||
To put an activity in picture-in-picture mode, call {@link
|
||
android.app.Activity#enterPictureInPictureMode
|
||
Activity.enterPictureInPictureMode()}. This method has no effect if the
|
||
device does not support picture-in-picture mode. For more information, see
|
||
the <a href=
|
||
"{@docRoot}training/tv/playback/picture-in-picture.jd">Picture-in-Picture</a>
|
||
documentation.
|
||
</p>
|
||
|
||
<h3 id="launch">Launch New Activities in Multi-Window Mode</h3>
|
||
|
||
<p>
|
||
When you launch a new activity, you can hint to the system that the new
|
||
activity should be displayed adjacent to the current one, if possible. To do
|
||
this, use the intent flag
|
||
{@link android.content.Intent#FLAG_ACTIVITY_LAUNCH_ADJACENT}. Passing
|
||
this flag requests the following behavior:
|
||
</p>
|
||
|
||
<ul>
|
||
<li>If the device is in split-screen mode, the system attempts to create the
|
||
new activity next to the activity that launched it, so the two activities
|
||
share the screen. The system is not guaranteed to be able to do this, but it
|
||
makes the activities adjacent if possible.
|
||
</li>
|
||
|
||
<li>If the device is not in split-screen mode, this flag has no effect.
|
||
</li>
|
||
</ul>
|
||
|
||
<p>
|
||
If a device is in freeform mode and you are launching a new activity, you can
|
||
specify the new activity's dimensions and screen location by calling
|
||
{@link android.app.ActivityOptions#setLaunchBounds
|
||
ActivityOptions.setLaunchBounds()}. This method has no effect if
|
||
the device is not in multi-window mode.
|
||
</p>
|
||
|
||
<p class="note">
|
||
<strong>Note:</strong> If you launch an activity within a task stack, the
|
||
activity replaces the activity on the screen, inheriting all of its
|
||
multi-window properties. If you want to launch the new activity as a separate
|
||
window in multi-window mode, you must launch it in a new task stack.
|
||
</p>
|
||
|
||
<h3 id="dnd">Supporting drag and drop</h3>
|
||
|
||
<p>
|
||
Users can <a href="{@docRoot}guide/topics/ui/drag-drop.html">drag and
|
||
drop</a> data from one activity to another while the two activities are
|
||
sharing the screen. (Prior to Android 7.0, users could only drag and drop data
|
||
within a single activity.) For this reason, you may want to add drag and drop
|
||
functionality to your app if your app does not currently support it.
|
||
</p>
|
||
|
||
|
||
<dl>
|
||
<dt>
|
||
{@link android.view.DragAndDropPermissions}
|
||
</dt>
|
||
|
||
<dd>
|
||
Token object responsible for specifying the permissions granted to the app
|
||
that receives a drop.
|
||
</dd>
|
||
|
||
<dt>
|
||
{@link android.view.View#startDragAndDrop View.startDragAndDrop()}
|
||
</dt>
|
||
|
||
<dd>
|
||
Alias for {@link android.view.View#startDrag View.startDrag()}. To enable
|
||
cross-activity drag and drop, pass the flag {@link
|
||
android.view.View#DRAG_FLAG_GLOBAL}. If you need to give URI permissions to
|
||
the recipient activity, pass the flags {@link
|
||
android.view.View#DRAG_FLAG_GLOBAL_URI_READ} or {@link
|
||
android.view.View#DRAG_FLAG_GLOBAL_URI_WRITE}, as appropriate.
|
||
</dd>
|
||
|
||
<dt>
|
||
{@link android.view.View#cancelDragAndDrop View.cancelDragAndDrop()}
|
||
</dt>
|
||
|
||
<dd>
|
||
Cancels a drag operation currently in progress. Can only be called by the
|
||
app that originated the drag operation.
|
||
</dd>
|
||
|
||
<dt>
|
||
{@link android.view.View#updateDragShadow View.updateDragShadow()}
|
||
</dt>
|
||
|
||
<dd>
|
||
Replaces the drag shadow for a drag operation currently in progress. Can
|
||
only be called by the app that originated the drag operation.
|
||
</dd>
|
||
|
||
<dt>
|
||
{@link android.app.Activity#requestDragAndDropPermissions
|
||
Activity.requestDragAndDropPermissions()}
|
||
</dt>
|
||
|
||
<dd>
|
||
Requests the permissions for the content URIs passed with the {@link
|
||
android.content.ClipData} contained in a {@link android.view.DragEvent}.
|
||
</dd>
|
||
</dl>
|
||
|
||
<h2 id="testing">Testing Your App's Multi-Window Support</h2>
|
||
|
||
<p>
|
||
Whether or not your app targets API level 24 or higher, you should
|
||
verify how it behaves in multi-window mode in case a user tries to launch it
|
||
in multi-window mode on a device running Android 7.0 or higher.
|
||
</p>
|
||
|
||
<h3 id="configuring">Configuring a Test Device</h3>
|
||
|
||
<p>
|
||
If a device runs Android 7.0 or higher, it automatically supports split-screen
|
||
mode.
|
||
</p>
|
||
|
||
<h3 id="test-non-n">If your app targets API level 23 or lower</h3>
|
||
|
||
<p>
|
||
If your app targets API level 23 or lower and the user attempts to use
|
||
the app in multi-window mode, the system forcibly resizes the app unless the
|
||
app declares a fixed orientation.
|
||
</p>
|
||
|
||
<p>
|
||
If your app does not declare a fixed orientation, you should launch your app
|
||
on a device running Android 7.0 or higher and attempt to put the app in
|
||
split-screen mode. Verify that the user experience is
|
||
acceptable when the app is forcibly resized.
|
||
</p>
|
||
|
||
<p>
|
||
If the app declares a fixed orientation, you should attempt to put the app in
|
||
multi-window mode. Verify that when you do so, the app remains
|
||
in full-screen mode.
|
||
</p>
|
||
|
||
<h3 id="test-mw">If you support multi-window mode</h3>
|
||
|
||
<p>
|
||
If your app targets API level 24 or higher and does not disable
|
||
multi-window support, verify the following behavior under both split-screen
|
||
and freeform modes.
|
||
</p>
|
||
|
||
<ul>
|
||
<li>Launch the app in full-screen mode, then switch to multi-window mode by
|
||
long-pressing the Overview button. Verify that the app switches properly.
|
||
</li>
|
||
|
||
<li>Launch the app directly in multi-window mode, and verify that the app
|
||
launches properly. You can launch an app in multi-window mode by pressing the
|
||
Overview button, then long-pressing the title bar of your app and dragging it
|
||
to one of the highlighted areas on the screen.
|
||
</li>
|
||
|
||
<li>Resize your app in split-screen mode by dragging the divider line.
|
||
Verify that the app resizes without crashing, and that necessary UI elements
|
||
are visible.
|
||
</li>
|
||
|
||
<li>If you have specified minimum dimensions for your app, attempt to resize
|
||
the app below those dimensions. Verify that you cannot resize the app to be
|
||
smaller than the specified minimum.
|
||
</li>
|
||
|
||
<li>Through all tests, verify that your app's performance is acceptable. For
|
||
example, verify that there is not too long a lag to update the UI after the
|
||
app is resized.
|
||
</li>
|
||
</ul>
|
||
|
||
<h4 id="test-checklist">Testing checklist</h4>
|
||
|
||
<p>
|
||
To verify your app's performance in multi-window mode, try the following
|
||
operations. You should try these operations in both split-screen and
|
||
multi-window mode, except where otherwise noted.
|
||
</p>
|
||
|
||
<ul>
|
||
<li>Enter and leave multi-window mode.
|
||
</li>
|
||
|
||
<li>Switch from your app to another app, and verify that the app behaves
|
||
properly while it is visible but not active. For example, if your app is
|
||
playing video, verify that the video continues to play while the user is
|
||
interacting with another app.
|
||
</li>
|
||
|
||
<li>In split-screen mode, try moving the dividing bar to make your app both
|
||
larger and smaller. Try these operations in both side-by-side and
|
||
one-above-the-other configurations. Verify that the app does not crash,
|
||
essential functionality is visible, and the resize operation doesn't take too
|
||
long.
|
||
</li>
|
||
|
||
<li>Perform several resize operations in rapid succession. Verify that your
|
||
app doesn't crash or leak memory. For information about checking your app's
|
||
memory usage, see <a href="{@docRoot}tools/debugging/debugging-memory.html">
|
||
Investigating Your RAM Usage</a>.
|
||
</li>
|
||
|
||
<li>Use your app normally in a number of different window configurations, and
|
||
verify that the app behaves properly. Verify that text is readable, and that
|
||
UI elements aren't too small to interact with.
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 id="test-disabled-mw">If you have disabled multi-window support</h3>
|
||
|
||
<p>
|
||
If you disabled multi-window support by setting
|
||
<code>android:resizeableActivity="false"</code>, you should launch your app on
|
||
a device running Android 7.0 or higher and attempt to put the app in
|
||
freeform and split-screen modes. Verify that when you do so, the app remains
|
||
in full-screen mode.
|
||
</p>
|