From 713cd74e333ab9bb35cb7538611194d891e4eb53 Mon Sep 17 00:00:00 2001
From: Andrew Solovay The Android platform allows devices to have
+managed
+profiles. A managed profile is controlled by an administrator, and the
+functionality available to it is set separately from the functionality of the
+user's primary profile. This approach lets enterprises control the environment
+where company-specific apps and data are running on a user's device, while still
+letting users use their personal apps and profiles. This lesson shows you how to modify your application so it functions
+reliably on a device with managed profiles. You don't need to do anything
+besides the ordinary app-development best practices. However, some of these best
+practices become especially important on devices with managed profiles. This
+document highlights the issues you need to be aware of. Users often want to use their personal devices in an enterprise setting. This
+situation can present enterprises with a dilemma. If the user can use their own
+device, the enterprise has to worry that confidential information (like employee
+emails and contacts) are on a device the enterprise does not control. To address this situation, Android 5.0 (API level 21) allows enterprises to
+set up managed profiles. If a device has a managed profile, the profile's
+settings are under the control of the enterprise administrator. The
+administrator can choose which apps are allowed for that profile, and can
+control just what device features are available to the profile. If a device has a managed profile, there are implications for apps
+running on the device, no matter which profile the app is running under: On a device with a managed profile, there are restrictions on whether intents
+can cross from one profile to another. In most cases, when an intent is fired
+off, it is handled on the same profile where it is fired. If there is no handler
+for the intent on that profile, the intent is not handled and the app
+that fired it may shut down unexpectedly—even if there's a handler for the
+intent on the other profile. The profile administrator can choose which intents are
+allowed to cross from one profile to another. Since the administrator makes
+this decision, there's no way for you
+to know in advance which intents are allowed to cross this boundary. The
+administrator sets this policy, and is free to change it at any time. Before your app starts an activity, you should verify that there is a
+suitable resolution. You
+can verify that there is an acceptable resolution by calling {@link
+android.content.Intent#resolveActivity Intent.resolveActivity()}. If there is no
+way to resolve the intent, the method returns
+ For example, if your app needs to set timers, it would need to check that
+there's a valid handler for the {@link
+android.provider.AlarmClock#ACTION_SET_TIMER} intent. If the app cannot resolve
+the intent, it should take an appropriate action (such as showing an error
+message). Sometimes an app needs to provide other apps with access to its own files.
+For example, an image gallery app might want to share its images with image
+editors. There are two ways you would ordinarily share a file: with a file
+URI or a content URI. A file URI begins with the Instead, you should share files with content URIs. Content URIs
+identify the file in a more secure, shareable fashion. The content URI contains
+the file path, but also the authority that provides the file, and an ID number
+identifying the file. You can generate a content ID for any file by using a
+{@link android.support.v4.content.FileProvider}. You can then share that content
+ID with other apps (even on the other profile). The recipient can use the
+content ID to get access to the actual file. For example, here's how you would get the content URI for a specific file
+URI: When you call the {@link
+android.support.v4.content.FileProvider#getUriForFile getUriForFile()} method,
+you must include the file provider's authority (in this example,
+ You should test your app in a managed-profile environment to
+catch problems that would cause your app to fail on a device with
+managed profiles. In particular, testing on a managed-profile device is a good
+way to make sure that your app handles intents properly: not firing intents that
+can't be handled, not attaching URIs that don't work cross-profile, and so
+on. We have provided a sample app, BasicManagedProfile,
+which you can use to set up a managed profile on an Android device that runs
+Android 5.0 (API level 21) and higher. This app offers you a simple way to test
+your app in a managed-profile environment. You can also use this app to
+configure the managed profile as follows: If you manually install an app over a USB cable to a device which has a
+managed profile, the app is installed on both the managed and the unmanaged
+profile. Once you have installed the app, you can test the app under the
+following conditions: There are a few tricks that you may find helpful in testing on a
+managed-profile device. For example, to find the users on a device, you would run this command: In this case, the unmanaged profile ("Drew") has the user ID 0, and the
+managed profile has the user ID 10. To run an app in the work profile, you
+would use a command like this:This lesson teaches you to
+
+
+
+
+Resources
+
+
+Overview
+
+
+
+
+
+Prevent Failed Intents
+
+null. If the method returns non-null, there is at least one way to
+resolve the intent, and it is safe to fire off the intent. In this case, the
+intent could be resolvable either
+because there is a handler on the current profile, or because the intent is
+allowed to cross to a handler on the other profile. (For more information about
+resolving intents, see Common Intents.)public void startTimer(String message, int seconds) {
+
+ // Build the "set timer" intent
+ Intent timerIntent = new Intent(AlarmClock.ACTION_SET_TIMER)
+ .putExtra(AlarmClock.EXTRA_MESSAGE, message)
+ .putExtra(AlarmClock.EXTRA_LENGTH, seconds)
+ .putExtra(AlarmClock.EXTRA_SKIP_UI, true);
+
+ // Check if there's a handler for the intent
+ if (timerIntent.resolveActivity(getPackageManager()) == null) {
+
+ // Can't resolve the intent! Fail this operation cleanly
+ // (perhaps by showing an error message)
+
+ } else {
+ // Intent resolves, it's safe to fire it off
+ startActivity(timerIntent);
+
+ }
+}
+
+
+Share Files Across Profiles
+
+file: prefix, followed by the
+absolute path of the file on the device's storage. However, because the
+managed profile and the personal profile use separate storage areas, a file URI
+that is valid on one profile is not valid on the other. This situation
+means that if you
+attach a file URI to an intent, and the intent is handled on the other profile,
+the handler is not able to access the file.// Open File object from its file URI
+File fileToShare = new File(fileUriToShare);
+
+Uri contentUriToShare = FileProvider.getUriForFile(getContext(),
+ "com.example.myapp.fileprovider", fileToShare);
+
+"com.example.myapp.fileprovider"), which is specified in the
+<provider>
+element of your app manifest.
+For more information about sharing files with content URIs, see
+Sharing
+Files.Test your App for Compatibility with Managed Profiles
+
+
+
+
+
+
+
+
+
+
+
+
+ Testing on managed profiles: Tips and tricks
+
+
+
+
+
+--user flag, which lets you specify which user to run
+as. By specifying a user, you can choose whether to run as the unmanaged or
+managed profile. For
+more information, see Android Debug
+Bridge: Using activity manager (am).list users command. The first number in the output string is the
+user ID, which you can use with the --user flag. For more
+information, see Android Debug
+Bridge: Using package manager (pm).$ adb shell pm list users
+UserInfo{0:Drew:13} running
+UserInfo{10:Work profile:30} running
+
+$ adb shell am start --user 10 \
+-n "com.example.myapp/com.example.myapp.testactivity" \
+-a android.intent.action.MAIN -c android.intent.category.LAUNCHER
diff --git a/docs/html/training/enterprise/index.jd b/docs/html/training/enterprise/index.jd
index 2926f71a0e7c1..0ac68cc94631f 100644
--- a/docs/html/training/enterprise/index.jd
+++ b/docs/html/training/enterprise/index.jd
@@ -47,4 +47,12 @@ for the enterprise.