Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Do Your Users Love Android Runtime Permissions?

Do Your Users Love Android Runtime Permissions?

http://oredev.org/2016/sessions/do-your-users-love-android-runtime-permissions

Android 6.0 Marshmallow brings runtime permissions to users.
Marshmallow MR1 and N have subtle changes, too.
Are you targeting API level 23 or 24 yet?
What changes affect developers? Learn about the basics as well as the edge cases of requesting permissions. The new permission model has opened up a great opportunity for developers, as users do not have to agree to all permissions up front. See how runtime permissions can build trust with your users!

Eric Cochran

November 11, 2016
Tweet

More Decks by Eric Cochran

Other Decks in Programming

Transcript

  1. 2 9 Permission groups • CALENDAR • READ_CALENDAR • WRITE_CALENDAR

    • CAMERA • CAMERA • CONTACTS • READ_CONTACTS • WRITE_CONTACTS • GET_ACCOUNTS • STORAGE • READ_EXTERNAL_STORAGE • WRITE_EXTERNAL_STORAGE • LOCATION • ACCESS_COARSE_LOCATION • ACCESS_FINE_LOCATION • SENSORS • BODY_SENSORS • MICROPHONE • RECORD_AUDIO • PHONE • READ_PHONE_STATE • CALL_PHONE • READ_CALL_LOG • WRITE_CALL_LOG • ADD_VOICEMAIL • USE_SIP • PROCESS_OUTGOING_CALLS • SMS • READ_SMS • SEND_SMS • RECEIVE_SMS • RECEIVE_MMS • RECEIVE_WAP_PUSH
  2. 3 • NORMAL — FREE! • DANGEROUS — ASK AT

    RUNTIME • SIGNATURE — /SYSTEM/PRIV-APP • PREINSTALLED — /SYSTEM/APP • PRE23 — FREE IF TARGET < 23 • DEVELOPMENT • PRIVILEGED (AKA SYSTEM) • SIGNATUREORSYSTEM • INSTALLER • VERIFIER Protection Level
  3. 5 What’s New for My App? • TARGETING < 23

    • PERMISSIONS GRANTED BY DEFAULT • EMPTY DATA WHEN USERS EXPLICITLY DENY PERMISSIONS • PRE23 PROTECTION • WRITE_SETTINGS IS NO MORE • SYSTEM_ALERT_WINDOW IS GRANTABLE • 6.0: GET_ACCOUNTS NOT NEEDED FOR YOUR OWN ACCOUNT
  4. 6 <uses-permission android:name=“android.permission.SYSTEM_ALERT_WINDOW"/> if (!Settings.canDrawOverlays(this)) {
 Intent intent = new

    Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
 Uri.parse("package:" + activity.getPackageName())); List<ResolveInfo> handlers = context.getPackageManager().queryIntentActivities( appSettings, 0);
 if (handlers.isEmpty()) { // We can't go to Settings.
 return; }
 activity.startActivityForResult(intent, REQUEST_CODE_PERMISION_SYSTEM_ALERT_WINDOW);
 } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 if (requestCode == REQUEST_CODE_PERMISION_SYSTEM_ALERT_WINDOW) {
 if (Settings.canDrawOverlays(this)) {
 // Yay!
 } else {
 // Denied.
 }
 }
 }
  5. 7 <uses-permission android:name=“android.permission.ACCESS_NOTIFICATION_POLICY"/> if (notificationManager.getCurrentInterruptionFilter() != INTERRUPTION_FILTER_ALL) {
 Intent intent

    = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS); List<ResolveInfo> handlers = context.getPackageManager().queryIntentActivities( appSettings, 0);
 if (handlers.isEmpty()) { // We can't go to Settings.
 return; }
 activity.startActivity(intent);
 }
  6. 8 Runtime Permissions String permission = READ_CALENDAR;
 Context checker; //

    PERMISSION_DENIED or PERMISSION_GRANTED
 int result = checker.checkSelfPermission(permission);
  7. 9 Runtime Permissions • USE SUPPORT ANNOTATIONS! @RequiresPermission(READ_CALENDAR) • USE

    SUPPORT V4! String permission = READ_CALENDAR;
 Context checker = …;
 int result = PermissionChecker.checkSelfPermission(checker, permission);
  8. 11 Request String[] permissionsNeeded = { READ_CALENDAR };
 Activity requester;


    requester.requestPermissions(permissionsNeeded, requestCode); @Override public void onRequestPermissionsResult(int requestCode,
 @NonNull String[] permissions, @NonNull int[] grantResults) {
 // grantedResults full of PERMISSION_GRANTED and PERMISSION_DENIED.
 }
  9. 12 Denied: What Now? Intent appSettings = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:"

    + context.getPackageName()));
 List<ResolveInfo> handlers = context.getPackageManager().queryIntentActivities( appSettings, 0);
 if (handlers.isEmpty()) {
 // We can't go to Settings.
 return;
 }
 context.startActivity(appSettings);