| 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><application></code></a> element: |
| </p> |
| |
| <pre><meta-data android:name="android.content.APP_RESTRICTIONS" |
| android:resource="@xml/app_restrictions" /> |
| </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><restrictions></code> element, which contains |
| one <code><restriction></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><restriction></code> element like this: |
| </p> |
| |
| <pre> |
| <?xml version="1.0" encoding="utf-8"?> |
| <restrictions xmlns:android="http://schemas.android.com/apk/res/android" > |
| |
| <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" /> |
| |
| </restrictions> |
| </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() { |
| @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> |