Opting Out of Multi-Window is Hard
The docs make it seem so easy:
android:resizeableActivity] in your manifest’s
<application>node to enable or disable multi-window display. 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.
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
true activity is started first, then some other app tries
false activity (because it happens to be exported),
false activity will wind up in the
same task as the
true activity, by default. Since the
says that multi-window is cool, the
false activity appears in split-screen
mode, despite having
it is in a task that allows multi-window mode.
Since you have no control over what
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:resizeableActivityvalue 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
Intentflags 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.
android:taskAffinityto 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 whatever
Intentflags that you want, so you have better control over how your real activity gets started. This would be more practical if we had a reliable
isInMultiWindowMode(), 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.
Want an expert opinion on your Android app architecture decisions? Perhaps Mark Murphy can help!