{"id":151,"date":"2020-03-13T11:44:13","date_gmt":"2020-03-13T18:44:13","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/surface-duo\/?p=151"},"modified":"2020-03-13T11:44:57","modified_gmt":"2020-03-13T18:44:57","slug":"ring-your-app-to-surface-duo-step-3","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/surface-duo\/ring-your-app-to-surface-duo-step-3\/","title":{"rendered":"Bring your app to Surface Duo \u2013 Step 3"},"content":{"rendered":"<p>Hello Surface Duo developers!<\/p>\n<p>In our Feb 6<sup>th<\/sup> blog post, we shared <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>, followed by a post 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> and <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/bring-your-app-to-surface-duo-step-2\/\">step 2 highlighting incremental changes<\/a> to make to your app<\/p>\n<p><img decoding=\"async\" width=\"1148\" height=\"579\" class=\"wp-image-152\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-4.png\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-4.png 1148w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-4-300x151.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-4-1024x516.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-4-768x387.png 768w\" sizes=\"(max-width: 1148px) 100vw, 1148px\" \/><\/p>\n<p style=\"text-align: left;\">Figure 1: Steps to bring your app to Microsoft Surface Duo 1: Steps to bring your app to Microsoft Surface Duo<\/p>\n<p>This week\u2019s blogpost will share details for Step 3 \u2013 How to embrace new Dual Screen features on Surface Duo.<\/p>\n<p>There are multiple ways to take advantage of the dual screens:<\/p>\n<ul>\n<li>Access the dual screen APIs directly<\/li>\n<li>Helper libraries<\/li>\n<li>Screen manager<\/li>\n<li>Dedicated layouts &amp; controls we&#8217;ll provide<\/li>\n<\/ul>\n<p>This blog post covers how to access the dual screen APIs in your layout code.<\/p>\n<p><img decoding=\"async\" width=\"745\" height=\"379\" class=\"wp-image-153\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-5.png\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-5.png 745w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-5-300x153.png 300w\" sizes=\"(max-width: 745px) 100vw, 745px\" \/><\/p>\n<p style=\"text-align: left;\">Figure 2: Dual Screen APIs layers<\/p>\n<h2>Microsoft Dual Screen APIs:<\/h2>\n<h2>Display Mask<\/h2>\n<p>The most useful API is the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dual-screen\/android\/api-reference\/display-mask?tabs=java\">DisplayMask<\/a>, which gives you a <a href=\"https:\/\/developer.android.com\/reference\/android\/graphics\/Rect\">RECT<\/a> with coordinates for the location of the<\/p>\n<p>Use this API to understand if your app and layouts intersects with the mask, and re-positions controls and assets based on their relevant position.<\/p>\n<p>Remember, you can also position controls differently if you\u2019re running on the left screen vs the right screen.<\/p>\n<p>The values you\u2019ll get differ based on the device <a href=\"https:\/\/developer.android.com\/reference\/android\/view\/Display.html#getRotation()\">rotation<\/a><\/p>\n<p><img decoding=\"async\" width=\"1614\" height=\"1578\" class=\"wp-image-154\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/a-screenshot-of-a-social-media-post-description-a.jpeg\" alt=\"A screenshot of a social media post Description automatically generated\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/a-screenshot-of-a-social-media-post-description-a.jpeg 1614w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/a-screenshot-of-a-social-media-post-description-a-300x293.jpeg 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/a-screenshot-of-a-social-media-post-description-a-1024x1001.jpeg 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/a-screenshot-of-a-social-media-post-description-a-768x751.jpeg 768w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/a-screenshot-of-a-social-media-post-description-a-1536x1502.jpeg 1536w\" sizes=\"(max-width: 1614px) 100vw, 1614px\" \/> Figure 3: The Display Mask locationThe Display Mask location<\/p>\n<p>See this sample code:<\/p>\n<pre class=\"lang:default decode:true\">DisplayMask displayMask = DisplayMask.fromResourcesRect(context);\r\n\r\nInt rotation;\r\n\r\nList&lt;Rect&gt; masks = displayMask.getBoundingRectsForRotation(rotation);\r\nRect mask = new Rect();\r\nif(!masks.isEmpty()) {\r\n  mask = masks.get(0);\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h2>Hinge Angle<\/h2>\n<p>You can also measure and act on the hinge angle between the two screens. We&#8217;ve added the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dual-screen\/android\/api-reference\/hinge-sensor?tabs=java\">hinge angle as a native sensor<\/a>, so you can add a listener to retrieve the value as the screens move.<\/p>\n<p>The range of motion is 0-360 degrees, which affects the screen display as shown in the diagram below:<\/p>\n<p><img decoding=\"async\" width=\"591\" height=\"667\" class=\"wp-image-155\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-6.png\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-6.png 591w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/word-image-6-266x300.png 266w\" sizes=\"(max-width: 591px) 100vw, 591px\" \/><\/p>\n<p>Figure 4: The Hinge Sensor<\/p>\n<p>Adding this code to read the sensor values:<\/p>\n<pre class=\"lang:java decode:true\" title=\"The Hinge Sensor\">private static final String HINGE_ANGLE_SENSOR_NAME = \"Hinge Angle Non-Wakeup\";\r\n\r\nprivate SensorManager mSensorManager;\r\n\r\nprivate Sensor mHingeAngleSensor;\r\n\r\nprivate SensorEventListener mSensorListener;\r\n\r\nprivate void setupSensors() {\r\n\r\n  mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);\r\n  List&lt;Sensor&gt; sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);\r\n  for (Sensor sensor : sensorList) {\r\n    if (sensor.getName().contains(HINGE_ANGLE_SENSOR_NAME)) {\r\n      mHingeAngleSensor = sensor;\r\n    }\r\n  }\r\n  mSensorListener = new SensorEventListener() {\r\n    @Override public void onSensorChanged(final SensorEvent event) {\r\n      if (event.sensor == mHingeAngleSensor) {\r\n        int angle = (int) event.values[0];\r\n      }\r\n    }\r\n    @Override public void onAccuracyChanged(Sensor sensor, int accuracy) {\r\n      \/\/TODO\r\n    }\r\n  };\r\n}\r\n\r\n@Override protected void onPause() {\r\n  super.onPause();\r\n  if(mHingeAngleSensor !=null) {\r\n    mSensorManager.unregisterListener(mSensorListener,mHingeAngleSensor);\r\n  }\r\n}\r\n\r\n@Override protected void onResume() {\r\n  super.onResume();\r\n  if(mHingeAngleSensor !=null) {\r\n    mSensorManager.registerListener(mSensorListener, mHingeAngleSensor, SensorManager.SENSOR_DELAY_NORMAL);\r\n  }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h2>Duo Device Capability<\/h2>\n<p>We know there&#8217;ll be times you want to build something special for Surface Duo devices, so we&#8217;ve made it easy to check at run-time with a <a href=\"https:\/\/docs.microsoft.com\/en-us\/dual-screen\/android\/sample-code\/is-dual-screen-device?tabs=java\">device capability flag<\/a>.<\/p>\n<p>Use the code below to detect Surface Duo devices, so it&#8217;s easier to maintain one codebase for all device configurations:<\/p>\n<p>Add this code snippet to your code:<\/p>\n<pre class=\"lang:java decode:true\" title=\"Duo Device Capability\">private boolean isDualScreenDevice(){\r\nString feature = \"com.microsoft.device.display.displaymask\";\r\nPackageManager pm = this.getPackageManager();\r\n\r\n  if (pm.hasSystemFeature(feature)) {\r\n    Log.i(TAG, \"System has feature: \" + feature);\r\n    return true;\r\n  } else {\r\n    Log.w(TAG, \"System missing feature: \" + feature);\r\n    return false;\r\n  }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"font-size: 1rem;\">*Note: You can also query the device name, but it will hard code the app to the Duo device, so not ideal<\/span><\/p>\n<h2>Summary:<\/h2>\n<p>See these APIs in action in our Sample GIT repos, we got your covered in <a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk-samples\">Java Samples<\/a>, <a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk-samples-kotlin\">Kotlin samples<\/a> in and <a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk-xamarin-samples\">C# Xamarin Samples<\/a>, all hosted in GitHub.<\/p>\n<p>Let us know how you are planning to use these APIs and how we can make it easier on you.<\/p>\n<p>And make sure to read our next week blog that will cover our helper functions and a new Dual Screen Layout Control that will speed up your development.<\/p>\n<h2>Feedback<\/h2>\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>And if you haven\u2019t seen those already, we started a <a href=\"https:\/\/www.youtube.com\/playlist?reload=9&amp;list=PLlrxD0HtieHg0F4sBsc4c29ReSHQqpsqs\">series of 1 minute videos<\/a> to answer the most common questions<\/p>\n<p>Thank you,<\/p>\n<p>Guy Merin, Development Manager, Surface Duo Developer Experience Team<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello Surface Duo developers! In our Feb 6th blog post, we shared 3 steps to bring your app to Microsoft Surface Duo, followed by a post on step 1 and how to test your app and step 2 highlighting incremental changes to make to your app Figure 1: Steps to bring your app to Microsoft [&hellip;]<\/p>\n","protected":false},"author":17398,"featured_media":155,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[31,29,30],"class_list":["post-151","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-surface-duo-sdk","tag-dual-screen-development","tag-surfaceduo","tag-surfaceduo-sdk"],"acf":[],"blog_post_summary":"<p>Hello Surface Duo developers! In our Feb 6th blog post, we shared 3 steps to bring your app to Microsoft Surface Duo, followed by a post on step 1 and how to test your app and step 2 highlighting incremental changes to make to your app Figure 1: Steps to bring your app to Microsoft [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/151","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=151"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/151\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media\/155"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media?parent=151"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/categories?post=151"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/tags?post=151"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}