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>&lt;application&gt;</code></a> element:
111</p>
112
113<pre>&lt;meta-data android:name="android.content.APP_RESTRICTIONS"
114    android:resource="@xml/app_restrictions" /&gt;
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>&lt;restrictions&gt;</code> element, which contains
122  one <code>&lt;restriction&gt;</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>&lt;restriction&gt;</code> element like this:
144</p>
145
146<pre>
147&lt;?xml version="1.0" encoding="utf-8"?&gt;
148&lt;restrictions xmlns:android="http://schemas.android.com/apk/res/android" &gt;
149
150  &lt;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" /&gt;
156
157&lt;/restrictions&gt;
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  &#64;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