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