Display your app on multi-screen at the same time by using multi-display in Android.
Overview
Android 10 or higher version supported to display other activities on many external screens, and they are named multi-display which are used for foldable phones as well as a secondary screen is connected with your device.
Today, I will introduce with you about how to display an activity on another screen, and the SDK’s LG for the LG V50 to tracking event for this foldable phone with its cover secondary screen.
Display your activity on another screen
Declare your secondary activity in the manifest
1 2 3 4 5 6 7 8 9 10 11 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>manifest</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>android</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://schemas.android.com/apk/res/android<span class="token punctuation">"</span></span> <span class="token attr-name">package</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.android.multiplescreens<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <application <span class="token comment"><!-- See about the taskAffinity attribute at http://bit.ly/34RKvzC --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>activity</span> <span class="token attr-name"><span class="token namespace">android:</span>name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>.SecondActivity<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>launchMode</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>singleTask<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>taskAffinity</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>cover.container<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>application</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>manifest</span><span class="token punctuation">></span></span> |
launchMode
is singleTask
which combine between FLAG_ACTIVITY_CLEAR_TOP
and FLAG_ACTIVITY_NEW_TASK
set in your intent when you start an activity. Cause for using these flags is to run your activity on the new task.
Besides, I have an attribute that is taskAffinity
. If your activity just use the FLAG_ACTIVITY_NEW_TASK
flag that taskAffinity
isn’t set, it start on the same task with other activities. However, if you set taskAffinity
for your activity, it would run on the new task and activities have a same taskAffinity
will run together.
Start your activity
Firstly, you need a DisplayManager
which manages the properties of attached displays.
1 2 | <span class="token keyword">val</span> displayManager <span class="token operator">=</span> <span class="token function">getSystemService</span><span class="token punctuation">(</span>Context<span class="token punctuation">.</span>DISPLAY_SERVICE<span class="token punctuation">)</span> <span class="token keyword">as</span> DisplayManager |
Next, you use it to take all display connected with the device.
1 2 | <span class="token keyword">val</span> displays <span class="token operator">=</span> displayManager<span class="token punctuation">.</span>displays |
Ensure that your device has than more two-display then create activity options by the ActivityOptions
class to indicate the display ID that you would like to show your activity.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token keyword">if</span> <span class="token punctuation">(</span>displays<span class="token punctuation">.</span>size <span class="token operator">></span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>Build<span class="token punctuation">.</span>VERSION<span class="token punctuation">.</span>SDK_INT <span class="token operator">>=</span> Build<span class="token punctuation">.</span>VERSION_CODES<span class="token punctuation">.</span>O<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Activity options are used to select the display screen.</span> <span class="token keyword">val</span> options <span class="token operator">=</span> ActivityOptions<span class="token punctuation">.</span><span class="token function">makeBasic</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// Select the display screen that you want to show the second activity</span> options<span class="token punctuation">.</span>launchDisplayId <span class="token operator">=</span> displays<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>displayId <span class="token comment">// To display on the second screen that your intent must be set flag to make</span> <span class="token comment">// single task (combine FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_NEW_TASK)</span> <span class="token comment">// or you also set it in the manifest (see more at the manifest file)</span> <span class="token function">startActivity</span><span class="token punctuation">(</span> <span class="token function">Intent</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token label symbol">@MainActivity</span><span class="token punctuation">,</span> SecondActivity<span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">.</span>java<span class="token punctuation">)</span><span class="token punctuation">,</span> options<span class="token punctuation">.</span><span class="token function">toBundle</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Now, you can run your activity on another screen.
LG Dual Screen SDK
What’s the LG Dual Screen?
The LG Dual Screen is a mobile handset with two screens. Independent applications can be run on the screens at the same time.
It has an SDK to support for tracking folding events.
Callbacks
This SDK have two major callbacks:
CoverDisplayCallback
: Handle events related to states such as cover is enabled, disabled or dismounted.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token keyword">private</span> <span class="token keyword">inner</span> <span class="token keyword">class</span> MainCoverDisplayCallback <span class="token operator">:</span> DisplayManagerHelper<span class="token punctuation">.</span><span class="token function">CoverDisplayCallback</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onCoverDisplayEnabledChangedCallback</span><span class="token punctuation">(</span>state<span class="token operator">:</span> Int<span class="token punctuation">)</span> <span class="token punctuation">{</span> displayManagerHelper<span class="token operator">?</span><span class="token punctuation">.</span>coverDisplayState<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">let</span> <span class="token punctuation">{</span> Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"Current DualScreen Callback state: <span class="token interpolation"><span class="token delimiter variable">${</span><span class="token function">coverDisplayStateToString</span><span class="token punctuation">(</span>it<span class="token punctuation">)</span><span class="token delimiter variable">}</span></span>"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>prevDualScreenState <span class="token operator">!=</span> state<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">when</span> <span class="token punctuation">(</span>state<span class="token punctuation">)</span> <span class="token punctuation">{</span> DisplayManagerHelper<span class="token punctuation">.</span>STATE_UNMOUNT <span class="token operator">-></span> <span class="token punctuation">{</span> Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"Changed DualScreen State to STATE_UNMOUNT"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> DisplayManagerHelper<span class="token punctuation">.</span>STATE_DISABLED <span class="token operator">-></span> <span class="token punctuation">{</span> Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"Changed DualScreen State to STATE_DISABLED"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> DisplayManagerHelper<span class="token punctuation">.</span>STATE_ENABLED <span class="token operator">-></span> <span class="token punctuation">{</span> <span class="token function">toSecondScreen</span><span class="token punctuation">(</span><span class="token punctuation">)</span> Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"Changed DualScreen State to STATE_ENABLED"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> prevDualScreenState <span class="token operator">=</span> state <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
SmartCoverCallback
: This callback help indicate when your cover is opened, closed or flip over.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token keyword">private</span> <span class="token keyword">inner</span> <span class="token keyword">class</span> MainSmartCoverCallback <span class="token operator">:</span> DisplayManagerHelper<span class="token punctuation">.</span><span class="token function">SmartCoverCallback</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onTypeChanged</span><span class="token punctuation">(</span>type<span class="token operator">:</span> Int<span class="token punctuation">)</span> <span class="token punctuation">{</span> Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"SmartCoverCallback type: <span class="token interpolation"><span class="token delimiter variable">${</span>displayManagerHelper<span class="token operator">?</span><span class="token punctuation">.</span>coverType<span class="token delimiter variable">}</span></span>"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onStateChanged</span><span class="token punctuation">(</span>state<span class="token operator">:</span> Int<span class="token punctuation">)</span> <span class="token punctuation">{</span> displayManagerHelper<span class="token operator">?</span><span class="token punctuation">.</span>coverState<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">let</span> <span class="token punctuation">{</span> Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"Current SmartCoverCallback state: <span class="token interpolation"><span class="token delimiter variable">${</span><span class="token function">smartCoverStateToString</span><span class="token punctuation">(</span>it<span class="token punctuation">)</span><span class="token delimiter variable">}</span></span>"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">when</span> <span class="token punctuation">(</span>state<span class="token punctuation">)</span> <span class="token punctuation">{</span> DisplayManagerHelper<span class="token punctuation">.</span>STATE_COVER_OPENED <span class="token operator">-></span> <span class="token punctuation">{</span> Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"Received SmartCoverCallback is STATE_COVER_OPENED"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> DisplayManagerHelper<span class="token punctuation">.</span>STATE_COVER_CLOSED <span class="token operator">-></span> <span class="token punctuation">{</span> Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"Received SmartCoverCallback is STATE_COVER_CLOSED"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> DisplayManagerHelper<span class="token punctuation">.</span>STATE_COVER_FLIPPED_OVER <span class="token operator">-></span> <span class="token punctuation">{</span> Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"Received SmartCoverCallback is STATE_COVER_FLIPPED_OVER"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
DisplayManagerHelper
DisplayManagerHelper
is provided by SDK used to register above callbacks as well as determine your device is an LG dual screen or not.
You can construct this class with the current context. If it’s successful, your activity isn’t the LG dual screen device. Otherwise, you can register your callbacks through two-function are registerCoverDisplayEnabledCallback(key: String, callback: CoverDisplayCallback)
and registerSmartCoverCallback(callback: SmartCoverCallback)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token keyword">try</span> <span class="token punctuation">{</span> <span class="token comment">// Try to construct the DisplayMangerHelper.</span> <span class="token comment">// If it isn't successful, this device isn't LG dual screens</span> displayManagerHelper <span class="token operator">=</span> <span class="token function">DisplayManagerHelper</span><span class="token punctuation">(</span>applicationContext<span class="token punctuation">)</span> coverDisplayCallback <span class="token operator">=</span> <span class="token function">MainCoverDisplayCallback</span><span class="token punctuation">(</span><span class="token punctuation">)</span> smartCoverCallback <span class="token operator">=</span> <span class="token function">MainSmartCoverCallback</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// Register the callbacks for covers</span> displayManagerHelper<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">registerCoverDisplayEnabledCallback</span><span class="token punctuation">(</span> applicationContext<span class="token punctuation">.</span>packageName<span class="token punctuation">,</span> coverDisplayCallback <span class="token punctuation">)</span> displayManagerHelper<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">registerSmartCoverCallback</span><span class="token punctuation">(</span>smartCoverCallback<span class="token punctuation">)</span> isLGDualScreen <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token operator">:</span> Exception<span class="token punctuation">)</span> <span class="token punctuation">{</span> isLGDualScreen <span class="token operator">=</span> <span class="token boolean">false</span> Log<span class="token punctuation">.</span><span class="token function">e</span><span class="token punctuation">(</span>TAG<span class="token punctuation">,</span> <span class="token string">"This device isn't LG dual screens"</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Finally, you should remove all callbacks when your activity or fragment is destroyed to certain that isn’t occur a memory leak.
1 2 3 4 5 6 7 | <span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onDestroy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Remove all callbacks when this activity is destroyed</span> displayManagerHelper<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">unregisterCoverDisplayEnabledCallback</span><span class="token punctuation">(</span>applicationContext<span class="token punctuation">.</span>packageName<span class="token punctuation">)</span> displayManagerHelper<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">unregisterSmartCoverCallback</span><span class="token punctuation">(</span>smartCoverCallback<span class="token punctuation">)</span> <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">onDestroy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Demo
You can see my multi-screen demo on GitHub. If it’s helpful with you, lets a star for me.