2016-05-27 Android Marsh Mellow Updates

Objective

Share knowledge on how to implement marshmallow updates in Android applications and impact of marshmallow in existing applications.

Presentation

Introduction:

Along with new features and capabilities, Android 6.0 (API level 23) includes a variety of system changes and API behavior changes.

If you have previously published an application for Android, be aware that these changes in the platform affect your application.

Requesting Permissions at Run Time

Beginning in Android 6.0 (API level 23), users grant permissions to applications while the application is running, not when they install the app. This approach streamlines the application install process, since the user does not need to grant permissions when they install or update the app. It also gives the user more control over the application’s functionality; for example, a user could choose to give a camera application access to the camera but not to the device location. The user can revoke the permissions at any time, by going to the application’s Settings screen.

System permissions are divided into two categories, normal and dangerous:

  • Normal permissions do not directly risk the user’s privacy. If your application lists a normal permission in its manifest, the system grants the permission automatically.
  • Dangerous permissions can give the application access to the user’s confidential data. If your application lists a normal permission in its manifest, the system grants the permission automatically. If you list a dangerous permission, the user has to explicitly give approval to your application.

Normal Permissions

Many permissions are designated as PROTECTION_NORMAL, which indicates that there’s no great risk to the user’s privacy or security in letting applications have those permissions.If an application declares in its manifest that it needs a normal permission, the system automatically grants the application that permission at install time. The system does not prompt the user to grant normal permissions, and users cannot revoke these permissions.

As of API level 23, the following permissions are classified as PROTECTION_NORMAL:

Dangerous permissions

All dangerous Android system permissions belong to permission groups. If the device is running Android 6.0 (API level 23) and the application’s targetSdkVersion is 23 or higher, the following system behavior applies when your application requests a dangerous permission:

If an application requests a dangerous permission listed in its manifest, and the application already has another dangerous permission in the same permission group, the system immediately grants the permission without any interaction with the user. For example, if an application had previously requested and been granted the READ_CONTACTS permission, and it then requests WRITE_CONTACTS, the system immediately grants that permission.

Dangerous permissions and permission groups.


Check For Permissions

If your application needs a dangerous permission, you must check whether you have that permission every time you perform an operation that requires that permission. The user is always free to revoke the permission, so even if the application used the camera yesterday, it can’t assume it still has that permission today.

To check if you have a permission, call the ContextCompat.checkSelfPermission() method. For example, this snippet shows how to check if the activity has permission to write to the calendar:

checkSelf Permission
// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.WRITE_CALENDAR);

If the application has the permission, the method returns PackageManager.PERMISSION_GRANTED, and the application can proceed with the operation. If the application does not have the permission, the method returns PERMISSION_DENIED, and the application has to explicitly ask the user for permission.

The following code checks if the application has permission to read the user’s contacts, and requests the permission if necessary:

checkSelf Permission
//  Here, thisActivity is the current activity
    if(ContextCompat.checkSelfPermission(thisActivity,         
            Manifest.permission.READ_CONTACTS)!=PackageManager.PERMISSION_GRANTED) {
    //Should we show an explanation?
          if(ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS))
            {
             //Show an expanation to the user *asynchronously* -- don't block
             //this thread waiting for the user's response! After the user
             //sees the explanation, try again to request the permission.
    }
    else {
        //No explanation needed, we can request the permission.
       
            ActivityCompat.requestPermissions(thisActivity,
                new
            String[]{Manifest.permission.READ_CONTACTS},
               
            MY_PERMISSIONS_REQUEST_READ_CONTACTS);
        //MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        //app-defined int constant. The callback method gets the
        //result of the request.
    }
}
 
Note: When your application calls requestPermissions(), the system shows a standard dialog box to the user. Your application cannot configure or alter that dialog box. If you need to provide any information or explanation to the user, you should do that before you call requestPermissions(), as described in Explain why the application needs permissions.

Handle the permissions request response

When your application requests permissions, the system presents a dialog box to the user. When the user responds, the system invokes your application’s onRequestPermissionsResult() method, passing it the user response. Your application has to override that method to find out whether the permission was granted. The callback is passed the same request code you passed to requestPermissions(). For example, if an application requests READ_CONTACTS access it might have the following callback method:

permissions request response
@Override
public
void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
 switch(requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            //If request is cancelled, the result arrays are empty.
            if(grantResults.length > 0&&grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //permission was granted, yay! Do the
                //contacts-related task you need to do.
            }
    else {
                //permission denied, boo! Disable the
                //functionality that depends on this permission.
            }
            return;
        }
        //other 'case' lines to check for other
        //permissions this  application might request
    }
}

