summaryrefslogtreecommitdiffstats
path: root/docs/html/training/enterprise/app-restrictions.jd
blob: fc5dfcc9d0fdc94698e2e8543684f55d45d92071 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
page.title=Implementing App Restrictions
page.metaDescription=Learn how to implement app restrictions and configuration settings that can be changed by other apps on the same device.
@jd:body

<div id="tb-wrapper">
<div id="tb">

<h2>This lesson teaches you to</h2>
<ol>
 <li><a href="#define_restrictions">Define App Restrictions</a></li>
 <li><a href="#check_restrictions">Check App Restrictions</a></li>
 <li><a href="#listen">Listen for App Restriction Changes</a></li>
</ol>

<!-- related docs (NOT javadocs) -->
<h2>Resources</h2>
<ul>
  <li><a href="{@docRoot}samples/AppRestrictionSchema/index.html">AppRestrictionSchema</a>
    sample app</li>
  <li><a href="{@docRoot}samples/AppRestrictionEnforcer/index.html">AppRestrictionEnforcer</a>
    sample app</li>
</ul>

</div>
</div>

<p>If you are developing apps for the enterprise market, you may need to satisfy
particular requirements set by a company's policies. Application restrictions
allow the enterprise administrator to remotely specify settings for apps.
This capability is particularly useful for enterprise-approved apps deployed to
a managed profile.</p>

<p>For example, an enterprise might require that approved apps allow the
enterprise administrator to:</p>

<ul>
  <li>Whitelist or blacklist URLs for a web browser</li>
  <li>Configure whether an app is allowed to sync content via cellular, or just
    by Wi-Fi</li>
  <li>Configure the app's email settings</li>
</ul>

<p>
  This guide shows how to implement these configuration settings in your app.
</p>

<p class="note">
  <strong>Note:</strong> For historical reasons, these configuration settings are known as
  <em>restrictions,</em> and are implemented with files and classes that use this
  term (such as {@link android.content.RestrictionsManager}). However, these
  restrictions can actually implement a wide range of configuration options,
  not just restrictions on app functionality.
</p>

<h2 id="overview">
  Remote Configuration Overview
</h2>

<p>
  Apps define the restrictions and configuration options that can be remotely
  set by an administrator. These restrictions are
  arbitrary configuration settings that can be changed by a restrictions
  provider. If your app is running on an enterprise device's managed
  profile, the enterprise administrator can change your app's restrictions.
</p>

<p>
  The restrictions provider is another app running on the same device.
  This app is typically controlled by the enterprise administrator. The
  enterprise administrator communicates restriction changes to the restrictions
  provider app. That app, in turn, changes the restrictions on your app.
</p>

<p>
  To provide externally configurable restrictions:
</p>

<ul>
  <li>Declare the restrictions in your app manifest. Doing so allows the
  enterprise administrator to read the app's restrictions through Google
  Play APIs.
  </li>

  <li>Whenever the app resumes, use the {@link
    android.content.RestrictionsManager} object to check the current
    restrictions, and change your app's UI and behavior to conform with those
    restrictions.
  </li>

  <li>Listen for the
  {@link android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED
  ACTION_APPLICATION_RESTRICTIONS_CHANGED} intent. When you receive this
  broadcast, check the {@link android.content.RestrictionsManager} to see what
  the current restrictions are, and make any necessary changes to your app's
  behavior.
  </li>
</ul>

<h2 id="define_restrictions">
  Define App Restrictions
</h2>

<p>
  Your app can support any restrictions you want to define. You declare the
  app's restrictions in a <em>restrictions file</em>, and declare the
  restrictions file in the manifest. Creating a restrictions file allows other
  apps to examine the restrictions your app provides. Enterprise Mobility
  Management (EMM) partners can read your app's restrictions by using Google
  Play APIs.
</p>

<p>
  To define your app's remote configuration options, put the following element
  in your manifest's
  <a href="{@docRoot}guide/topics/manifest/application-element.html">
  <code>&lt;application&gt;</code></a> element:
