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