The dialog box shown by the system describes the permission group your application needs access to; it does not list the specific permission. For example, if you request the READ_CONTACTS permission, the system dialog box just says your application needs access to the device’s contacts. The user only needs to grant permission once for each permission group. If your application requests any other permissions in that group (that are listed in your application manifest), the system automatically grants them. When you request the permission, the system calls your onRequestPermissionsResult() callback method and passes PERMISSION_GRANTED, the same way it would if the user had explicitly granted your request through the system dialog box.

Optimizing for Doze and application Standby

Starting from Android 6.0 (API level 23), Android introduces two power-saving features that extend battery life for users by managing how applications behave when a device is not connected to a power source.

Doze :

Doze reduces battery consumption by deferring background CPU and network activity for applications when the device is unused for long periods of time.

As soon as you upgrade to Marshmallow or get a new device running it, you’ll immediately notice the impact of Doze mode. This feature is active by default, and Google does not allow OEMs to modify the way it works. When you leave your device sitting unplugged with the screen off for about 30 minutes, it shifts into Doze mode to prevent the battery from being drained.

Doze restrictions

The following restrictions apply to your applications while in Doze:

application Standby

application Standby allows the system to determine that an application is idle when the user is not actively using it. The system makes this determination when the user does not touch the application for a certain period of time.

An application on Android 6.0 defaults to Standby unless one of three things has happened in the last several days—the application has a foreground process active, you explicitly launch the app, or the application produces a notification.

An application that goes into Standby loses all network access and all its background sync jobs are suspended. These restrictions are temporarily lifted when your phone is plugged in and for a few minutes every day or two. This gives suspended applications a chance to run any pending sync jobs, but they won’t be allowed to continue running. A high-priority push notification will also be able to wake an application from Standby for a short time.

Taking Control

Both the above systems work on their own when you use a device with Android 6.0 Marshmallow, but you can meddle with things if you like. Doze is accessible in the settings under Battery > Overflow > Battery optimization. Here, you’ll see a list of applications that are exempt from Doze, which will probably just be Google Play Services and a few device-specific features. You can’t force these into Doze mode, but you can exempt other applications from Doze.

To disable Doze, use the drop-down at the top to switch over to the list of all applications. From there, you can pick any of them to exempt from Doze mode (Don’t optimize). You really only want to do this is an application isn’t working correctly in Doze. It could affect battery life negatively.

Testing with Doze and application Standby

To ensure a great experience for your users, you should test your application fully in Doze and application Standby.

Testing your application with Doze

You can test Doze mode by following these steps:

  1. Configure a hardware device or virtual device with an Android 6.0 (API level 23) or higher system image.
  2. Connect the device to your development machine and install your app.
  3. Run your application and leave it active.
  4. Shut off the device screen. (The application remains active.)
  5. Force the system to cycle through Doze modes by running the following commands:
    $ adb shell dumpsys battery unplug
    $ adb shell dumpsys deviceidle step

    You may need to run the second command more than once. Repeat it until the device state changes to idle.

  6. Observe the behavior of your application after you reactivate the device. Make sure the application recovers gracefully when the device exits Doze.

Testing your application with application Standby

To test the application Standby mode with your app:

  1. Configure a hardware device or virtual device with an Android 6.0 (API level 23) or higher system image.
  2. Connect the device to your development machine and install your app.
  3. Run your application and leave it active.
  4. Force the application into application Standby mode by running the following commands:
    $ adb shell dumpsys battery unplug
    $ adb shell am set-inactive <packageName> true
  5. Simulate waking your application using the following commands:
    $ adb shell am set-inactive <packageName> false
    $ adb shell am get-inactive <packageName>
  6. Observe the behavior of your application after waking it. Make sure the application recovers gracefully from standby mode. In particular, you should check if your application’s Notifications and background jobs continue to function as expected.

Access to Hardware Identifier

To provide users with greater data protection, starting in this release, Android removes programmatic access to the device’s local hardware identifier for applications using the Wi-Fi and Bluetooth APIs. The WifiInfo.getMacAddress() and the BluetoothAdapter.getAddress() methods now return a constant value of 02:00:00:00:00:00.

To access the hardware identifiers of nearby external devices via Bluetooth and Wi-Fi scans, your application must now have the ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions:

Note: When a device running Android 6.0 (API level 23) initiates a background Wi-Fi or Bluetooth scan, the operation is visible to external devices as originating from a randomized MAC address.

Apache HTTP Client Removal

Android 6.0 release removes support for the Apache HTTP client. If your application is using this client and targets Android 2.3 (API level 9) or higher, use the HttpURLConnection class instead. This API is more efficient because it reduces network use through transparent compression and response caching, and minimizes power consumption. To continue using the Apache HTTP APIs, you must first declare the following compile-time dependency in your build.gradle file:

Leave a Reply

Your email address will not be published. Required fields are marked *