</p>

<pre>&lt;meta-data android:name="android.content.APP_RESTRICTIONS"
    android:resource="@xml/app_restrictions" /&gt;
</pre>

<p>
  Create a file named <code>app_restrictions.xml</code> in your app's
  <code>res/xml</code> directory. The structure of that file is described in
  the reference for {@link android.content.RestrictionsManager}. The file has a
  single top-level <code>&lt;restrictions&gt;</code> element, which contains
  one <code>&lt;restriction&gt;</code> child element for every configuration
  option the app has.
</p>

<p class="note">
  <strong>Note:</strong> Do not create localized versions of the restrictions
  file. Your app is only allowed to have a single restrictions file,
  so restrictions will be consistent for your app in all locales.
</p>

<p>
  In an enterprise environment, an EMM will typically use the restrictions
  schema to generate a remote console for IT administrators, so the
  administrators can remotely configure your application.
</p>

<p>
  For example, suppose your app can be remotely configured to allow or forbid
  it to download data over a cellular connection. Your app could have a
  <code>&lt;restriction&gt;</code> element like this:
</p>

<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;restrictions xmlns:android="http://schemas.android.com/apk/res/android" &gt;

  &lt;restriction
    android:key="downloadOnCellular"
    android:title="App is allowed to download data via cellular"
    android:restrictionType="bool"
    android:description="If 'false', app can only download data via Wi-Fi"
    android:defaultValue="true" /&gt;

&lt;/restrictions&gt;
</pre>

<p>
  The supported types for the <code>android:restrictionType</code> element are
  documented in the reference for {@link android.content.RestrictionsManager}.
</p>

<p>
  You use each restriction's <code>android:key</code> attribute to read its
  value from a restrictions bundle. For this reason, each restriction must have
  a unique key string, and the string <em>cannot</em> be localized. It must be
  specified with a string literal.
</p>

<p class="note">
  <strong>Note:</strong> In a production app, <code>android:title</code> and
  <code>android:description</code> should be drawn from a localized resource
  file, as described in <a href=
  "{@docRoot}guide/topics/resources/localization.html">Localizing with
  Resources</a>.
</p>

<p>
  The restrictions provider can query the app to find details on the app's
  available restrictions, including their description text. Restrictions
  providers and enterprise administrators can change your app's restrictions at
  any time, even when the app is not running.
</p>

<h2 id="check_restrictions">
  Check App Restrictions
</h2>

<p>
  Your app is not automatically notified when other apps change its restriction
  settings. Instead, you need to check what the restrictions are when your app
  starts or resumes, and listen for a system intent to find out if the
  restrictions change while your app is running.
</p>

<p>
  To find out the current restriction settings, your app uses a {@link
  android.content.RestrictionsManager} object. Your app should check for the
  current restrictions at the following times:
</p>

