{"id":128,"date":"2020-03-05T14:43:00","date_gmt":"2020-03-05T22:43:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/surface-duo\/?p=128"},"modified":"2020-03-06T10:13:21","modified_gmt":"2020-03-06T18:13:21","slug":"bring-your-app-to-surface-duo-step-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/surface-duo\/bring-your-app-to-surface-duo-step-2\/","title":{"rendered":"Bring your app to Surface Duo &#8211; Step 2"},"content":{"rendered":"<p>Hello Surface Duo developers!<\/p>\n<p>In the Feb 6<sup>th<\/sup> blog post, we shared our <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/bring-your-app-to-surface-duo\/\">3 steps to bring your app to Microsoft Surface Duo<\/a>.<\/p>\n<p><img decoding=\"async\" class=\"wp-image-129 alignnone\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image.png\" width=\"1023\" height=\"516\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image.png 1148w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-300x151.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-1024x516.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-768x387.png 768w\" sizes=\"(max-width: 1023px) 100vw, 1023px\" \/><\/p>\n<p><span style=\"font-size: 8pt;\">Figure 1: Steps to bring your app to Microsoft Surface Duo<\/span><\/p>\n<p>Last week, Hakon from our awesome PM team provided more detail on <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/testing-your-app-on-the-dual-screen-form-factor\/\">step 1 and how to test your app<\/a>.<\/p>\n<p>This week, I want to share some details on Step 2 \u2013 things you can do TODAY to get your app working better on a dual screen device.<\/p>\n<p>The items listed below are some of the Android features you can add to light up your app on a dual screen device. None of these are specific to Surface Duo, but your app will benefit from them on other form factors such as foldables as well:<\/p>\n<ol>\n<li><strong>App resizing<\/strong> \u2013 Make sure your app adapts well to screen resizing and don\u2019t lock to a specific orientation.<\/li>\n<li><strong>Drag and drop<\/strong> is a key productivity scenario given that your app will run side by side with another app on the other screen.<\/li>\n<li><strong>Launch intents in the adjacent screen <\/strong>\u2013 Consider running user activities as new tasks, those can run in the other screen and keep users in their flow<\/li>\n<li><strong>Multi instance \u2013 <\/strong>Consider having tasks and activities as multi instance; this will allow users to run two tasks of your app, one on each screen.<\/li>\n<li><strong>Widgets<\/strong> can get more eyeballs on dual-screen devices<\/li>\n<li><strong>Pen <\/strong>usage will be natural on Surface Duo, consider adding support in your app<\/li>\n<\/ol>\n<p>Follow the guidance below and take a look at our <a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk-samples\">Java<\/a> and <a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk-samples-kotlin\">Kotlin samples<\/a> in GitHub.<\/p>\n<p><strong>App Resizing and Orientation<\/strong><\/p>\n<p>Your app should not lock to a specific size and layout and should consider many form factors and aspect ratios. While Surface Duo uses standard aspect ratios, be sure to follow the Google Android guidance on <a href=\"https:\/\/developer.android.com\/guide\/topics\/ui\/multi-window\">supporting Multi Windows<\/a>.<\/p>\n<p>The Surface Duo will be used in various postures, so allow your user to utilize those and don\u2019t lock the app to a specific orientation or layout.<\/p>\n<p><span style=\"font-size: 8pt;\"><img decoding=\"async\" class=\"alignnone wp-image-143\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/postures.jpg\" alt=\"Image postures\" width=\"1062\" height=\"219\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/postures.jpg 975w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/postures-300x62.jpg 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/postures-768x158.jpg 768w\" sizes=\"(max-width: 1062px) 100vw, 1062px\" \/><\/span><\/p>\n<p><span style=\"font-size: 8pt;\">Figure 2: Surface Duo Device Postures<\/span><\/p>\n<p><strong>Drag and Drop <\/strong><\/p>\n<p>Supporting drag and drop is very simple.<\/p>\n<p>You can support drag and drop within regions in the app, or support dragging content out from your app to another app, or support dropping dragged content from another app into your app.<\/p>\n<p>Our Drag and Drop sample below, can help with your code snippet<\/p>\n<p><img decoding=\"async\" class=\"alignnone wp-image-144\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/DragAndDrop-1.gif\" alt=\"Image DragAndDrop\" width=\"1060\" height=\"700\" \/><\/p>\n<p><span style=\"font-size: 8pt;\">Figure 3: Drag and Drop sample on the left screen<\/span><\/p>\n<p>In order to support drag and drop, make sure you follow the <a href=\"https:\/\/developer.android.com\/guide\/topics\/ui\/drag-drop\">Google Android Drag-and-Drop guidance<\/a>.<\/p>\n<p>In particular, make sure to add these to your code:<\/p>\n<ul>\n<li><strong>Pick Up &#8211; <\/strong>Enable content to be picked up and moved<\/li>\n<li><strong>Preview \u2013 <\/strong>Provide a preview for the content being dragged using <a href=\"https:\/\/developer.android.com\/reference\/android\/content\/ClipData\">ClipData<\/a> and a <a href=\"https:\/\/developer.android.com\/reference\/android\/view\/View.DragShadowBuilder\">DragShadowBuilder<\/a><\/li>\n<li>Provide preview for content being picked up so user can understand the flow<\/li>\n<li><strong>Drop Zones <\/strong>\u2013 Highlight the drop zone in your app so users can understand where they can drop content<\/li>\n<li><strong>Handle the Drop event <\/strong>\u2013 Respond to the ACTION_DROP and handle the content that is being dropped into your app. Make sure you support all relevant content types (Text, Image, URL, etc.)<\/li>\n<\/ul>\n<p><strong>Launch Intents in the adjacent screen<\/strong><\/p>\n<p>Many Android apps use intents to launch activities in their flows.<\/p>\n<p>A small trick you can apply with just a few lines of code is to utilize both screens and add value to your existing apps starting today.<\/p>\n<p>An example I like to use is a messaging app that supports group chats with a threaded view and a reply.<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-146\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/LaunchIntentAdjacent.gif\" alt=\"Launch Intent on the Adjacent Screen\" width=\"872\" height=\"594\" \/><\/p>\n<p><span style=\"font-size: 8pt;\">Figure 4: Group chat sample app<\/span><\/p>\n<p>Typically, when a user wants to write a reply to the group chat, the app is architected in way that it will launch a new Reply activity.<\/p>\n<p>Starting that activity will take over portions of the screen or even the whole screen, resulting in users losing their flow and the context of all other replies in the group chat.<\/p>\n<p>Your users will often bounce back and forth between the threaded view and the reply.<\/p>\n<p>However, with a few easy steps, you can launch the reply intent in the adjacent screen and keep the user in their flow.<\/p>\n<p>Let\u2019s see this in the code:<\/p>\n<p>When I add the below two flags to the intent parameters and start the activity, it will now utilize the adjacent screen.<\/p>\n<pre class=\"lang:java decode:true \" title=\"Intent Flags\">Intent intent = new Intent(this, SecondActivity.class);\r\n\/\/ Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT is required to launch a second activity on a second display while still keeping the first activity on the first display(not pausing\/stopping it)\r\n\r\n\r\nintent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);\r\nstartActivity(intent);<\/pre>\n<p>&nbsp;<\/p>\n<p>The cool thing here is that it will only do it if the adjacent screen is free. If you have another app running there, it will launch the activity on the same screen. It is that easy; just two lines of code.<\/p>\n<p><strong>Multi Instance:<\/strong><\/p>\n<p>Does it make sense for your app to support running multiple instances of activities?<\/p>\n<p>For example, comparing two web pages side-by-side in Edge browser.<\/p>\n<p>You can achieve this functionality by adding a secondary action to your app and enable users to launch them via a long press on your app icon, and click the secondary action shortcut.<\/p>\n<p><img decoding=\"async\" class=\"wp-image-133\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-3.png\" width=\"1012\" height=\"514\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-3.png 1191w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-3-300x152.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-3-1024x520.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-3-768x390.png 768w\" sizes=\"(max-width: 1012px) 100vw, 1012px\" \/><\/p>\n<p><span style=\"font-size: 8pt;\">Figure 5: Multi Instance app<\/span><\/p>\n<p>Follow the Google Android guidance for <a href=\"https:\/\/developer.android.com\/guide\/topics\/ui\/shortcuts\">App Shortcuts<\/a> and <a href=\"https:\/\/developer.android.com\/guide\/components\/activities\/tasks-and-back-stack\">Handling the tasks stack<\/a>, and take a look at our code snippet below:<\/p>\n<pre class=\"lang:java decode:true\" title=\"Setting a secondary Activity\">\/\/Add this code to your onCreate() method:\r\n\r\nIntent intent = new Intent(Intent.ACTION_MAIN, Uri.EMPTY, this, MainActivity.class);\r\nintent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);\r\n\r\nIntent intent2 = new Intent(Intent.ACTION_MAIN, Uri.EMPTY, this, SecondActivity.class);\r\nintent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);\r\n\r\n\r\nShortcutManager shortcutManager = getSystemService(ShortcutManager.class);\r\n\r\nShortcutInfo shortcut = new ShortcutInfo.Builder(this, \"id1\")\r\n.setShortLabel(\"New Instance\")\r\n.setLongLabel(\"New Instance\")\r\n.setIntent(intent)\r\n.build();\r\n\r\nShortcutInfo shortcut2 = new ShortcutInfo.Builder(this, \"id2\")\r\n.setShortLabel(\"Second Activity\")\r\n.setLongLabel(\"Second Activity\")\r\n.setIntent(intent2)\r\n.build();\r\n\r\nif (shortcutManager != null) {\r\nshortcutManager.setDynamicShortcuts(Arrays.asList(shortcut, shortcut2));\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Widgets<\/strong><\/p>\n<p>You might already be supporting widgets today. If you aren\u2019t, now might be a good time to add it as widgets can allow more user engagement when on dual-screen devices.<\/p>\n<p>In single screen phones, users typically unlock their device and perform a task such as launching an app or responding to a notification. In this flow, users are not spending too much time on the \u201chome screen\u201d engaging with widgets.<\/p>\n<p>However, with dual-screen devices, when users unlock their device and launch an app, the other screen is still free and will show home screen content such as widgets.<\/p>\n<p>To get started with widgets, follow the <a href=\"https:\/\/developer.android.com\/guide\/topics\/appwidgets\/overview\">Google Android Guidance<\/a>.<\/p>\n<p><strong>Feedback?<\/strong><\/p>\n<p>We would LOVE to hear from you about your experiences using the SDK, emulator, and your first thoughts on how you can utilize these in YOUR app.<\/p>\n<p>Please reach out using our <a href=\"http:\/\/aka.ms\/SurfaceDuoSDK-Feedback\">feedback forum<\/a> or direct message me on <a href=\"https:\/\/twitter.com\/gmerin\">Twitter<\/a> or <a href=\"https:\/\/github.com\/guymerin\">GitHub<\/a>.<\/p>\n<p>Thank you,<\/p>\n<p>Guy Merin, Development Manager, Surface Duo Developer Experience Team<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This blogpost details Step 2 in the journey to bring your app to Surface Duo.<br \/>\nThese will cover App resizing, Drag and drop support, how to launch intents in the adjacent screen, Multi instance\/Activities support, Widgets and Pen support<\/p>\n","protected":false},"author":17398,"featured_media":131,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[31,45,29,30],"class_list":["post-128","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-surface-duo-sdk","tag-dual-screen-development","tag-surface-duo-sdk","tag-surfaceduo","tag-surfaceduo-sdk"],"acf":[],"blog_post_summary":"<p>This blogpost details Step 2 in the journey to bring your app to Surface Duo.<br \/>\nThese will cover App resizing, Drag and drop support, how to launch intents in the adjacent screen, Multi instance\/Activities support, Widgets and Pen support<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/128","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/users\/17398"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/comments?post=128"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/128\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media\/131"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media?parent=128"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/categories?post=128"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/tags?post=128"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}