Opting Out of Multi-Window is Hard
The docs make it seem so easy:
Set [
android:resizeableActivity
] in your manifest’s<activity>
or<application>
node to enable or disable multi-window display. If this attribute is set totrue
, the activity can be launched in split-screen and freeform modes. If the attribute is set tofalse
, 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.
Alas, it’s not that easy, at least not in all situations.
The key rule of multi-window is: the task determines the window.
Suppose that you have two activities. One you are perfectly content with
being used in split-screen or freeform modes. The other, not so much.
So, you set android:resizeableActivity
to be true
on the first,
false
on the second. You’re thinking that these attributes will
implement what you want.
What really happens is that either activity might behave in either
fashion… depending on which one is started first, how it is started,
and what other attributes you might have on the respective <activity>
elements.
If the true
activity is started first, then some other app tries
starting the false
activity (because it happens to be exported),
that false
activity will wind up in the
same task as the true
activity, by default. Since the true
activity
says that multi-window is cool, the false
activity appears in split-screen
mode, despite having android:resizeableActivity
be false
… because
it is in a task that allows multi-window mode.
Since you have no control over what Intent
flags
are used for exported activities, your options are somewhat constrained:
-
Just support multi-window mode for all of your activities. This may or may not be that easy, since windows can get pretty small.
-
Use the same
android:resizeableActivity
value for all exported activities, so any task will have the right multi-window behavior. -
Don’t export any activities other than the launcher activity, so you start all the rest of the activities yourself and have full control over the
Intent
flags that you use. You can then try to work out the right set of flags to give you the behavior that you want. For lots of apps, this will wind up being the answer, as many apps do not export anything other than the launcher activity already. -
Use
android:taskAffinity
to try to route different activities to different tasks, and hope that this doesn’t screw other stuff up too much, since tasks are for more than just multi-window behavior. -
Have the exported activity not be the “real” activity, but instead have it use
Theme.Translucent.NoTitleBar
(to have no UI of its own). Then, have it start the real not-exported activity with whateverIntent
flags that you want, so you have better control over how your real activity gets started. This would be more practical if we had a reliableisInMultiWindowMode()
, as that might impact what flags we choose.
Of course, there may be other options that I am not thinking of.
Making this more of a challenge is that we do not have real freeform multi-window mode support yet. Android-on-Chrome OS is starting, but it appears that Chrome OS support will be weird and not something that we can rely upon as a predictor of future results. I had expected a freeform multi-window announcement at Google I|O, other than Chrome OS, and that did not happen.
As with my earlier blog post on exported activities and freeform windows, getting multi-window right will require a fair amount of testing. Unfortunately, our time for this testing is running out, as Android N is supposed to ship to production devices in the July-September timeframe.