diff --git a/docs/html/training/enterprise/app-compatibility.jd b/docs/html/training/enterprise/app-compatibility.jd new file mode 100644 index 0000000000000..1ae1ee362aa6a --- /dev/null +++ b/docs/html/training/enterprise/app-compatibility.jd @@ -0,0 +1,274 @@ +page.title=Ensuring Compatibility with Managed Profiles +@jd:body + +
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
+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.)
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).
+ +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);
+
+ }
+}
+
+
+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 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.
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:
+ +// Open File object from its file URI +File fileToShare = new File(fileUriToShare); + +Uri contentUriToShare = FileProvider.getUriForFile(getContext(), + "com.example.myapp.fileprovider", fileToShare);+ +
When you call the {@link
+android.support.v4.content.FileProvider#getUriForFile getUriForFile()} method,
+you must include the file provider's authority (in this example,
+"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.
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.
+ +--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).For example, to find the users on a device, you would run this command:
+ +$ adb shell pm list users
+UserInfo{0:Drew:13} running
+UserInfo{10:Work profile:30} running
+
+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:
+ +$ adb shell am start --user 10 \ +-n "com.example.myapp/com.example.myapp.testactivity" \ +-a android.intent.action.MAIN -c android.intent.category.LAUNCHERdiff --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. Policies