{"id":405,"date":"2017-05-23T18:32:22","date_gmt":"2017-05-23T23:32:22","guid":{"rendered":"http:\/\/jebware.com\/blog\/?p=405"},"modified":"2017-12-13T10:23:04","modified_gmt":"2017-12-13T15:23:04","slug":"an-android-runtime-permissions-corner-case","status":"publish","type":"post","link":"https:\/\/jebware.com\/blog\/?p=405","title":{"rendered":"An Android runtime permissions corner case"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">I recently got curious about what happens to the runtime permissions state when the user revokes or grants a permission using the OS Settings app, rather than allowing or denying in the dialog prompt that an app can show to request permission. <\/span><\/p>\n<p><span style=\"font-weight: 400;\">For background, there are two parts to the state that an app can query at any time:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><a href=\"https:\/\/developer.android.com\/reference\/android\/support\/v4\/content\/ContextCompat.html#checkSelfPermission(android.content.Context, java.lang.String)\">checkSelfPermission()<\/a> returns <a href=\"https:\/\/developer.android.com\/reference\/android\/content\/pm\/PackageManager.html#PERMISSION_GRANTED\">PERMISSION_GRANTED<\/a> or <a href=\"https:\/\/developer.android.com\/reference\/android\/content\/pm\/PackageManager.html#PERMISSION_DENIED\">PERMISSION_DENIED<\/a>, meaning that your app either has that permission, or it doesn\u2019t.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><a href=\"https:\/\/developer.android.com\/reference\/android\/support\/v4\/app\/ActivityCompat.html#shouldShowRequestPermissionRationale(android.app.Activity, java.lang.String)\">shouldShowRequestPermissionRationale()<\/a> returns true or false. &nbsp;True means that the user has previously denied your request for this permission, so you should explain to the user why your app needs this permission. &nbsp;This returns false if the user denies the permission and checks the \u201cdon\u2019t ask again\u201d box.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">The question I got curious about was this: what happens when the user revokes a permission in the settings app? &nbsp;If they had previously chosen \u201cdon\u2019t ask again\u201d, but then later grant the permission in settings, then revoke the permission again, can you prompt for the permission?<\/span><\/p>\n<p><span style=\"font-weight: 400;\">I made a simple app to try it out, and came up with this for the possible states:<\/span><span style=\"font-weight: 400;\"><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/05\/permissions-flowchart.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-407\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/05\/permissions-flowchart.png\" alt=\"\" width=\"1042\" height=\"513\"><\/a><\/span>The answer is that if the user revokes a permission in settings, all of that history essentially goes away. &nbsp;You\u2019re left in the same state as if you had asked for permission and the user had denied it once, but you <em>can ask again<\/em>.<\/p>\n<p><span style=\"font-weight: 400;\">I realize this isn\u2019t the sort of thing that\u2019s going to happen in the course of normal usage; I don\u2019t expect most users to ever toggle those permissions from the settings app. &nbsp;But I think it\u2019s worth understanding how it works.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I recently got curious about what happens to the runtime permissions state when the user revokes or grants a permission using the OS Settings app, rather than allowing or denying in the dialog prompt that an app can show to request permission. For background, there are two parts to the state that an app can &hellip; <a href=\"https:\/\/jebware.com\/blog\/?p=405\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;An Android runtime permissions corner case&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false,"twitterCardType":"summary_large_image","cardImageID":0,"cardImage":"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2017\/05\/permissions-flowchart.png","cardTitle":"","cardDesc":"","cardImageAlt":"","cardPlayer":"","cardPlayerWidth":0,"cardPlayerHeight":0,"cardPlayerStream":"","cardPlayerCodec":""},"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/405"}],"collection":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=405"}],"version-history":[{"count":3,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/405\/revisions"}],"predecessor-version":[{"id":409,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/405\/revisions\/409"}],"wp:attachment":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=405"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=405"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=405"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}