{"id":33040,"date":"2016-03-03T17:43:07","date_gmt":"2016-03-03T12:13:07","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=33040"},"modified":"2016-04-17T18:05:18","modified_gmt":"2016-04-17T12:35:18","slug":"android-permission-system","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/android-permission-system\/","title":{"rendered":"Android Permission System And Case Study"},"content":{"rendered":"<p style=\"text-align: center\"><strong>How to work with Android Permission System in Android M<br \/>\n<\/strong><\/p>\n<p>To protect the android system and the user&#8217;s privacy, <a title=\"Android App Development Services\" href=\"http:\/\/www.tothenew.com\/mobile-android-application-development-services\">Android system<\/a> runs each application in a limited access sandbox. If the application wants to use resources or information outside of its sandbox, the application has to explicitly request permission. Depending on the type of permission the application requests, the system may grant the permission automatically, or the system may ask the user to grant the permission. Android depends on two types of permission to decide to grant or request permission, \u00a0Normal and Dangerous Permissions.<\/p>\n<p><strong>Declaring Permission:<\/strong><\/p>\n<p>You need to declare required permissions in Application manifest file.<br \/>\nDepending on the sensitiveness of the permission, the system might grant the permission automatically, or the device user might have to grant the request. For example, if your\u00a0application requests permission to turn on the device&#8217;s flashlight, the system grants that permission automatically. But if your\u00a0application needs to read the user&#8217;s contacts, the system asks the user to approve that permission. Depending on the platform version, the user grants the permission either when they install the\u00a0application (on Android 5.1 and lower) or while running the\u00a0application (on Android 6.0 and higher).<\/p>\n<p><strong>Add Permissions to Manifest:<\/strong><\/p>\n<p>To declare that your\u00a0application needs a permission, put a\u00a0&lt;uses-permission&gt;\u00a0element in your\u00a0application manifest file, as a child of the top-level\u00a0&lt;manifest&gt;\u00a0element. For example, an\u00a0application that needs to send SMS messages would have this line in the manifest:<\/p>\n<p>[code]<\/p>\n<p>&lt;manifest xmlns:android=&quot;http:\/\/schemas.android.com\/apk\/res\/android&quot;<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 package=&quot;com.example.ttnd&quot;&gt;<br \/>\n\u00a0 \u00a0 &lt;uses-permission android:name=&quot;android.permission.SEND_SMS&quot;\/&gt;<br \/>\n\u00a0 \u00a0<br \/>\n\u00a0 \u00a0 &lt;application &#8230;&gt;<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 &#8230;<br \/>\n\u00a0 \u00a0 &lt;\/application&gt;<br \/>\n&lt;\/manifest&gt;<br \/>\n  [\/code]<\/p>\n<p><strong>Requesting Permissions at Runtime:<\/strong><\/p>\n<p>The Beginning in Android 6.0 (API level 23), users grant permissions to\u00a0applications while the\u00a0application is running, not when they install the application. This approach streamlines the\u00a0application install process, since the user does not need to grant permissions when they install or update the application. It also gives the user more control over the application&#8217;s functionality; for example, a user could choose to give a camera\u00a0application access to the camera but not to the device location. The user can revoke the permissions at any time, by going to the application&#8217;s Settings screen.<\/p>\n<p>Android System permissions are divided into two categories, <strong>Normal<\/strong>\u00a0and <strong>Dangerous<\/strong> permission:<br \/>\nThe <strong>Normal<\/strong> permissions do not directly risk the user&#8217;s privacy. If your\u00a0application lists a normal permission in its manifest, the system grants the permission automatically. The <strong>Dangerous<\/strong> permissions can give the\u00a0application access to the user&#8217;s confidential data. If you list a dangerous permission, the user has to explicitly give approval to your application.<\/p>\n<ul>\n<li>If the device is running Android 5.1 or lower,\u00a0or\u00a0your application&#8217;s target SDK is 22 or lower: If you list a dangerous permission in your manifest, the user has to grant the permission when they install the application; if they do not grant the permission, the system does not install the\u00a0application at all.<\/li>\n<li>If the device is running Android 6.0 or higher,\u00a0and\u00a0your application&#8217;s target SDK is 23 or higher: The\u00a0application has to list the permissions in the manifest,\u00a0and\u00a0it must request each dangerous permission it needs while the\u00a0application is running. The user can grant or deny each permission, and the\u00a0application can continue to run with limited capabilities even if the user denies a permission request.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><strong>Checks for Permissions:<\/strong><\/p>\n<p>if your\u00a0application needs a dangerous permission, you must check whether you have that permission every time to perform an operation that requires the permission. The user is always free to deny the permission, so even if the\u00a0application used the camera yesterday, it can&#8217;t assume it still has that permission today.<\/p>\n<p>To check if you have a permission, call the\u00a0<strong>ContextCompat.checkSelfPermission()<\/strong>\u00a0method. For example, Code snippet\u00a0 below shows how to check if the activity has permission to write to the calendar:<\/p>\n<p>[code]<br \/>\n\/\/ Assume thisActivity is the current activity<br \/>\nint permissionCheck = ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR);<br \/>\n[\/code]<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: left\">If the\u00a0application has the permission, the method returns\u00a0<strong>PackageManager.PERMISSION_GRANTED<\/strong>, and the\u00a0application can proceed with the operation. If the\u00a0application does not have the permission, the method returns\u00a0 returns\u00a0<strong>PackageManager .PERMISSION_DENIED<\/strong>, and the\u00a0application has to explicitly ask the user for permission.<\/p>\n<p><strong>Request for Permission:<\/strong><\/p>\n<p>If your\u00a0application doesn&#8217;t already have the permission it needs, the\u00a0application must call <strong>requestPermissions()<\/strong> methods to request the appropriate permissions. Your\u00a0application passes the permissions it wants, and also an integer request code\u00a0that you specify to identify this permission request. This method functions asynchronously, it returns right away, and after the user responds to the dialog box, the system calls the application&#8217;s callback method with the results, passing the same request code that the\u00a0application passed to\u00a0<strong>requestPermissions()<\/strong>.<br \/>\nThere may be a situation, where the user deny the requested permission, that probably shows that the user doesn&#8217;t understand why the\u00a0application needs the permission to provide that functionality. In a situation like that, it&#8217;s probably a good idea to show an explanation.<br \/>\nSo when the user again interact with the feature that have been rejected by the user earlier, Android provides a utility method, <strong>shouldShowRequestPermissionRationale()<\/strong>. This method returns true\u00a0if the\u00a0application has been requested this permission previously and the user denied the request.<\/p>\n<p>If the user turned down the permission request in the past and chose the\u00a0Don&#8217;t ask again\u00a0option in the permission request system dialog, this method returns\u00a0false. The method also returns\u00a0false\u00a0if a device policy prohibits the\u00a0application from having that permission.<br \/>\nThe following code checks if the\u00a0application has permission to read the user&#8217;s contacts, and requests the permission if necessary:<\/p>\n<p>[code]<br \/>\n\/\/ Here, thisActivity is the current activity<br \/>\nif (ContextCompat.checkSelfPermission(thisActivity,<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Manifest.permission.READ_CONTACTS)<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 != PackageManager.PERMISSION_GRANTED) {<br \/>\n\u00a0 \u00a0 \/\/ Should we show an explanation?<br \/>\n\u00a0 \u00a0 if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Manifest.permission.READ_CONTACTS)) {<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \/\/ Show an expanation to the user *asynchronously* &#8212; don&#8217;t block<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \/\/ this thread waiting for the user&#8217;s response! After the user<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \/\/ sees the explanation, try again to request the permission.<br \/>\n\u00a0 \u00a0 } else {<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \/\/ No explanation needed, we can request the permission.<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 ActivityCompat.requestPermissions(thisActivity,<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 new String[]{Manifest.permission.READ_CONTACTS},<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 MY_PERMISSIONS_REQUEST_READ_CONTACTS);<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \/\/ MY_PERMISSIONS_REQUEST_READ_CONTACTS is an<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \/\/ app-defined int constant. The callback method gets the<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \/\/ result of the request.<br \/>\n\u00a0 \u00a0 }<br \/>\n}[\/code]<\/p>\n<p>When your application calls\u00a0<strong>requestPermissions()<\/strong>, the system shows a standard dialog box to the user. Your\u00a0application cannot\u00a0configure or alter that dialog box. If you need to provide any information or explanation to the user, you should do that before you call\u00a0<strong>requestPermissions()<\/strong>.<\/p>\n<p><strong>Handle the permissions request response:<\/strong><\/p>\n<p>When your\u00a0application requests permissions, the system shows a dialog box to the user. When the user responds, the system invokes your application&#8217;s\u00a0<strong>onRequestPermissionsResult()<\/strong>\u00a0method, passing it the user response. Your\u00a0application has to override that method. The callback is passed the same request code you passed to<strong>\u00a0requestPermissions()<\/strong>. For example, if an\u00a0application requests<strong>\u00a0READ_CONTACT<\/strong> access it might have the following callback method:<\/p>\n<p>[code]<br \/>\n@Override<br \/>\npublic void onRequestPermissionsResult(int requestCode,<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 String permissions[], int[] grantResults) {<br \/>\n\u00a0 \u00a0 switch (requestCode) {<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ If request is cancelled, the result arrays are empty.<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (grantResults.length &gt; 0<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &amp;&amp; grantResults[0] == PackageManager.PERMISSION_GRANTED) {<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ permission was granted<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ contacts-related task you need to do.<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else {<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ permission denied, Disable the<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ functionality that depends on this permission.<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return;<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 }<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \/\/ other &#8216;case&#8217; lines to check for other<br \/>\n\u00a0 \u00a0 \u00a0 \u00a0 \/\/ permissions this application might request<br \/>\n\u00a0 \u00a0 }<br \/>\n}<br \/>\n[\/code]<\/p>\n<p>The dialog box shown by the system describes the\u00a0permission group\u00a0your\u00a0application needs access to; it does not list the specific permission. For example, if you request the\u00a0<strong>READ_CONTACTS<\/strong>\u00a0permission, the system dialog box just says your\u00a0application needs access to the device&#8217;s contacts. The user only needs to grant permission once for each permission group. If your\u00a0application requests any other permissions in that group (that are listed in your\u00a0application manifest), the system automatically grants them. When you request the permission, the system calls your <strong>onRequestPermissionsResult()<\/strong>\u00a0callback method and passes\u00a0<strong>PERMISSION_GRANTED<\/strong>, the same way it would if the user had explicitly granted your request through the system dialog box.<\/p>\n<p><strong>How Android system ask for Permission:<\/strong><\/p>\n<p>Here is a flow diagram that represent the general flow of events that will happen when you need to use a feature that requires a permission.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-33053 aligncenter\" src=\"\/blog\/wp-ttn-blog\/uploads\/2016\/03\/permissions.png\" alt=\"permissions\" width=\"600\" height=\"422\" \/><\/p>\n<p>We can check if a permission has been previously granted by calling\u00a0<strong>checkSelfPermission<\/strong>\u00a0before using the particular feature that will require that permission. This method returns an\u00a0int\u00a0value based on whether that permission is granted<br \/>\nor not.<\/p>\n<p>If the value of int is equal to <strong>PackageManager.PERMISSION_GRANTED<\/strong> that means you can continue as expected, Otherwise You have to request for the permission to grant using RequestPermission. You just need to pass a integer request code and String permission array.<\/p>\n<p>Here is the code snippet:<\/p>\n<p>[code]<\/p>\n<p>int hasLocationPermission = checkSelfPermission( Manifest.permission.ACCESS_FINE_LOCATION );<br \/>\nint hasSMSPermission = checkSelfPermission( Manifest.permission.SEND_SMS );<\/p>\n<p>List&lt;String&gt; permissions = new ArrayList&lt;String&gt;();<br \/>\nif( hasLocationPermission != PackageManager.PERMISSION_GRANTED ) {<br \/>\n\u00a0\u00a0\u00a0\u00a0permissions.add( Manifest.permission.ACCESS_FINE_LOCATION );<br \/>\n}<br \/>\n\u00a0<br \/>\nif( hasSMSPermission != PackageManager.PERMISSION_GRANTED ) {<br \/>\n\u00a0\u00a0\u00a0\u00a0permissions.add( Manifest.permission.SEND_SMS );<br \/>\n}<br \/>\n\u00a0<br \/>\nif( !permissions.isEmpty() ) {<br \/>\n\u00a0\u00a0\u00a0\u00a0requestPermissions( permissions.toArray( new String[permissions.size()] ), REQUEST_CODE_SOME_FEATURES_PERMISSIONS );<br \/>\n}<br \/>\n[\/code]<\/p>\n<p>when <strong>requestPermissions<\/strong>\u00a0is called, a dialog is presented to the user for each permission group that your application is asking permission for. It is best practice to only request permissions as needed, rather than in bulk when your user first starts the application.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-33055\" src=\"\/blog\/wp-ttn-blog\/uploads\/2016\/03\/allowdialog.png\" alt=\"allowdialog\" width=\"600\" height=\"148\" \/><\/p>\n<p>After interacting with dialog, <strong>onRequestPermissionsResult<\/strong>\u00a0is called and can be accessed in your\u00a0Activity.<\/p>\n<p>Code snippets will show, \u00a0weather a permission has been granted or denied. If the user denied the required permission than you should disable the affected feature and let the user know about that.<\/p>\n<p>[code]<\/p>\n<p>@Override<br \/>\npublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {<br \/>\n\u00a0\u00a0\u00a0\u00a0switch ( requestCode ) {<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case REQUEST_CODE_SOME_FEATURES_PERMISSIONS: {<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for( int i = 0; i &lt; permissions.length; i++ ) {<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if( grantResults[i] == PackageManager.PERMISSION_GRANTED ) {<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Log.d( &quot;Permissions&quot;, &quot;Permission Granted: &quot; + permissions[i] );<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} else if( grantResults[i] == PackageManager.PERMISSION_DENIED ) {<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Log.d( &quot;Permissions&quot;, &quot;Permission Denied: &quot; + permissions[i] );<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0break;<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0default: {<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0super.onRequestPermissionsResult(requestCode, permissions, grantResults);<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<br \/>\n\u00a0\u00a0\u00a0\u00a0}<br \/>\n}[\/code]<\/p>\n<p>I also prepared a presentation on Android Permission System, You can check it out <a title=\"Presentation Link\" href=\"http:\/\/www.slideshare.net\/ShivangGoel1\/android-permission-system-59111951\">here<\/a>.<\/p>\n<p><strong>Case Study:<\/strong><\/p>\n<p>I was doing some research work on android permission system and I found some surprising results with Android M device. I am trying to share it with this case study. Please read the below points thoroughly.<\/p>\n<ul>\n<li>When I set the targetSDKVersion to 23, The application was crashed in Android M device, due to permission denied, Because I did not handle the permission request as pr Android M guide lines.<\/li>\n<li>But when I changed the targetSDKVersion to 21 (or less than 23), then the application was working fine in Android M device. When I denied the permission manually from application settings, in the application that build by\u00a0 targetSDKVersion 21, the application did not crash, but particular functionality was not working.<\/li>\n<li>For instance: I was reading contact from Android M device, I build the application with targetSDKVersion 23, I did not handle the permission request (READ_CONTACT) for android M as android guidelines. The application was crashed, due to permission denied. When I changed the targetSDKVersion to 21 (or less than 23), the application worked fine, the application was able to read contact. When I manually denied the READ_CONTACT permission, The application did not crash, but the application was unable to read contacts.<\/li>\n<\/ul>\n<p><strong>Conclusion<\/strong>: I think, the conclusion is, When we target the application to 23 that means, You have <a title=\"automated testing services\" href=\"http:\/\/www.tothenew.com\/testing\/automated-independent-manual-testing\">tested your application<\/a> till API level 23 (Android M), So android system would not take care of your application for API version 23 or less. But if you are targeting your application with API version 21 (or less than 23), that means android system will take care of your application above API version 21. So as conclusion targetSDKVersion=23 means you have tested your application till API level 23.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How to work with Android Permission System in Android M To protect the android system and the user&#8217;s privacy, Android system runs each application in a limited access sandbox. If the application wants to use resources or information outside of its sandbox, the application has to explicitly request permission. Depending on the type of permission [&hellip;]<\/p>\n","protected":false},"author":892,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":9},"categories":[518,1],"tags":[4845,3150],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/33040"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/892"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=33040"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/33040\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=33040"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=33040"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=33040"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}