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—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><provider></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