1page.title=Set up Managed Configurations 2page.metaDescription=Learn how to implement managed configurations that can be changed by other apps on the same device. 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="#define-configuration">Define Managed Configurations</a></li> 12 <li><a href="#check-configuration">Check Managed Configurations</a></li> 13 <li><a href="#listen-configuration">Listen for Managed Configuration Changes</a></li> 14 </ol> 15 </div> 16</div> 17 18<p> 19 If you are developing apps for the enterprise market, you may need 20 to satisfy particular requirements set by a company's policies. 21 Managed configurations, previously known as <em>application restrictions</em>, 22 allow the enterprise administrator to remotely specify settings for 23 apps. This capability is particularly useful for enterprise-approved 24 apps deployed to a managed profile. 25</p> 26 27<p>For example, an enterprise might require that approved apps allow the 28enterprise administrator to:</p> 29 30<ul> 31 <li>Whitelist or blacklist URLs for a web browser</li> 32 <li>Configure whether an app is allowed to sync content via cellular, or just 33 by Wi-Fi</li> 34 <li>Configure the app's email settings</li> 35</ul> 36 37<p> 38 This guide shows how to implement these configuration settings in your app. 39</p> 40 41<p class="note"> 42 <strong>Note:</strong> For historical reasons, these configuration settings are known as 43 <em>restrictions,</em> and are implemented with files and classes that use this 44 term (such as {@link android.content.RestrictionsManager}). However, these 45 restrictions can actually implement a wide range of configuration options, 46 not just restrictions on app functionality. 47</p> 48 49<h2 id="overview"> 50 Remote Configuration Overview 51</h2> 52 53<p> 54 Apps define the managed configuration options that can be remotely 55 set by an administrator. These are arbitrary settings that can be 56 changed by a managed configuration provider. If your app is running on an 57 enterprise device's managed profile, the enterprise administrator 58 can change your app's managed configuration. 59</p> 60 61<p> 62 The managed configurations provider is another app running on the same device. 63 This app is typically controlled by the enterprise administrator. The 64 enterprise administrator communicates configuration changes to the managed 65 configuration provider app. That app, in turn, changes the configurations on your app. 66</p> 67 68<p> 69 To provide externally managed configurations: 70</p> 71 72<ul> 73 <li>Declare the managed configurations in your app manifest. Doing 74 so allows the enterprise administrator to read the app's 75 configurations through Google Play APIs. 76 </li> 77 78 <li>Whenever the app resumes, use the {@link 79 android.content.RestrictionsManager} object to check the current 80 managed configurations, and change your app's UI and behavior to 81 conform with those configurations. 82 </li> 83 84 <li>Listen for the 85 {@link android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED 86 ACTION_APPLICATION_RESTRICTIONS_CHANGED} intent. When you receive this 87 broadcast, check the {@link android.content.RestrictionsManager} to see what 88 the current managed configurations are, and make any necessary changes to your 89 app's behavior. 90 </li> 91</ul> 92 93<h2 id="define-configuration"> 94 Define Managed Configurations 95</h2> 96 97<p> 98 Your app can support any managed configuration you want to define. You declare the 99 app's managed configurations in a <em>managed configurations file</em>, and declare the 100 configurations file in the manifest. Creating a configurations file allows other 101 apps to examine the managed configurations your app provides. Enterprise Mobility 102 Management (EMM) partners can read your app's configurations by using Google 103 Play APIs. 104</p> 105 106<p> 107 To define your app's remote configuration options, put the following element 108 in your manifest's 109 <a href="{@docRoot}guide/topics/manifest/application-element.html"> 110 <code><application></code></a> element: 111</p> 112 113<pre><meta-data android:name="android.content.APP_RESTRICTIONS" 114 android:resource="@xml/app_restrictions" /> 115</pre> 116 117<p> 118 Create a file named <code>app_restrictions.xml</code> in your app's 119 <code>res/xml</code> directory. The structure of that file is described in 120 the reference for {@link android.content.RestrictionsManager}. The file has a 121 single top-level <code><restrictions></code> element, which contains 122 one <code><restriction></code> child element for every configuration 123 option the app has. 124</p> 125 126<p class="note"> 127 <strong>Note:</strong> Do not create localized versions of the 128 managed configuration file. Your app is only allowed to have a 129 single managed configurations file, so configurations will be 130 consistent for your app in all locales. 131</p> 132 133<p> 134 In an enterprise environment, an EMM will typically use the managed 135 configuration schema to generate a remote console for IT 136 administrators, so the administrators can remotely configure your 137 application. 138</p> 139 140<p> 141 For example, suppose your app can be remotely configured to allow or forbid 142 it to download data over a cellular connection. Your app could have a 143 <code><restriction></code> element like this: 144</p> 145 146<pre> 147<?xml version="1.0" encoding="utf-8"?> 148<restrictions xmlns:android="http://schemas.android.com/apk/res/android" > 149 150 <restriction 151 android:key="downloadOnCellular" 152 android:title="App is allowed to download data via cellular" 153 android:restrictionType="bool" 154 android:description="If 'false', app can only download data via Wi-Fi" 155 android:defaultValue="true" /> 156 157</restrictions> 158</pre> 159 160<p> 161 The supported types for the <code>android:restrictionType</code> element are 162 documented in the reference for {@link android.content.RestrictionsManager}. 163</p> 164 165<p> 166 You use each configuration's <code>android:key</code> attribute to 167 read its value from a managed configuration bundle. For this reason, 168 each configuration must have a unique key string, and the string 169 <em>cannot</em> be localized. It must be specified with a string literal. 170</p> 171 172<p class="note"> 173 <strong>Note:</strong> In a production app, <code>android:title</code> and 174 <code>android:description</code> should be drawn from a localized resource 175 file, as described in <a href= 176 "{@docRoot}guide/topics/resources/localization.html">Localizing with 177 Resources</a>. 178</p> 179 180<p> 181 The managed configuration provider can query the app to find details 182 on the app's available configurations, including their description 183 text. Configurations providers and enterprise administrators can 184 change your app's managed configurations at any time, even when the 185 app is not running. 186</p> 187 188<h2 id="check-configuration"> 189 Check Managed Configurations 190</h2> 191 192<p> 193 Your app is not automatically notified when other apps change its 194 configuration settings. Instead, you need to check what the managed 195 configurations are when your app starts or resumes, and listen for a 196 system intent to find out if the configurations change while your 197 app is running. 198</p> 199 200<p> 201 To find out the current configuration settings, your app uses a 202 {@link android.content.RestrictionsManager} object. Your app should 203 check for the current managed configurations at the following times: 204</p> 205 206<ul> 207 <li>When the app starts or resumes, in its 208 {@link android.app.Activity#onResume onResume()} method 209 </li> 210 211 <li>When the app is notified of a configuration change, as described in 212 <a href="#listen-configuration">Listen for Managed Configuration 213 Changes</a> 214 </li> 215</ul> 216 217<p> 218 To get a {@link android.content.RestrictionsManager} object, get the current 219 activity with {@link android.app.Fragment#getActivity getActivity()}, then 220 call that activity's {@link android.app.Activity#getSystemService 221 Activity.getSystemService()} method: 222</p> 223 224<pre>RestrictionsManager myRestrictionsMgr = 225 (RestrictionsManager) getActivity() 226 .getSystemService(Context.RESTRICTIONS_SERVICE);</pre> 227 228<p> 229 Once you have a {@link android.content.RestrictionsManager}, you can get the 230 current configuration settings by calling its 231 {@link android.content.RestrictionsManager#getApplicationRestrictions 232 getApplicationRestrictions()} method: 233</p> 234 235<pre>Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();</pre> 236 237<p class="note"> 238 <strong>Note:</strong> For convenience, you can also fetch the current 239 configurations with a {@link android.os.UserManager}, by calling 240 {@link android.os.UserManager#getApplicationRestrictions 241 UserManager.getApplicationRestrictions()}. This method behaves exactly the 242 same as {@link android.content.RestrictionsManager#getApplicationRestrictions 243 RestrictionsManager.getApplicationRestrictions()}. 244</p> 245 246<p> 247 The {@link android.content.RestrictionsManager#getApplicationRestrictions 248 getApplicationRestrictions()} method requires reading from data storage, so 249 it should be done sparingly. Do not call this method every time you need to 250 know the current configuration. Instead, you should call it once when your app 251 starts or resumes, and cache the fetched managed configurations bundle. Then listen 252 for the {@link android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED 253 ACTION_APPLICATION_RESTRICTIONS_CHANGED} intent to find out if the configuration 254 change while your app is active, as described in 255 <a href="#listen-configuration">Listen for Managed Configuration Changes</a>. 256</p> 257 258<h3 id="read-configurations"> 259 Reading and applying managed configurations 260</h3> 261 262<p> 263 The {@link android.content.RestrictionsManager#getApplicationRestrictions 264 getApplicationRestrictions()} method returns a {@link android.os.Bundle} 265 containing a key-value pair for each configuration that has been set. The 266 values are all of type <code>Boolean</code>, <code>int</code>, 267 <code>String</code>, and <code>String[]</code>. Once you have the 268 managed configurations {@link android.os.Bundle}, you can check the current 269 configuration settings with the standard {@link android.os.Bundle} methods for 270 those data types, such as {@link android.os.Bundle#getBoolean getBoolean()} 271 or 272 {@link android.os.Bundle#getString getString()}. 273</p> 274 275<p class="note"> 276 <strong>Note:</strong> The managed configurations {@link android.os.Bundle} 277 contains one item for every configuration that has been explicitly set by a 278 managed configurations provider. However, you <em>cannot</em> assume that a 279 configuration will be present in the bundle just because you defined a default 280 value in the managed configurations XML file. 281</p> 282 283<p> 284 It is up to your app to take appropriate action based on the current 285 managed configuration settings. For example, if your app has a 286 configuration specifying whether it can download data over a 287 cellular connection, and you find that the configuration is set to 288 <code>false</code>, you would have to disable data download except when 289 the device has a Wi-Fi connection, as shown in the following example code: 290</p> 291 292<pre> 293boolean appCanUseCellular; 294 295if appRestrictions.containsKey("downloadOnCellular") { 296 appCanUseCellular = appRestrictions.getBoolean("downloadOnCellular"); 297} else { 298 // here, cellularDefault is a boolean set with the restriction's 299 // default value 300 appCanUseCellular = cellularDefault; 301} 302 303if (!appCanUseCellular) { 304 // ...turn off app's cellular-download functionality 305 // ...show appropriate notices to user 306}</pre> 307 308<h2 id="listen-configuration"> 309 Listen for Managed Configuration Changes 310</h2> 311 312<p> 313 Whenever an app's managed configurations are changed, the system fires the 314 {@link android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED 315 ACTION_APPLICATION_RESTRICTIONS_CHANGED} intent. Your app has to listen for 316 this intent so you can change the app's behavior when the configuration settings 317 change.</p> 318 319<p class="note"> 320 <strong>Note:</strong> The {@link 321 android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED 322 ACTION_APPLICATION_RESTRICTIONS_CHANGED} intent is sent only to listeners 323 that are dynamically registered, <em>not</em> to listeners that are declared 324 in the app manifest. 325</p> 326<p> 327 The following code shows how to dynamically register a broadcast receiver for 328 this intent: 329</p> 330 331<pre>IntentFilter restrictionsFilter = 332 new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED); 333 334BroadcastReceiver restrictionsReceiver = new BroadcastReceiver() { 335 @Override public void onReceive(Context context, Intent intent) { 336 337 // Get the current configuration bundle 338 Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions(); 339 340 // Check current configuration settings, change your app's UI and 341 // functionality as necessary. 342 } 343}; 344 345registerReceiver(restrictionsReceiver, restrictionsFilter); 346</pre> 347<p class="note"> 348 <strong>Note:</strong> Ordinarily, your app does not need to be notified 349 about configuration changes when it is paused. Instead, you should unregister 350 your broadcast receiver when the app is paused. When the app resumes, you 351 first check for the current managed configurations (as discussed in 352 <a href="#check-configuration">Check Managed Configurations</a>), then register 353 your broadcast receiver to make sure you're notified about configuration changes 354 that happen while the app is active. 355</p> 356