| page.title=Android for Work Developer Guide |
| page.tags="work", "android for work", "afw", "developer", "android" |
| page.metaDescription=Android for Work provides organizations with a secure, flexible, and unified Android mobility platform combining devices, applications, and management. |
| page.image=images/work/cards/android-studio_600px.png |
| |
| @jd:body |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>In this document</h2> |
| <ul> |
| <li><a href="#managed-profiles">Managed Profiles</a></li> |
| <li><a href="#managed-configurations">Implementing Managed Configurations</a></li> |
| <li><a href="#cosu">COSU Devices</a></li> |
| <li><a href="#sso">Set up Single Sign-on with Chrome Custom Tabs</a></li> |
| <li><a href="#testing">Test Your App</a></li> |
| </ul> |
| </div> |
| </div> |
| |
| <p> |
| Android for Work provides organizations with a secure, flexible, and |
| unified Android mobility platform—combining devices, applications, |
| and management. By default, Android apps are compatible with Android |
| for Work. However, there are additional features you can use to make |
| your Android app work best on a managed device: |
| </p> |
| |
| <ul> |
| <li> |
| <a href="#managed-profiles">Managed profile compatibility</a>—Modify your Android |
| app so it functions best on an Android device with a work profile. |
| </li> |
| <li> |
| <a href="#managed-configurations">Managed configurations</a>—Modify |
| your app to allow IT administrators the option to specify custom |
| settings for your apps. |
| </li> |
| <li> |
| <a href="#cosu">Corporate-owned, single-use (COSU)</a>—Optimize your |
| app so that it can be deployed on an Android device as a kiosk. |
| </li> |
| <li> |
| <a href="#sso">Single Sign-On (SSO)</a>—Simplify the sign-on process |
| for users signing in to different apps on their Android device |
| running Android for Work. |
| </li> |
| </ul> |
| |
| <h3>Prerequisites</h3> |
| |
| <ol> |
| <li>You’ve created an Android app.</li> |
| <li>You’re ready to modify your app so that it works best with |
| Android for Work.</li> |
| <li>Minimum version: Android 5.0 Lollipop recommended version: |
| Android 6.0 Marshmallow and later.</li> |
| </ol> |
| |
| <p> |
| <strong>Note:</strong> Android for Work functions natively on most |
| Android 5.0 devices; however, Android 6.0 and later offers |
| additional features for Android for Work, especially with regard to |
| COSU. |
| </p> |
| |
| <h2 id="managed-profiles">Manage Profiles</h2> |
| |
| <p> |
| You can manage a user’s business data and applications through a |
| work profile. A work profile is a managed corporate profile |
| associated with the primary user account on an Android device. A |
| work profile securely isolates work apps and data from personal apps |
| and data. This work profile is in a separate container from the |
| personal profile, which your user controls. These separate profiles |
| allow organizations to manage the business data they care about, but |
| leave everything else on a user’s device under the user’s control. |
| For a deep dive into best practices, see the |
| <a href="{@docRoot}work/managed-profiles.html">Set up Managed Profiles</a> |
| guide. For an overview of those best practices, see below. |
| </p> |
| |
| <h3>Key features of a managed profile</h3> |
| |
| <ul> |
| <li>Separate and secure profile</li> |
| <li>Google Play for Work for application distribution</li> |
| <li>Separate badged work applications</li> |
| <li>Profile-only management capabilities controlled by an administrator</li> |
| </ul> |
| |
| <h3>Managed profile benefits on Android 5.0+</h3> |
| |
| <ul> |
| <li>Full device encryption</li> |
| <li>One Android application package (APK) for both profiles when |
| there’s a personal profile and a work profile present on the device</li> |
| <li><a href="https://support.google.com/work/android/answer/6192678" |
| >Device policy controller</a> (DPC) is limited to the managed profile</li> |
| <li>Device administration via the |
| <a href="{@docRoot}reference/android/app/admin/DevicePolicyManager.html" |
| >DevicePolicyManager</a> class</li> |
| </ul> |
| |
| <h3>Considerations for managed profiles</h3> |
| <ul> |
| <li>The Android system prevents intents |
| <a href="{@docRoot}reference/android/app/admin/DevicePolicyManager.html#clearCrossProfileIntentFilters(android.content.ComponentName)" |
| >from crossing profiles</a> and IT administrators can |
| <a href="{@docRoot}reference/android/app/admin/DevicePolicyManager.html#enableSystemApp(android.content.ComponentName,%20java.lang.String)" |
| >enable or disable system apps</a>.</li> |
| <li>A file path (Uniform Resource Identifier [URI]) that’s valid on |
| one profile may not be valid on the other.</li> |
| </ul> |
| |
| <h3>Prevent intents from failing between profiles</h3> |
| <p> |
| It’s difficult to know which intents can cross between profiles, and |
| which ones are blocked. The only way to know for sure is by testing. |
| Before your app starts an activity, you should verify that the |
| request is resolved by calling |
| <a href="{@docRoot}reference/android/content/Intent.html#resolveActivity(android.content.pm.PackageManager)" |
| ><code>Intent.resolveActivity()</code></a>. |
| <ul> |
| <li>If it returns <code>null</code>, the request doesn’t resolve.</li> |
| <li>If it returns something, it shows that the intent resolves, |
| and it’s safe to send the intent.</li> |
| </ul> |
| </p> |
| <p> |
| <strong>Note</strong>: For detailed testing instructions, see |
| <a href="{@docRoot}work/managed-profiles.html#prevent_failed_intents" |
| >Prevent Failed Intents</a>. |
| </p> |
| |
| <h3>Share files across profiles</h3> |
| <p> |
| Some developers use URIs to mark file paths in Android. However, |
| with Android for Work, because there are separate profiles, we |
| recommend: |
| </p> |
| |
| <table> |
| <tr> |
| <td style="white-space:nowrap;"> |
| <strong>Use:</strong><br/> |
| Content URIs |
| </td> |
| <td> |
| <ul> |
| <li> |
| The <a href="{@docRoot}reference/android/content/ContentUris.html" |
| >content URIs</a> contain the authority, path, and ID for a |
| specific file. You can generate this using |
| <a href="{@docRoot}reference/android/support/v4/content/FileProvider.html" |
| >FileProvider</a> subclass. |
| <a href="{@docRoot}training/secure-file-sharing/index.html">Learn more</a> |
| </li> |
| <li> |
| Share and grant permissions to access the content URI using |
| an Intent. Permissions can only be passed across the profile |
| boundary using Intents. If you grant another app access rights |
| to your file using |
| <a href="{@docRoot}reference/android/content/Context.html#grantUriPermission(java.lang.String,%20android.net.Uri,%20int)" |
| ><code>Context.grantUriPermission()</code></a>, it only is granted for |
| that app in the same profile.</li> |
| </ul> |
| </td> |
| </tr> |
| <tr> |
| <td style="white-space:nowrap;"> |
| <strong>Don't use:</strong><br/> |
| File URI |
| </td> |
| <td> |
| <ul> |
| <li>Contains the absolute path of the file on the device’s |
| storage.</li> |
| <li>A file path URI that’s valid on one profile isn’t valid on |
| the other.</li> |
| <li>If you attach a file URI to an intent, a handler is unable |
| to access the file in another profile.</li> |
| </ul> |
| </td> |
| </tr> |
| </table> |
| |
| <p> |
| <strong>Next steps</strong>: Once your app supports managed |
| profiles, test it in a work profile. See |
| <a href="#testing">Test your app with Android for Work</a>. |
| </p> |
| |
| <h2 id="managed-configurations">Implementing Managed Configurations</h2> |
| |
| <p> |
| Managed configurations are a set of instructions that IT administrators |
| can use to manage their users’ mobile devices in a specific way. |
| These instructions are universal and work across any EMM, allowing |
| administrators to remotely configure applications on their users’ |
| phones. |
| </p> |
| |
| <p> |
| If you’re developing apps for business or government, you may need |
| to satisfy your industry’s specific set of requirements. Using |
| managed configurations, the IT administrator can remotely specify |
| settings and enforce policies for their users’ Android apps; for |
| example: |
| </p> |
| |
| <ul> |
| <li>Configure if an app can sync data via cellular/3G, or only Wi-Fi</li> |
| <li>Whitelist or blacklist URLs on a web browser</li> |
| <li>Configure an app's email settings</li> |
| <li>Enable or disable printing</li> |
| <li>Manage bookmarks</li> |
| </ul> |
| |
| <h3>Best practices for implementing managed configurations</h3> |
| |
| <p> |
| The <a href="{@docRoot}work/managed-configurations.html">Set up Managed Configurations</a> |
| guide is the key source for information on how to build and deploy |
| managed configurations. After you’ve reviewed this documentation, see |
| recommendations below for additional guidance. |
| </p> |
| |
| <h4>When first launching the app</h4> |
| <p> |
| As soon as you launch an application, you can see if managed |
| configurations are already set for this app in <code>onStart()</code> or |
| <code>onResume()</code>. Additionally, you can find out if your |
| application is managed or unmanaged. For example, if |
| <a href="{@docRoot}reference/android/content/RestrictionsManager.html#getApplicationRestrictions()" |
| ><code>getApplicationRestrictions()</code></a> returns: |
| <ul> |
| <li><strong>A set of application-specific restrictions</strong>—You |
| can configure the managed configurations silently (without requiring |
| user input).</li> |
| <li><strong>An empty bundle</strong>—Your application acts like |
| it’s unmanaged (for example, how the app behaves in a personal |
| profile).</li> |
| <li><strong>A bundle with a single key value pair with |
| <a href="{@docRoot}reference/android/os/UserManager.html#KEY_RESTRICTIONS_PENDING" |
| ><code>KEY_RESTRICTIONS_PENDING</code></a> set to true</strong>—your |
| application is being managed, but the DPC isn’t configured |
| correctly. You should block this user from your app, and direct |
| them to their IT administrator.</li> |
| </ul> |
| </p> |
| |
| <h4>Listen for changes to managed configurations</h4> |
| <p> |
| IT administrators can change managed configurations and what |
| policies they want to enforce on their users at any time. Because of |
| this, we recommend you ensure that your app can accept new |
| restrictions for your managed configuration as follows: |
| </p> |
| |
| <ul> |
| <li><strong>Fetch restrictions on launch</strong>—Your app should |
| call <code>getApplicationRestrictions()</code> in <code>onStart()</code> |
| and <code>onResume()</code>, and compare against old restrictions |
| to see if changes are required.</li> |
| <li><strong>Listen while running</strong>—Dynamically register |
| <a href="{@docRoot}reference/android/content/Intent.html#ACTION_APPLICATION_RESTRICTIONS_CHANGED" |
| ><code>ACTION_APPLICATION_RESTRICTIONS_CHANGED</code></a> in your |
| running activities or services, after you’ve checked for new |
| restrictions. This intent is sent only to listeners that are |
| dynamically registered, and not to listeners declared in the app |
| manifest.</li> |
| <li><strong>Unregister while not running</strong>—In <code>onPause()</code>, |
| you should unregister for the broadcast of |
| <code>ACTION_APPLICATION_RESTRICTIONS_CHANGED</code>.</li> |
| </ul> |
| |
| <h2 id="cosu">COSU Devices</h2> |
| |
| <p> |
| Corporate-owned, single-use devices (COSU) are kiosk devices used |
| for a single purpose, such as digital signage displays, ticket |
| printing kiosks, or checkout registers. |
| </p> |
| <p> |
| When an Android device is configured as a COSU device, the user sees |
| an application locked to the screen with no Home or Recent Apps |
| buttons to escape the app. COSU can also be configured to show a set |
| of applications, such as a library kiosk with an app for the library |
| catalog and a web browser. |
| </p> |
| <p> |
| For instructions, see |
| <a href="{@docRoot}work/cosu.html">Set up Single-Purpose Devices</a>. |
| </p> |
| |
| <h2 id="sso">Set up Single Sign-on with Chrome Custom Tabs</h2> |
| |
| <p> |
| Enterprise users often have multiple apps on their device, and they |
| prefer to sign in once to access all of their work applications. |
| Typically, users sign in through a |
| <a href="https://developer.chrome.com/multidevice/webview/overview">WebView</a>; |
| however, there are a couple reasons why this isn’t ideal: |
| </p> |
| <ol> |
| <li> |
| Users often need to sign in multiple times with the same |
| credentials. The WebView solution often isn’t a true Single |
| Sign-On (SSO) experience. |
| </li> |
| <li> |
| There can be security risks, including malicious applications |
| inspecting cookies or injecting JavaScript® to access a user’s |
| credentials. Even trusted developers are at risk if they rely on |
| potentially malicious third-party SDKs. |
| </li> |
| </ol> |
| |
| <p> |
| A solution to both problems is to authenticate users using browser |
| Custom Tabs, instead of WebView. This ensures that authentication: |
| </p> |
| <ul> |
| <li> |
| Occurs in a secure context (the system browser) where the host app |
| cannot inspect contents. |
| </li> |
| <li> |
| Has a shared cookie state, ensuring the user has to sign in only |
| once. |
| </li> |
| </ul> |
| |
| <h3>Requirements</h3> |
| |
| <p> |
| <a href="https://developer.android.com/topic/libraries/support-library/features.html#custom-tabs" |
| >Custom Tabs</a> are supported back to API level 15 (Android 4.0.3). |
| To use Custom Tabs you need a supported browser, such as Chrome. |
| Chrome 45 and later implement this feature as |
| <a href="https://developer.chrome.com/multidevice/android/customtabs">Chrome Custom Tabs</a>. |
| </p> |
| |
| <h3>How do I implement SSO with Custom Tabs?</h3> |
| |
| <p> |
| Google has open sourced an OAuth client library that uses Custom |
| Tabs, contributing it to the OpenID Connect working group of the |
| OpenID Foundation. To set up Custom Tabs for SSO with the |
| AppAuth library, see the <a href="https://github.com/openid/AppAuth-Android" |
| >documentation and sample code on GitHub</a>, or try |
| <a href="https://codelabs.developers.google.com/codelabs/appauth-android-codelab/" |
| >the codelab</a>. |
| </p> |
| |
| <h2 id="testing">Test your App with Android for Work</h2> |
| |
| <p> |
| Once you’ve developed your app, you’ll want to test it in a work |
| profile—both as a profile owner and device owner. See the |
| instructions below. |
| </p> |
| |
| <h3>Use TestDPC to test your Android app</h3> |
| |
| <p> |
| TestDPC is a tool you can use to test your Android app in a variety |
| of Android for Work environments. You can configure it as a profile |
| owner or a device owner to launch management APIs on your device, |
| using one of these methods: |
| </p> |
| <ul> |
| <li>Download the source code for TestDPC from |
| <a href="https://github.com/googlesamples/android-testdpc">GitHub</a>.</li> |
| <li>Install TestDPC directly from |
| <a href="https://play.google.com/store/apps/details?id=com.afwsamples.testdpc" |
| >Google Play</a>.</li> |
| </ul> |
| <p> |
| For more information on how to configure TestDPC, see the |
| instructions below and the |
| <a href="https://github.com/googlesamples/android-testdpc">TestDPC User Guide</a>. |
| </p> |
| |
| <p> |
| <strong>REQUIRED</strong>: Your test Android device needs to run |
| Android 5.0 or later and be able to natively support Android for Work. |
| </p> |
| |
| <h3>Provision a profile owner</h3> |
| |
| <p> |
| To test your app in a work profile, you need to first provision a |
| profile owner on the TestDPC app: |
| </p> |
| |
| <ol> |
| <li>Launch the TestDPC app and click <strong>Set up profile</strong>.</li> |
| <li>When prompted, click <strong>Set up</strong>, ensuring the |
| TestDPC’s logo is highlighted on the screen.</li> |
| <li>If your device isn’t encrypted, you need to encrypt your device. |
| Follow the briefcase notification after reboot to continue |
| provisioning.<br/> |
| Once you’ve provisioned the profile owner correctly, badged |
| applications appear at the end of your app tray. Install your app |
| on the device and test to see how it runs in the work profile. |
| </li> |
| <li> |
| Install your app on the device and test to see how it runs in the |
| work profile. |
| </li> |
| </ol> |
| |
| <p class="caution"><b>Caution</b>: When running your app with Instant Run in |
| Android Studio, attempting to open your app with a Work profile or secondary |
| profile will crash your app. To use your app with the Work profile, we |
| recommend you create a new <a href="/studio/run/rundebugconfig.html">run |
| configuration</a> that includes the <code>--user <var>user_id</var></code> flag, |
| specifying the Work profile user ID. You can find the user ID by executing |
| <code>adb shell pm list users</code> from command line. For more information, |
| see the <a href="/studio/run/index.html#ir-work-profile">Instant Run |
| documentation</a>.</p> |
| |
| |
| <h3>Provision a device owner</h3> |
| |
| <p> |
| Testing your app as a device owner requires more steps than testing |
| as a profile owner. You first need to provision the device owner on |
| your test device using the |
| <a href="{@docRoot}samples/NfcProvisioning/index.html" |
| >NfcProvisioning sample app</a>. For complete instructions to |
| provision TestDPC in device owner mode using the NfcProvisioning |
| app, see the <a href="https://github.com/googlesamples/android-testdpc" |
| >TestDPC User Guide</a>. |
| </p> |
| |
| <ol> |
| <li>Download the <a href="{@docRoot}samples/NfcProvisioning/index.html" |
| >NfcProvisioning</a> app sample files to your development environment.</li> |
| <li>Unpack the project, open your shell, and <code>cd</code> to the project directory.</li> |
| <li>Add a file to the directory with the <code>local.properties</code> name |
| and the following content: |
| <pre>sdk.dir=/path/to/your/android/sdk</pre> |
| </li> |
| <li>While in the project directory, enter these commands to build the NfcProvisioning APK: |
| <pre>./gradlew init |
| ./gradlew build</pre> |
| The NfcProvisioning APK you need is now located in <code>./Application/build/outputs/apk</code>. |
| </li> |
| <li>Install the APK on your programmer device, which you can use to provision other devices.</li> |
| <li>Create a text file called <code>nfcprovisioning.txt</code> and |
| include the following information: |
| <pre>android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME=com.afwsamples.testdpc |
| android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION=https://testdpc-latest-apk.appspot.com |
| android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM=gJD2YwtOiWJHkSMkkIfLRlj-quNqG1fb6v100QmzM9w= |
| # note: checksum must be URL-safe |
| android.app.extra.PROVISIONING_LOCALE=en_US |
| android.app.extra.PROVISIONING_TIME_ZONE=America/New_York</pre> |
| <p> |
| <strong>Note:</strong> If you’re developing for Android 5.0 |
| Lollipop, see the instructions in the |
| <a href="https://github.com/googlesamples/android-testdpc" |
| >TestDPC User Guide</a>. |
| </p> |
| </li> |
| <li>Push that text file to your programmer device by entering: |
| <pre>adb push <path-to-nfcprovisioning.txt> /sdcard/</pre> |
| </li> |
| <li> |
| Ensure that the programmer device is connected to Wi-Fi on either |
| an unsecured or WPA2 secured network. |
| <p> |
| The NFC Provisioning app will automatically pass those Wi-Fi |
| credentials onto the target device. |
| </p> |
| </li> |
| <li>Open the NFC Provisioning app and ensure <code>com.google.android.testdpc</code> |
| is auto-populated.</li> |
| <li>Bump the devices to transfer the data.</li> |
| <li>Follow the onscreen instructions to set up your target device.</li> |
| <li>Once you’ve completed provisioning the device owner, you can test your app on that device. You |
| should specifically test how |
| <a href="{@docRoot}work/managed-configurations.html">managed configurations</a>, |
| <a href="{@docRoot}work/managed-profiles.html#sharing_files">URIs</a>, and |
| <a href="{@docRoot}work/managed-profiles.html#prevent_failed_intents">intents</a> |
| work on that device.</li> |
| </ol> |
| |
| <h3>End-to-end testing</h3> |
| |
| <p> |
| After you’ve finished testing your app in the environments above, |
| you’ll likely want to test your app in an end-to-end production |
| environment. This process includes the steps a customer needs to |
| take to deploy your app in their organization, including: |
| </p> |
| |
| <ul> |
| <li>App distribution through Play</li> |
| <li>Server-side managed configuration</li> |
| <li>Server-side profile policy control</li> |
| </ul> |
| |
| <p> |
| You need to access an EMM console to complete the end-to-end |
| testing. The easiest way to get one is to request a testing console |
| from your EMM. Once you have access, complete these tasks: |
| </p> |
| |
| <ol> |
| <li>Create a test version of your application with a |
| <a href="http://tools.android.com/tech-docs/new-build-system/applicationid-vs-packagename" |
| >new ApplicationId</a>.</li> |
| <li>Claim a <a href="https://support.google.com/work/android/answer/6174056" |
| >managed Google domain</a> and bind it to your EMM. If you |
| already have a testing domain that’s bound to an EMM, you may need |
| to unbind it to test it with your preferred EMM. Please consult your |
| EMM for the specific unbinding steps.</li> |
| <li><a href="https://support.google.com/a/answer/2494992" |
| >Publish your application to the private channel</a> for their |
| managed Google domain.</li> |
| <li>Use the EMM console and EMM application to: |
| <ol> |
| <li>Set up work devices.</li> |
| <li>Distribute your application.</li> |
| <li>Set managed configuration.</li> |
| <li>Set device policies.</li> |
| </ol> |
| </ol> |
| |
| <p> |
| This process will differ based on your EMM. Please consult your |
| EMM’s documentation for further details. Congrats! You’ve completed |
| these steps and verified that your app works well with Android for |
| Work. |
| </p> |
| |
| <p> |
| <a href="https://www.google.com/work/android/developers/applyDevHub/"> |
| <span class="dac-sprite dac-auto-chevron"></span> |
| Learn about the Android for Work DevHub. |
| </a> |
| </p> |