1page.title=Set up Managed Profiles
2page.metaDescription=Learn how to make sure your apps operate smoothly in a corporate environment by following some best practices.
3page.image=images/work/cards/briefcase_600px.png
4
5@jd:body
6
7<div id="qv-wrapper">
8  <div id="qv">
9    <h2>In this document</h2>
10    <ol>
11      <li><a href="#prevent_failed_intents">Prevent Failed Intents</a></li>
12      <li><a href="#sharing_files">Share Files Across Profiles</a></li>
13      <li><a href="#testing_apps">
14        Test your App for Compatibility with Managed Profiles</a></li>
15    </ol>
16  </div>
17</div>
18
19<p>The Android platform allows devices to have
20<a href="{@docRoot}about/versions/android-5.0.html#Enterprise">managed
21profiles</a>. A managed profile is controlled by an administrator, and the
22functionality available to it is set separately from the functionality of the
23user's primary profile. This approach lets enterprises control the environment
24where company-specific apps and data are running on a user's device, while still
25letting users use their personal apps and profiles.</p>
26
27<p>This lesson shows you how to modify your application so it functions
28reliably on a device with managed profiles. You don't need to do anything
29besides the ordinary app-development best practices. However, some of these best
30practices become especially important on devices with managed profiles. This
31document highlights the issues you need to be aware of.</p>
32
33<h2 id="overview">Overview</h2>
34
35<p>Users often want to use their personal devices in an enterprise setting. This
36situation can present enterprises with a dilemma. If the user can use their own
37device, the enterprise has to worry that confidential information (like employee
38emails and contacts) are on a device the enterprise does not control. </p>
39
40<p>To address this situation, Android 5.0 (API level 21) allows enterprises to
41set up <i>managed profiles</i>. If a device has a managed profile, the profile's
42settings are under the control of the enterprise administrator. The
43administrator can choose which apps are allowed for that profile, and can
44control just what device features are available to the profile.</p>
45
46<p>If a device has a managed profile, there are implications for apps
47running on the device, no matter which profile the app is running under:</p>
48
49<ul>
50
51<li>By default, most intents do not cross from one profile to the other. If an
52app running on profile fires an intent, there is no handler for the intent on
53that profile, and the intent is not allowed to cross to the other profile
54due to profile restrictions, the request fails and the app may shut down
55unexpectedly.</li>
56<li>The profile administrator can limit which system apps are available on the
57managed profile. This restriction can also result in there being no handler for
58some common intents on the managed profile.</li>
59<li>Since the managed and unmanaged profiles have separate storage areas, a
60file URI that is valid on one profile is not valid on the other. Any
61intent fired on one profile might be handled on the other (depending on profile
62settings), so it is not safe to attach file URIs to intents.</li>
63
64</ul>
65
66<h2 id="prevent_failed_intents">Prevent Failed Intents</h2>
67
68<p>On a device with a managed profile, there are restrictions on whether intents
69can cross from one profile to another.  In most cases, when an intent is fired
70off, it is handled on the same profile where it is fired. If there is no handler
71for the intent <em>on that profile</em>, the intent is not handled and the app
72that fired it may shut down unexpectedly&mdash;even if there's a handler for the
73intent on the other profile.</p>
74
75<p>The profile administrator can choose which intents are
76allowed to cross from one profile to another. Since the administrator makes
77this decision, there's no way for you
78to know in advance <em>which</em> intents are allowed to cross this boundary. The
79administrator sets this policy, and is free to change it at any time.</p>
80
81<p>Before your app starts an activity, you should verify that there is a
82suitable resolution. You
83can verify  that there is an acceptable resolution by calling {@link
84android.content.Intent#resolveActivity Intent.resolveActivity()}. If there is no
85way to resolve the intent, the method returns
86<code>null</code>. If the method returns non-null, there is at least one way to
87resolve the intent, and it is safe to fire off the intent. In this case, the
88intent could be resolvable either
89because there is a handler on the current profile, or because the intent is
90allowed to cross to a handler on the other profile. (For more information about
91resolving intents, see <a
92href="{@docRoot}guide/components/intents-common.html">Common Intents</a>.)</p>
93
94<p>For example, if your app needs to set timers,  it would need to check that
95there's a valid handler for the {@link
96android.provider.AlarmClock#ACTION_SET_TIMER} intent. If the app cannot resolve
97the intent, it should take an appropriate action (such as showing an error
98message).</p>
99
100<pre>public void startTimer(String message, int seconds) {
101
102    // Build the "set timer" intent
103    Intent timerIntent = new Intent(AlarmClock.ACTION_SET_TIMER)
104            .putExtra(AlarmClock.EXTRA_MESSAGE, message)
105            .putExtra(AlarmClock.EXTRA_LENGTH, seconds)
106            .putExtra(AlarmClock.EXTRA_SKIP_UI, true);
107
108    // Check if there's a handler for the intent
109    <strong>if (timerIntent.resolveActivity(getPackageManager()) == null)</strong> {
110
111        // Can't resolve the intent! Fail this operation cleanly
112        // (perhaps by showing an error message)
113
114    } else {
115        // Intent resolves, it's safe to fire it off
116        startActivity(timerIntent);
117
118    }
119}
120</pre>
121
122<h2 id="sharing_files">Share Files Across Profiles</h2>
123
124<p>Sometimes an app needs to provide other apps with access to its own files.
125For example, an image gallery app might want to share its images with image
126editors. There are two ways you would ordinarily share a file: with a <em>file
127URI</em> or a <em>content URI</em>.</p>
128
129<p>A file URI begins with the <code>file:</code> prefix, followed by the
130absolute path of the file on the device's storage. However, because the
131managed profile and the personal profile use separate storage areas, a file URI
132that is valid on one profile is not valid on the other. This situation
133means that if you
134attach a file URI to an intent, and the intent is handled on the other profile,
135the handler is not able to access the file.</p>
136
137<p>Instead, you should share files with <em>content URIs</em>. Content URIs
138identify the file in a more secure, shareable fashion. The content URI contains
139the file path, but also the authority that provides the file, and an ID number
140identifying the file. You can generate a content ID for any file by using a
141{@link android.support.v4.content.FileProvider}. You can then share that content
142ID with other apps (even on the other profile). The recipient can use the
143content ID to get access to the actual file.</p>
144
145<p>For example, here's how you would get the content URI for a specific file
146URI:</p>
147
148<pre>// Open File object from its file URI
149File fileToShare = new File(<em>fileUriToShare</em>);
150
151Uri contentUriToShare = FileProvider.getUriForFile(getContext(),
152        <em>"com.example.myapp.fileprovider"</em>, fileToShare);</pre>
153
154<p>When you call the {@link
155android.support.v4.content.FileProvider#getUriForFile getUriForFile()} method,
156you must include the file provider's authority (in this example,
157<code>"com.example.myapp.fileprovider"</code>), which is specified in the
158<a href="{@docRoot}guide/topics/manifest/provider-element.html"><code>&lt;provider&gt;</code></a>
159element of your app manifest.
160For more information about sharing files with content URIs, see
161<a href="{@docRoot}training/secure-file-sharing/index.html">Sharing
162Files</a>.</p>
163
164<h2 id="testing_apps">Test your App for Compatibility with Managed Profiles</h2>
165
166<p>You should test your app in a managed-profile environment to
167catch problems that would cause your app to fail on a device with
168managed profiles. In particular, testing on a managed-profile device is a good
169way to make sure that your app handles intents properly: not firing intents that
170can't be handled, not attaching URIs that don't work cross-profile, and so
171on.</p>
172
173<p>We have provided a sample app, <a
174href="{@docRoot}samples/BasicManagedProfile/index.html">BasicManagedProfile</a>,
175which you can use to set up a managed profile on an Android device that runs
176Android 5.0 (API level 21) and higher. This app offers you a simple way to test
177your app in a managed-profile environment. You can also use this app to
178configure the managed profile as follows:</p>
179
180<ul>
181
182  <li>Specify which default apps are available on the managed
183    profile</li>
184
185  <li>Configure which intents are allowed to cross from one profile to
186    the other</li>
187
188</ul>
189
190<p>If you manually install an app over a USB cable to a device which has a
191managed profile, the app is installed on both the managed and the unmanaged
192profile. Once you have installed the app, you can test the app under the
193following conditions:</p>
194
195<ul>
196
197  <li>If an intent would ordinarily be handled by a default app (for example,
198    the camera app), try disabling that default app on the managed profile, and
199    verify that the app handles this appropriately.</li>
200
201  <li>If you fire an intent expecting it to be handled by some other app, try
202enabling and disabling that   intent's permission to cross from one profile to
203another. Verify that the app behaves properly under both circumstances. If the
204intent is not allowed to cross between profiles, verify the app's behavior both
205when there is a suitable handler on the app's profile, and when there is not.
206For example, if your app fires a map-related intent, try each of the following
207scenarios:
208
209    <ul>
210
211<li>The device allows map intents to cross from one profile to the other, and
212there is a suitable handler on the other profile (the profile the app is not
213running on)</li>
214
215<li>The device does not allow map intents to cross between profiles, but there
216is a suitable handler on the app's profile</li>
217
218<li>The device does not allow map intents to cross between profiles, and there
219is no suitable handler for map intents on the device's profile</li>
220
221    </ul>
222  </li>
223
224<li>If you attach content to an intent, verify that the intent behaves properly
225both when it is handled on the app's profile, and when it crosses between
226profiles.</li>
227
228</ul>
229
230<h3 id="testing_tips">Testing on managed profiles: Tips and tricks</h3>
231
232<p>There are a few tricks that you may find helpful in testing on a
233managed-profile device.</p>
234
235<ul>
236
237<li>As noted,  when you side-load an app on a managed profile device, it is
238installed on both profiles. If you wish, you can delete the app from one profile
239and leave it on the other.</li>
240
241<li>Most of the activity manager commands available in the <a
242href="{@docRoot}tools/help/adb.html">Android Debug Bridge</a> (adb) shell
243support the <code>--user</code> flag, which lets you specify which user to run
244as. By specifying a user, you can choose whether to run as the unmanaged or
245managed profile. For
246more information, see <a href="{@docRoot}tools/help/shell.html#am">ADB
247Shell Commands</a>.</li>
248
249<li>To find the active users on a device, use the adb package manager's
250<code>list users</code> command. The first number in the output string is the
251user ID, which you can use with the <code>--user</code> flag.  For more
252information, see <a href="{@docRoot}tools/help/shell.html#pm">ADB Shell
253Commands</a>.</li>
254
255</ul>
256
257<p>For example, to find the users on a device, you would run this command:</p>
258
259<pre class="no-pretty-print">$ <strong>adb shell pm list users</strong>
260UserInfo{0:Drew:13} running
261UserInfo{10:Work profile:30} running</pre>
262
263<p>In this case, the unmanaged profile ("Drew") has the user ID 0, and the
264managed profile has the user  ID 10. To run an app in the work profile, you
265would use a command like this:</p>
266
267<pre class="no-pretty-print">$ adb shell am start --user 10 \
268-n "<em>com.example.myapp/com.example.myapp.testactivity</em>" \
269-a android.intent.action.MAIN -c android.intent.category.LAUNCHER</pre>
270