Enterprise Android App Config - Application Restrictions - Not working as expected

1.1k views Asked by At

Really could use some guidance on how to debug / troubleshoot this issue I'm having.

I built my first app designed to be configured by an Enterprise MDM / EMM service. I created the app_restrictions.xml file, and I setup my Bundle for restrictions to be read in from that file.

When running in debug on a device connected to my computer, I can successfully read in all the values from the XML file

However the problem occurs once I roll it into production.

I've published the app to the play store, and added the app to the EMM/MDM.

I can see the managed configuration settings all appear inside the EMM/MDM - so I've got everything right up to this point.

However once the app is pushed with an alternate configuration to a device, the values being read in are not the custom values from the EMM/MDM - they are my default values inside of the XML that I developed.

I cannot find any good resources on troubleshooting this part of the process.

Anyone done this before have any ideas?

2

There are 2 answers

0
Ed Kuhner On BEST ANSWER

I've been creating a lot of B2B applications lately, and providing the customer with the ability to customize the app on a per-device or per-deployment basis is critical.

Here's my guide to adding App Config settings into your application for any MDM to be able to leverage these via the Managed Google Play Store:

Manifest: you must have this inside the section:

        <meta-data android:name="android.content.APP_RESTRICTIONS"
        android:resource="@xml/app_restrictions" />

app_restrictions.xml This file will hold your app restrictions. There are only a few options for app restrictions but you can make this work in all kinds of different creative ways. here's a basic set of restrictions:

<restrictions xmlns:android="http://schemas.android.com/apk/res/android">

    <restriction
    android:key="LicenseKey"
    android:title="@string/LicenseKey"
    android:restrictionType="string"
    android:description="@string/LicenseKey_Description"
    android:defaultValue="" />

    <restriction
    android:key="Section1"
    android:title="Settings"
    android:restrictionType="bundle">

        <restriction
        android:key="Setting1"
        android:title="Setting 1"
        android:description="More descriptive description here"
        android:restrictionType="choice"
        android:entryValues="@array/setting_1_array_values"
        android:entries="@array/setting_1_array_choices"
        android:defaultValue="@string/setting_1"/>

        <restriction
        android:key="Setting2"
        android:title="Setting 2"
        android:description="More descriptive description here"
        android:restrictionType="string"
        android:defaultValue="Some default string value here" />

        <restriction
        android:key="Setting3"
        android:title="Setting 3"
        android:description="More descriptive description here"
        android:restrictionType="integer"
        android:defaultValue="20" />

</restriction>

<restriction
    android:key="Section 2"
    android:title="Group things in more sections to make it easier to manage if you have lots of settings"
    android:restrictionType="bundle">

        <restriction
        android:key="Setting4"
        android:title="Setting 4"
        android:description="More descriptive description here"
        android:restrictionType="integer"
        android:defaultValue="20" />

        <restriction
        android:key="Setting5"
        android:title="Setting 5"
        android:description="More descriptive description here"
        android:restrictionType="integer"
        android:defaultValue="20" />

</restriction>

For some of your restrictions you may want a pre-defined list of items in a drop down style selector - as shown above you can use an array for this and put the following into your Strings.xml

Strings.xml:

<string-array name="setting_1_array_choices">
    <item>"Choose This for Option A"</item>
    <item>"Choose This for Option B"</item>
</string-array>
<string-array name="setting_1_array_values">
    <item>option_a</item>
    <item>option_b</item>
</string-array>

Now - loading these restrictions into your app:

    RestrictionsManager manager = (RestrictionsManager) getSystemService(this.RESTRICTIONS_SERVICE);
    Bundle restrictions = manager.getApplicationRestrictions();
    loadRestrictions(restrictions);

To load them I created this loadRestrictions sample:

private void loadRestrictions (Bundle bundle) {
    Set<String> keys = bundle.keySet();
    if (keys.isEmpty()) {
        //empty key set here
        //nothing sent via MDM App Config
    } else {
        //we've got keys to process
        for (String k : keys) {
            Object value = bundle.get(k);
            String valueString = "";
            if (value != null) {
                valueString = value.toString();
            }
            switch (k) {
                case "Section1":
                    if (value != null) {
                        loadRestrictions((Bundle) value);
                    }
                    break;
                case "Section2":
                    if (value != null) {
                        loadRestrictions((Bundle) value);
                    }
                    break;
                case "Setting1":
                    //Setting 1
                    // this is an array of choices
                    String optionChoice = "";
                    if(valueString.equals("option_a")) {
                        optionChoice = "Option A Was Chosen";
                    } else if (valueString.equals("option_b")) {
                        optionChoice = "Option B Was Chosen";
                    } else {
                        //we should not ever get here?
                        optionChoice = "ERROR?";
                    }                        
                    break;
                case "Setting2":
                    //Setting 1
                    // value for this key is in valueString
                    String setting2 = (String) valueString;
                    break;
                case "Setting3":
                    //Setting 3
                    // INTEGER value for this key is in value
                    int setting3 = (int) value;
                    break;
                case "Setting4":
                    //Setting 4
                    // INTEGER value for this key is in value
                    int setting4 = (int) value;
                    break;
                case "Setting5":
                    //Setting 5
                    // INTEGER value for this key is in value
                    int setting5 = (int) value;
                    break;
                default:
                    //another odd error occurred here
                    break;
            } //switch
        } //for keys
    }
}//load restrictions

Enjoy!!!

0
isthemartin On

When you use this method: getManifestRestriction restriction manager gets XML app restrictions, but when you use this method: getApplicationRestrictions the app reads restrictions from you EMM/MDM, also, you must configure a broadcast receiver for listening any change in your policies.

One more thing: in my case I had to create a shared preferences with all app restrictions to save the current settings and avoid that device erase them after a reboot.