{"id":207434,"date":"2024-02-23T20:49:41","date_gmt":"2024-02-23T20:49:41","guid":{"rendered":"https:\/\/michigandigitalnews.com\/index.php\/2024\/02\/23\/increase-your-apps-availability-across-device-types\/"},"modified":"2025-06-25T17:21:40","modified_gmt":"2025-06-25T17:21:40","slug":"increase-your-apps-availability-across-device-types","status":"publish","type":"post","link":"https:\/\/michigandigitalnews.com\/index.php\/2024\/02\/23\/increase-your-apps-availability-across-device-types\/","title":{"rendered":"Increase your app\u2019s availability across device types"},"content":{"rendered":"<p> [ad_1]<br \/>\n<\/p>\n<div>\n<meta content=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEh0mQvASMlgKp0V9-V7d-D1uIC5j1aSzEBxwsAxr1nxEyaCBYM53s2qTJ9PiS1cJ6V1ZikicN_ptQQJjwDdoWVKNzdpLzCJxJ0NQoQ5UxVRYV924yj2sXDV_obr9ajYa8nHQTTRSK2N-iNBfYRj2c_T1507KUjsZLeJkJTxMLOHH3GJ77xX0mKOEq_QJ54\/s1600\/social-Remove-unnecessary-required-features%20%281%29.png\" name=\"twitter:image\"\/><br \/>\n<img decoding=\"async\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEh0mQvASMlgKp0V9-V7d-D1uIC5j1aSzEBxwsAxr1nxEyaCBYM53s2qTJ9PiS1cJ6V1ZikicN_ptQQJjwDdoWVKNzdpLzCJxJ0NQoQ5UxVRYV924yj2sXDV_obr9ajYa8nHQTTRSK2N-iNBfYRj2c_T1507KUjsZLeJkJTxMLOHH3GJ77xX0mKOEq_QJ54\/s1600\/social-Remove-unnecessary-required-features%20%281%29.png\" style=\"display: none;\"\/><\/p>\n<p><em>Posted by Alex Vanyo \u2013 Developer Relations Engineer<\/em><\/p>\n<p><a href=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEjuGXY_G5N4CDN2OcJC4IWqYwKpQgbWmgOPGgNe5oZdfRT-hZkaBGn2TKpCbcNiS2BkWRFFoO-opsO5_fdcsotKYLBsxJzBOBXrEpUWpAH4qNLDYVBGI2T_w2lH4dWyqeMKnXAYwJHyR4a2G1GTQ0Nc9Ft_Yr21KXCyKwC-5u-hxBYbaKcj-s_ic2sdq-4\/s1600\/header-Remove-unnecessary-required-features%20%281%29.png\"><img decoding=\"async\" border=\"0\" data-original-height=\"800\" data-original-width=\"100%\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEjuGXY_G5N4CDN2OcJC4IWqYwKpQgbWmgOPGgNe5oZdfRT-hZkaBGn2TKpCbcNiS2BkWRFFoO-opsO5_fdcsotKYLBsxJzBOBXrEpUWpAH4qNLDYVBGI2T_w2lH4dWyqeMKnXAYwJHyR4a2G1GTQ0Nc9Ft_Yr21KXCyKwC-5u-hxBYbaKcj-s_ic2sdq-4\/s1600\/header-Remove-unnecessary-required-features%20%281%29.png\"\/><\/a><\/p>\n<h2><span style=\"font-size: large;\"><b>TL;DR:<\/b><\/span><span style=\"font-size: large;\"><i> Remove unnecessary feature requirements that prevent users from downloading your app on devices that don\u2019t support the features. Automate tracking feature requirements and maximize app availability with badging!<\/i><\/span><\/h2>\n<h2><span style=\"font-size: x-large;\">Required features reduce app availability<\/span><\/h2>\n<p><span style=\"font-family: Courier;\"> <a href=\"https:\/\/developer.android.com\/guide\/topics\/manifest\/uses-feature-element\" target=\"_blank\" rel=\"noopener\">&lt;uses-feature&gt;<\/a><\/span> is an app manifest element that specifies whether your app depends on a <a href=\"https:\/\/developer.android.com\/guide\/topics\/manifest\/uses-feature-element#features-reference\" target=\"_blank\" rel=\"noopener\">hardware or software feature<\/a>. By default, <span style=\"color: #0d904f; font-family: Courier;\">&lt;uses-feature&gt;<\/span> specifies that a feature is required. To indicate that the feature is optional, you must add the <span style=\"color: #0d904f; font-family: Courier;\">android:required=&#8221;false&#8221;<\/span> attribute.<\/p>\n<p>Google Play <a href=\"https:\/\/developer.android.com\/guide\/topics\/manifest\/uses-feature-element#market-feature-filtering\" target=\"_blank\" rel=\"noopener\">filters<\/a> which apps are available to download based on required features. If the user\u2019s device doesn\u2019t support some hardware or software feature, then an app that requires that feature won\u2019t be available for the user to download.<\/p>\n<p><span style=\"font-family: Courier;\"><a href=\"https:\/\/developer.android.com\/guide\/topics\/manifest\/uses-permission-element\" target=\"_blank\" rel=\"noopener\">&lt;uses-permission&gt;<\/a><\/span>, another app manifest element, complicates things by implicitly requiring features for permissions such as <span style=\"color: #0d904f; font-family: Courier;\">CAMERA<\/span> or <span style=\"color: #0d904f; font-family: Courier;\">BLUETOOTH<\/span> (see <a href=\"https:\/\/developer.android.com\/guide\/topics\/manifest\/uses-feature-element#permissions\" target=\"_blank\" rel=\"noopener\">Permissions that imply feature requirements<\/a>). The initial declared orientations for your activities can also <a href=\"https:\/\/developer.android.com\/guide\/topics\/manifest\/uses-feature-element#screen-hw-features\" target=\"_blank\" rel=\"noopener\">implicitly require<\/a> hardware features.<\/p>\n<p>The system determines implicitly required features after merging all modules and dependencies, so it may not be clear to you which features your app ultimately requires. You might not even be aware when the list of required features has changed. For example, integrating a new dependency into your app might introduce a new required feature. Or the integration might request additional permissions, and the permissions could introduce new, implicitly required features.<\/p>\n<p>This behavior has been around for a while, but Android has changed a lot over the years. Android apps now run on phones, foldables, tablets, laptops, cars, TVs and watches, and these devices are more varied than ever. Some devices don\u2019t have telephony services, some don\u2019t have touchscreens, some don\u2019t have cameras.<\/p>\n<p>Expectations based on permissions have also changed. With runtime permissions, a <span style=\"font-family: Courier;\"><a href=\"https:\/\/developer.android.com\/guide\/topics\/manifest\/uses-permission-element\" target=\"_blank\" rel=\"noopener\">&lt;uses-permission&gt;<\/a><\/span> declaration in the manifest no longer guarantees that your app will be granted that permission. Users can choose to deny access to hardware in favor of other ways to interact with the app. For example, instead of giving an app permission to access the device\u2019s location, a user may prefer to always search for a particular location instead.<\/p>\n<p>Banking apps shouldn\u2019t require the device to have an autofocusing camera for check scanning. They shouldn\u2019t specify that the camera must be a front or rear camera or that the device has a camera at all! It should be enough to allow the user to upload a picture of a check from another source.<\/p>\n<p>Apps should support keyboard navigation and mouse input for accessibility and usability reasons, so strictly requiring a hardware touchscreen should not be necessary.<\/p>\n<p>Apps should support both landscape and portrait orientations, so they shouldn\u2019t require that the screen could be landscape-oriented or could be portrait-oriented. For example, screens built in to cars may be in a fixed landscape orientation. Even if the app supports both landscape and portrait, the app could be unnecessarily requiring that the device supports being used in portrait, which would exclude those cars.<\/p>\n<h2><span style=\"font-size: x-large;\">Determine your app\u2019s required features<\/span><\/h2>\n<p>You can use <span style=\"font-family: Courier;\"><a href=\"https:\/\/developer.android.com\/tools\/aapt2\" target=\"_blank\" rel=\"noopener\">aapt2<\/a><\/span> to <a href=\"https:\/\/developer.android.com\/guide\/topics\/manifest\/uses-feature-element#testing\" target=\"_blank\" rel=\"noopener\">output information<\/a> about your APK, including the explicitly and implicitly required features. The logic matches how the Play Store filters app availability.<\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span style=\"color: #0d904f; font-family: courier;\">aapt2 dump badging &lt;path_to_.apk&gt;<\/span><\/pre>\n<\/div>\n<p>In the Play Console, you can also check which devices are being excluded from accessing your app.<\/p>\n<h2><span style=\"font-size: x-large;\">Increase app availability by making features optional<\/span><\/h2>\n<p>Most apps should not strictly require hardware and software features. There are few guarantees that the user will allow using that feature in the first place, and users expect to be able to use all parts of your app in the way they see fit. To increase your app\u2019s availability across form factors:<\/p>\n<ul>\n<ul>\n<li>Provide alternatives in case the feature is not available, ensuring your app doesn\u2019t need the feature to function.<\/li>\n<li>Add <span style=\"color: #0d904f; font-family: Courier;\">android:required=&#8221;false&#8221;<\/span> to existing <span style=\"font-family: Courier;\"><a href=\"https:\/\/developer.android.com\/guide\/topics\/manifest\/uses-feature-element\" target=\"_blank\" rel=\"noopener\">&lt;uses-feature&gt;<\/a><\/span> tags to mark the feature as not required (or remove the tag entirely if the app no longer uses a feature).<\/li>\n<li>Add the <span style=\"color: #0d904f; font-family: Courier;\">&lt;uses-feature&gt;<\/span> tag with <span style=\"color: #0d904f; font-family: Courier;\">android:required=&#8221;false&#8221;<\/span> for implicitly required feature due to declaring <a href=\"https:\/\/developer.android.com\/guide\/topics\/manifest\/uses-feature-element#permissions\" target=\"_blank\" rel=\"noopener\">permissions that imply feature requirements<\/a>.<\/li>\n<\/ul>\n<\/ul>\n<h2><span style=\"font-size: x-large;\">Prevent regressions with CI and badging<\/span><\/h2>\n<p>To guard against regressions caused by inadvertently adding a new feature requirement that reduces device availability, automate the task of determining your app\u2019s features as part of your build system. By storing the badging output of the <span style=\"color: #0d904f; font-family: Courier;\">aapt2<\/span> tool in a text file and checking the file into version control, you can track all declared permissions and explicitly and implicitly required features from your final universal apk. This includes all features and permissions included by transitive dependencies, in addition to your own.<\/p>\n<p>You can automate badging as part of your continuous integration setup by setting up three Gradle tasks for each variant of your app you want to validate. Using release as an example, create these three tasks:<\/p>\n<ul>\n<ul>\n<li><span style=\"color: #0d904f; font-family: Courier;\">generateReleaseBadging<\/span> \u2013 Generates the badging file from the universal APK using the <span style=\"color: #0d904f; font-family: Courier;\">aapt2<\/span> executable. The output of this task (the badging information) is used for the following two tasks.<\/li>\n<li><span style=\"color: #0d904f; font-family: Courier;\">updateReleaseBadging<\/span> \u2013 Copies the generated badging file into the main project directory. The file is checked into source control as a <i>golden<\/i> badging file.<\/li>\n<li><span style=\"color: #0d904f; font-family: Courier;\">checkReleaseBadging<\/span> \u2013 Validates the generated badging file against the golden badging file.<\/li>\n<\/ul>\n<\/ul>\n<p>CI should run <span style=\"color: #0d904f; font-family: Courier;\">checkReleaseBadging<\/span> to verify that the checked-in golden badging file still matches the generated badging file for the current code. If code changes or dependency updates have caused the badging file to change in any way, CI fails.<\/p>\n<p><image><\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" alt=\"Screen grab of failing CI due to adding a new permission and required feature without updating the badging file.\" border=\"0\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEg5gEmbKrLOZt8WPIz8W14trqUnJHSV_OGxOrbnxZT3hjwfsLzjumUXUr3TmIIPc7R9LUKWkMI-0dLvpr9Twv5oSQuSVD3I1A3cg2tk8LZVrxEUeGIiJdspr37IdZmjAg503XXO49x9EcoFrnwRw8p-FhUAFMYsxbjRJS1ZvkG-A2iWM-0j0_3iPs4HYec\/s1600\/image2.png\" style=\"margins: auto; width: auto;\"\/><\/div>\n<p><imgcaption><center><em>Failing CI due to adding a new permission and required feature without updating the badging file.<\/em><\/center><\/imgcaption><\/image><\/p>\n<p>When changes are intentional, run <span style=\"color: #0d904f; font-family: Courier;\">updateReleaseBadging<\/span> to update the golden badging file and recheck it into source control. Then, this change will surface in code review to be validated by reviewers that the badging changes are expected.<\/p>\n<p><image><\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" alt=\"Screen grab showing updated golden badging file for review with additional permission and implied required feature.\" border=\"0\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhmh5GYFVBnxMNGc1KanoawkqJjUn7Sgy6CNO0WoVhFU2PF0kAp78EeC7tBZrGJ2yLj_uaMLVdvxOo9nY0qSmaUTjQQRy3kIsHaC8BL1MoUdU65YaskKhz8Jgb3O-iUQaQ5lWaQDrS_MW8QHOSkS0byHTGJyveF-4ceLxIWViYIti0rQQPK09QQs1itxMg\/s1600\/image1.png\" style=\"margins: auto; width: auto;\"\/><\/div>\n<p><imgcaption><center><em>Updated golden badging file for review with additional permission and implied required feature.<\/em><\/center><\/imgcaption><\/image><\/p>\n<p>CI-automated badging guards against changes inadvertently causing a new feature to be required, which would reduce availability of the app.<\/p>\n<p>For a complete working example of a CI system verifying the badging file, check out the setup in the <a href=\"https:\/\/github.com\/android\/nowinandroid\" target=\"_blank\" rel=\"noopener\">Now in Android<\/a> app.<\/p>\n<h2><span style=\"font-size: x-large;\">Keep features optional<\/span><\/h2>\n<p>Android devices are continually becoming more varied, with users expecting a great experience from your Android app regardless of the type of device they\u2019re using. While some software or hardware features might be essential to your app\u2019s function, in many cases they should not be strictly required, needlessly preventing some users from downloading your app.<\/p>\n<p>Use the <a href=\"https:\/\/developer.android.com\/guide\/topics\/manifest\/uses-feature-element#testing\" target=\"_blank\" rel=\"noopener\">badging<\/a> output from <span style=\"color: #0d904f; font-family: Courier;\">aapt2<\/span> to check which features your app requires, and use the Play Console to verify which devices the requirements are preventing from downloading your app. You can automatically check your app\u2019s badging in CI and catch regressions.<\/p>\n<p><b>Bottom line:<\/b> If you don\u2019t absolutely need a feature for your entire app to function, make the feature optional to ensure your app\u2019s availability to the greatest number of devices and users.<\/p>\n<p>Learn more by checking out our <a href=\"https:\/\/developer.android.com\/guide\/topics\/manifest\/uses-feature-element\" target=\"_blank\" rel=\"noopener\">developer guide<\/a>.<\/p>\n<\/div>\n<p>[ad_2]<br \/>\n<br \/><a href=\"http:\/\/android-developers.googleblog.com\/2023\/12\/increase-your-apps-availability-across-device-types.html\">Source link <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>[ad_1] Posted by Alex Vanyo \u2013 Developer Relations Engineer TL;DR: Remove unnecessary feature requirements that prevent users from downloading your app on devices that don\u2019t<\/p>\n","protected":false},"author":1,"featured_media":207435,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[146],"tags":[],"_links":{"self":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts\/207434"}],"collection":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/comments?post=207434"}],"version-history":[{"count":1,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts\/207434\/revisions"}],"predecessor-version":[{"id":342695,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts\/207434\/revisions\/342695"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/media\/207435"}],"wp:attachment":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/media?parent=207434"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/categories?post=207434"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/tags?post=207434"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}