<ul>
  <li>When the app starts or resumes, in its
  {@link android.app.Activity#onResume onResume()} method
  </li>

  <li>When the app is notified of a restriction change, as described in
    <a href="#listen">Listen for Device Configuration
    Changes</a>
  </li>
</ul>

<p>
  To get a {@link android.content.RestrictionsManager} object, get the current
  activity with {@link android.app.Fragment#getActivity getActivity()}, then
  call that activity's {@link android.app.Activity#getSystemService
  Activity.getSystemService()} method:
</p>

<pre>RestrictionsManager myRestrictionsMgr =
    (RestrictionsManager) getActivity()
        .getSystemService(Context.RESTRICTIONS_SERVICE);</pre>

<p>
  Once you have a {@link android.content.RestrictionsManager}, you can get the current restrictions
  settings by calling its
  {@link android.content.RestrictionsManager#getApplicationRestrictions
  getApplicationRestrictions()} method:
</p>

<pre>Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();</pre>

<p class="note">
  <strong>Note:</strong> For convenience, you can also fetch the current
  restrictions with a {@link android.os.UserManager}, by calling {@link
  android.os.UserManager#getApplicationRestrictions
  UserManager.getApplicationRestrictions()}. This method behaves exactly the
  same as {@link android.content.RestrictionsManager#getApplicationRestrictions
  RestrictionsManager.getApplicationRestrictions()}.
</p>

<p>
  The {@link android.content.RestrictionsManager#getApplicationRestrictions
  getApplicationRestrictions()} method requires reading from data storage, so
  it should be done sparingly. Do not call this method every time you need to
  know the current restrictions. Instead, you should call it once when your app
  starts or resumes, and cache the fetched restrictions bundle. Then listen for
  the {@link android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED
  ACTION_APPLICATION_RESTRICTIONS_CHANGED} intent to find out if restrictions
  change while your app is active, as described in <a href="#listen">Listen for
  Device Configuration Changes</a>.
</p>

<h3 id="read_restrictions">
  Reading and applying restrictions
</h3>

<p>
  The {@link android.content.RestrictionsManager#getApplicationRestrictions
  getApplicationRestrictions()} method returns a {@link android.os.Bundle}
  containing a key-value pair for each restriction that has been set. The
  values are all of type <code>Boolean</code>, <code>int</code>,
  <code>String</code>, and <code>String[]</code>. Once you have the
  restrictions {@link android.os.Bundle}, you can check the current
  restrictions settings with the standard {@link android.os.Bundle} methods for
  those data types, such as {@link android.os.Bundle#getBoolean getBoolean()}
  or
  {@link android.os.Bundle#getString getString()}.
</p>

<p class="note">
  <strong>Note:</strong> The restrictions {@link android.os.Bundle} contains
  one item for every restriction that has been explicitly set by a restrictions
  provider. However, you <em>cannot</em> assume that a restriction will be
  present in the bundle just because you defined a default value in the
  restrictions XML file.
</p>

<p>
  It is up to your app to take appropriate action based on the current
  restrictions settings. For example, if your app has a restriction specifying
  whether it can download data over a cellular connection, and you find that
  the restriction is set to <code>false</code>, you would have to disable data
  download except when the device has a Wi-Fi connection, as shown in the
  following example code:
</p>

<pre>
boolean appCanUseCellular;

if appRestrictions.containsKey("downloadOnCellular") {
    appCanUseCellular = appRestrictions.getBoolean("downloadOnCellular");
} else {
    // here, cellularDefault is a boolean set with the restriction's
    // default value
    appCanUseCellular = cellularDefault;
}

if (!appCanUseCellular) {
    // ...turn off app's cellular-download functionality
    // ...show appropriate notices to user
}</pre>

<h2 id="listen">
  Listen for App Restriction Changes
</h2>

<p>
  Whenever an app's restrictions are changed, the system fires the
  {@link android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED
  ACTION_APPLICATION_RESTRICTIONS_CHANGED} intent. Your app has to listen for
  this intent so you can change the app's behavior when the restriction settings
  change. The following code shows how to dynamically register a broadcast
  receiver for this intent:
</p>

<pre>IntentFilter restrictionsFilter =
    new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);

BroadcastReceiver restrictionsReceiver = new BroadcastReceiver() {
  &#64;Override public void onReceive(Context context, Intent intent) {

    // Get the current restrictions bundle
    Bundle <code>appRestrictions</code> =

    myRestrictionsMgr.getApplicationRestrictions();

    // Check current restrictions settings, change your app's UI and
    // functionality as necessary.

  }

};

registerReceiver(restrictionsReceiver, restrictionsFilter);
</pre>
<p class="note">
  <strong>Note:</strong> Ordinarily, your app does not need to be notified
  about restriction changes when it is paused. Instead, you should unregister
  your broadcast receiver when the app is paused. When the app resumes, you
  first check for the current restrictions (as discussed in <a href=
  "#check_restrictions">Check Device Restrictions</a>), then register your
  broadcast receiver to make sure you're notified about restriction changes
  that happen while the app is active.
</p>