DEVELOPERS BLOG

Best Practices for Developing Enterprise Android Apps

afw_best_feature

Best Practices: Android for Work and BES12

When developing enterprise-focused Android apps, it can often feel overwhelming with the options available from different handset manufacturers, EMM solutions, SDKs, and deployment options.

What we’ll focus on today are the very basics, or best practices, for writing an Android app for the enterprise. While none of these features will guarantee a secure app, these concepts can be considered the sanity-checks and building blocks to securing your next Android application.

Policy-based Restrictions (System-level)

The first thing we can do as developers, is ensure that the device has some sort of security measure in place, aka a security policy, before granting access to our app data. To do this we can take advantage of any combination of pre-defined device policies, which are organized into respective policy sets.

Android Policy Set Examples of Policy Constants/Methods
limit-password PASSWORD_QUALITY_COMPLEX
PASSWORD_QUALITY_ALPHABETIC
USES_POLICY_LIMIT_PASSWORD
watch-login USES_POLICY_WATCH_LOGIN
ACTION_SYSTEM_UPDATE_POLICY_CHANGED
reset-password resetPassword()
getPasswordMaximumLength()
force-lock lockNow()
setMaximumTimeToLock()
wipe-data WIPE_EXTERNAL_STORAGE
WIPE_RESET_PROTECTION_DATA
wipeData()
expire-password getPasswordExpiration()
resetPassword()
isActivePasswordSufficient()
encrypted-storage ACTION_START_ENCRYPTION
ENCRYPTION_STATUS_ACTIVE
ENCRYPTION_STATUS_UNSUPPORTED
disable-camera setCameraDisabled()

For example, let’s say we wanted to enforce that the device password has at least a letter, a numerical digit and a special symbol. In this instance, we would leverage the PASSWORD_QUALITY_COMPLEX constant within the limit-password policy set.

Each policy set we use must be declared both within the res/xml/device_admin.xml and AndroidManifest.xml files, or a SecurityException will be thrown when referencing the undeclared policy set.

Within the DevicePolicyManager Class, you can reference the associated methods/constants with each specific policy.

After defining and declaring your policy above, you’ll want to be able to listen for any changes related to the granular policies you have declared. To do this we can add a Device Admin broadcast receiver to alert our app, which gives us an opportunity to erase any sensitive data and/or do any other administrative tasks within our app to prevent a security compromise. Don’t forget to register the receiver in the AndroidManifest.xml file as well.

In order for our defined policies to actually be enforced, we need the end-user to accept them by activating the administration of the device. The easiest way to accomplish this would be through an explicit Intent.

And finally, once we know that the end-user has activated the admin policy, we can invoke any necessary actions that may be required in order to ensure the device is in compliance (like setting a new password). Android is very proactive in redacting options that do not meet the standards outlined by the policy outline. Much like having the end-user activate the administration of the device, this is done most gracefully through explicit Intents.

If you’re interested in integrating policy-based restrictions within your app, feel free to reference the Enhancing Security with Device Management Policies Android guide, as well as the DeviceManagement sample app available here.

In addition, the always resourceful Android Device Administration guide can be referenced here.

Complying with Managed Profiles

The second thing we can do as developers of secure Android applications for the enterprise, is to ensure that our apps are able to function on devices with managed profiles. In an enterprise environment it’s safe to assume that there is some level of profile management taking place (perhaps multiple).

The first place where working with managed profiles can become awkward is with Intents, since the Android system prevents Intents from firing across profiles. When an Intent is fired, the first place it looks to be handled is within the profile it is running within. If an associated handler is not available within said profile, or it is not allowed by the profile admin, the app will likely fail.

To work around this scenario in the most graceful way to the end-user, would be to verify that the Intent can actually be resolved prior to starting an Activity. Particularly, the Intent.resolveActivity() method can be used to allow you to provide an elegant error message when null is returned.

Another scenario where working with managed profiles is difficult is when we want to share data, particularly across profiles. When working with multiple profiles, we cannot use a File URI (file://…) because the absolute filepath is not valid across different profiles. This means that regardless of an Intent handler being available, the file itself is not accessible. To get around this we can make use of a Content URI instead by using the FileProvider Class, which provides additional metadata pertaining to the file we’re looking to access, allowing us to share it between apps and profiles.

For further information on working with managed profiles, please feel free to reference the Ensuring Compatibility with Managed Profiles Android training guide, and the BasicManagedProfile sample app used to test compatability with manages profiles here.

About jamesdreherbb