{"id":2042,"date":"2021-12-02T12:05:05","date_gmt":"2021-12-02T20:05:05","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/surface-duo\/?p=2042"},"modified":"2021-12-02T12:05:05","modified_gmt":"2021-12-02T20:05:05","slug":"uno-platform-android-foldable","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/surface-duo\/uno-platform-android-foldable\/","title":{"rendered":"Android foldable support on Uno Platform"},"content":{"rendered":"<p>\n  Hello XAML developers!\n<\/p>\n<p>\n  The Uno Platform has supported Microsoft Surface Duo since <a href=\"https:\/\/platform.uno\/blog\/surface-duo-winui-twopaneview-implementation-via-uno-platform\/\">early 2020<\/a> \u2013 the Uno Platform team even shared <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/get-started-uno-platform\">get started tips on this blog<\/a>. This support was based on the DuoSDK NuGet, which exposes the Microsoft DisplayMask API in C#. The Uno Platform implements the TwoPaneView control on all supported platforms, and by adding the <a href=\"https:\/\/www.nuget.org\/packages\/Uno.UI.DualScreen\">Uno.UI.DualScreen<\/a> NuGet it will \u2018light up\u2019 on Surface Duo, detecting the hinge and laying out the two panes accordingly.\n<\/p>\n<p>\n  At <a href=\"https:\/\/unoconf.com\/\"><em>UnoConf 2021<\/em><\/a> this week, we announced that we\u2019ve been working with the Uno Platform team to support the new Jetpack Window Manager API and extend Uno\u2019s foldable to support to other devices. The updated support replaces the old package and provides foldable enhancements for apps running on Surface Duo as well as other foldables that support Jetpack Window Manager.<\/p>\n<p>\n  Check out the <a href=\"https:\/\/platform.uno\/blog\/announcing-uno-platform-4-0-four-major-components-added\/\">Uno Platform 4.0 announcement blog<\/a> and watch the conference recording below for more details:\n<\/p>\n<p><iframe width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/QBQvE4M04fQ\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<h2>Uno.UI.Foldable<\/h2>\n<p>\n  The updated foldable support is available via the new <a href=\"https:\/\/www.nuget.org\/packages\/Uno.UI.Foldable\">Uno.UI.Foldable<\/a> NuGet, which replaces the DualScreen NuGet in your Uno Platform projects. The new library implements the same interfaces as the earlier version, so no user-code changes are required \u2013 the hinge angle sensor and <a href=\"https:\/\/docs.microsoft.com\/windows\/apps\/design\/controls\/two-pane-view\">TwoPaneView<\/a> control will both automatically work on foldable devices with Jetpack Window Manager support.\n<\/p>\n<p>\n  You can check out foldable Uno app samples on GitHub:\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"1107\" height=\"876\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/graphical-user-interface-application-description.png\" class=\"wp-image-2043\" alt=\"Screenshot of Uno Platform SamplesApp running on Surface Duo 2, showing the TwoPaneView test page\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/graphical-user-interface-application-description.png 1107w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/graphical-user-interface-application-description-300x237.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/graphical-user-interface-application-description-1024x810.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/graphical-user-interface-application-description-768x608.png 768w\" sizes=\"(max-width: 1107px) 100vw, 1107px\" \/><br\/><em>Figure 1: Uno Platform SamplesApp showing TwoPaneView<\/em>\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"1089\" height=\"870\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/a-picture-containing-text-electronics-descriptio.png\" class=\"wp-image-2044\" alt=\"Screenshot of Uno Platform SimpleCalculator app running on Surface Duo 2 across both screens\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/a-picture-containing-text-electronics-descriptio.png 1089w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/a-picture-containing-text-electronics-descriptio-300x240.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/a-picture-containing-text-electronics-descriptio-1024x818.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/a-picture-containing-text-electronics-descriptio-768x614.png 768w\" sizes=\"(max-width: 1089px) 100vw, 1089px\" \/><br\/><em>Figure 2: SimpleCalculator enhanced with TwoPaneView<\/em>\n<\/p>\n<h2>Contributing to the Uno Platform open-source project<\/h2>\n<p>\n  Because the Uno Platform is open source (Apache 2.0 license), we were able to view and understand the existing implementation, and ultimately contribute updated code via GitHub. These are the steps we followed:\n<\/p>\n<h3>1. Create an issue<\/h3>\n<p>\n  A great first step when contributing to any open-source project is to raise an issue to describe the bug you want to fix or the feature you\u2019d like to add. This gives the project maintainers a chance to understand your suggestion, de-duplicate it from any other similar work, and provide you with tips, hints, or ideas about how to approach the code. Getting agreement and approval from maintainers ensures you are on the right track from the start!\n<\/p>\n<p>\n  The foldable update started with issue <a href=\"https:\/\/github.com\/unoplatform\/uno\/issues\/6507\">#6507 Update implementation to use Window Manager<\/a>.\n<\/p>\n<h3>2. Build a prototype<\/h3>\n<p>\n  To prove that Jetpack Window Manager library could be referenced from Uno applications, I created a simple prototype using a C# binding for the Java API. The WindowJava NuGet that exposes the Window Manager APIs in C# is itself built from an open-source <a href=\"https:\/\/github.com\/xamarin\/AndroidX\/\">project<\/a>. The <a href=\"https:\/\/github.com\/conceptdev\/uno-samples\/tree\/main\/WindowManager\">prototype<\/a> contained two screens that test the hinge angle sensor, the folding feature detection, and the TwoPaneView API.\n<\/p>\n<p>\n<a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-demo-samplesapp-1.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-demo-samplesapp-1.png\" alt=\"Prototype Jetpack Window Manager sample running on Surface Duo and another foldable device\" width=\"1458\" height=\"729\" class=\"alignnone size-full wp-image-2062\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-demo-samplesapp-1.png 1458w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-demo-samplesapp-1-300x150.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-demo-samplesapp-1-1024x512.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-demo-samplesapp-1-768x384.png 768w\" sizes=\"(max-width: 1458px) 100vw, 1458px\" \/><\/a><br\/><em>Figure 3: FoldingFeature properties showing on Surface Duo and 7.6\u201d folding emulator<\/em>\n<\/p>\n<p>\n  Uno\u2019s dependency injection meant that once I had implemented the existing IApplicationViewSpanningRects interface, the control automatically inherited the updated behavior and was able to detect the fold on devices and emulators beyond Surface Duo. \n<\/p>\n<p>\n<a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-demo-twopane.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-demo-twopane.png\" alt=\"TwoPaneView sample running on Surface Duo and another foldable device\" width=\"1458\" height=\"729\" class=\"alignnone size-full wp-image-2065\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-demo-twopane.png 1458w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-demo-twopane-300x150.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-demo-twopane-1024x512.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-demo-twopane-768x384.png 768w\" sizes=\"(max-width: 1458px) 100vw, 1458px\" \/><\/a><br\/><em>Figure 4: TwoPaneView showing on a Surface Duo and a 7.6\u201d folding emulator<\/em>\n<\/p>\n<p>\n  Building the prototype outside of the Uno Platform codebase proved to be a fast and easy way to validate the approach would work, and also exposed areas where Uno could be extended to make implementation easier (e.g. adding activity lifecycle events). You can view these discussions in the issue history.\n<\/p>\n<h3>3. Submit a pull request<\/h3>\n<p>\n  Once the prototype was working and the overall approach agreed on with the maintainers, a fork and pull request was created <a href=\"https:\/\/github.com\/unoplatform\/uno\/pull\/7365\">#7365 feat: DualScreen support for multiple device models<\/a>. Another best practice is to keep your contribution focused on the agreed features, ensuring the code you add is easy to read (adheres to project standards) and bug free! Avoid the temptation to move code around, apply a different coding style, or anything that isn\u2019t directly related to your proposal \u2013 this makes it harder for the maintainers to understand, review, and ultimately accept your pull request.\n<\/p>\n<p>\n  When adding code to a project, it\u2019s usually a good idea to also make sure you add tests according to the repo\u2019s approach. In this case, since we were swapping out an implementation to an existing interface, there were conveniently already tests in place that could be used to validate the code. \n<\/p>\n<p>\n<a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-ci.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-ci.png\" alt=\"Uno Platform continuous integration results (showing all passing tests)\" width=\"1265\" height=\"465\" class=\"alignnone size-full wp-image-2055\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-ci.png 1265w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-ci-300x110.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-ci-1024x376.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/unoconf-ci-768x282.png 768w\" sizes=\"(max-width: 1265px) 100vw, 1265px\" \/><\/a><br\/><em>Figure 5: Continuous integration results<\/em><\/p>\n<p>\n  Finally, getting the pull request approved for merging can take a few tries. Projects with sophisticated CI systems (like Uno) run builds and tests and can warn you of problems (and sometimes how to fix them). Once your implementation is done and you get green builds, use the pull request or issue discussion to communicate with the maintainers, get approval for your work, and see it merged into main!\n<\/p>\n<h2>Resources and feedback<\/h2>\n<p>\n  Visit the <a href=\"https:\/\/unoconf.com\/\">UnoConf 2021<\/a> website to watch the session recordings, and use the\u00a0<a href=\"http:\/\/aka.ms\/SurfaceDuoSDK-Feedback\">feedback forum<\/a>\u00a0or message us on Twitter\u00a0<a href=\"https:\/\/twitter.com\/surfaceduodev\">@surfaceduodev<\/a> to share your app ideas or if you have any questions about building foldable apps with Uno, or any other platform.\n<\/p>\n<p>\n  Finally, please join us for our <a href=\"https:\/\/twitch.tv\/surfaceduodev\">dual screen developer livestream<\/a> at 11am (Pacific time) each Friday \u2013 mark it in your calendar and check out the <a href=\"https:\/\/www.youtube.com\/channel\/UClGu9QLtPNz8OdddBfhZXPA\">archives on YouTube<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello XAML developers! The Uno Platform has supported Microsoft Surface Duo since early 2020 \u2013 the Uno Platform team even shared get started tips on this blog. This support was based on the DuoSDK NuGet, which exposes the Microsoft DisplayMask API in C#. The Uno Platform implements the TwoPaneView control on all supported platforms, and [&hellip;]<\/p>\n","protected":false},"author":570,"featured_media":2043,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[706,46,695],"class_list":["post-2042","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-surface-duo-sdk","tag-jetpack-window-manager","tag-surface-duo","tag-uno-platform"],"acf":[],"blog_post_summary":"<p>Hello XAML developers! The Uno Platform has supported Microsoft Surface Duo since early 2020 \u2013 the Uno Platform team even shared get started tips on this blog. This support was based on the DuoSDK NuGet, which exposes the Microsoft DisplayMask API in C#. The Uno Platform implements the TwoPaneView control on all supported platforms, and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/2042","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\/570"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/comments?post=2042"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/2042\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media\/2043"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media?parent=2042"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/categories?post=2042"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/tags?post=2042"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}