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