Tasks for configuration handling
The code you add to your app to receive app-specific configuration is simple because the AppConnect wrapper around your app and the client do most of the work. Your focus is in applying the configuration to your app according to your requirements.
To handle app-specific configuration in your app, do the following high-level tasks:
-
Check at runtime if your app is wrapped.
This check is typically necessary if you are a third-party app developer using the same source code to create a Google Play app and an in-house AppConnect app. Only wrapped AppConnect apps can receive app-specific configuration from an Ivanti server.
If you are developing an app that will be distributed only as an in-house app, not from Google Play, you will not use this check.
-
Create a callback method to receive configuration updates
You provide a callback method that receives app-specific configuration updates.
IMPORTANT: The callback thread runs on the main thread.
-
Request the configuration when your app starts.
When your app starts, request the app-specific configuration, which your app will receive asynchronously in the callback method you provide.
-
Add callback information to AndroidManifest.xml
You provide a callback method that receives app-specific configuration updates. Add information about your callback method to your app’s AndroidManifest.xml file. You add this information as a <meta-data> element in your <application> element.
-
Specify app configuration and policies in .properties files.
You can include .properties files in your app that list your app’s key-value pairs and data loss prevention (DLP) policies. When the Ivanti server administrator uploads your app to the server, these files cause the server to automatically configure the key-value pairs and DLP policies.
If your app uses the legacy method for app-specific configuration handling, a summary of what to do to use the new method is in Changing from the legacy configuration handling to the new mechanism.
Check at runtime if your app is wrapped
If you are a third-party developer, you sometimes develop an app in which the same source code is used in these ways:
-
as a wrapped app distributed from the Ivanti server’s App Catalog
This secure AppConnect app is for enterprise device users.
-
as an unwrapped app distributed from Google Play
This unsecured app is for general distribution.
An app that serves both these markets typically behaves differently depending on whether it is a wrapped, secure AppConnect app.
For example:
-
If a wrapped app expects key-value pairs from the Ivanti server, but does not receive the expected pairs or valid values, it should take appropriate actions.
As a best practice, if your app expects a login ID from the server, but does not receive one, do not allow the device user to enter the ID manually. See Best practices for handling app-specific configuration.
-
If an app is not wrapped, it cannot get its configuration from the Ivanti server. It gets configurable information another way, such as prompting the device user to enter it.
For example, the unwrapped app prompts the user to enter a login ID.
To determine at runtime whether the app is running as a wrapped app, check this Android system property:
"com.mobileiron.wrapped"
For example, use the following expression:
Boolean.parseBoolean(System.getProperty("com.mobileiron.wrapped", "false"))
The expression returns true if the app is wrapped. Otherwise, it returns false.
Create a callback method to receive configuration updates
Add a callback method to your app that receives the app-specific configuration when:
- the app requests the app-specific configuration after the app launches.
- the administrator has made updates to the app-specific configuration on the Ivanti server.
IMPORTANT: The callback method runs on the app's main thread.
Implementing the callback method
Create a callback method with the name of your choice in a class of your choice.
Example
public class AppConfigCallback { public boolean onConfigReceived(Context context, Bundle config) { // Extract the key-value pairs from the Bundle object. For example: Map<String, String> map = new HashMap<String, String>(); for (String key:config.keySet()) { map.put(key, config.getString(key)); } // Process the key-value pairs according to your app's requirements. // return true if app successfully processes the key-value pairs; otherwise false. }
}
Parameters of callback method
- Context
Receives the application context. - Bundle
Bundle object that receives the app-specific configuration key-value pairs
If no key-value pairs are configured on the Ivanti server, calling the Bundle object's keyset() method returns an empty set.
Return value of callback method
boolean
Return true if the app successfully processed the configuration's key-value pairs.
Return false if your app failed to successfully process the key-value pairs. Some reasons for returning false are:
- A value is not valid for its key.
For example, if the key is “emailAddress”, but the value does not include the @ character, return false. - A value is empty.
Typically, if a key is included in the Ivanti server configuration for your app, your app expects a value. If the Ivanti server administrator did not enter a value, return false. - Your app encounters a system error while processing a key-value pair.
Your app determines whether a system error impacts key-value processing to warrant returning false.
When the callback method returns false, how your app continues to operate depends on your app’s design and requirements.
Request the configuration when your app starts
When your app starts, request the app-specific configuration. To request it, create an Intent object with the action "com.mobileiron.appconnect.action.REQUEST_APP_CONFIG"., and pass it to sendBroadcast().
For example, in HelloAppConnect:
public class AppConfigCallback { private static final String ACTION_REQUEST_APP_CONFIG = "com.mobileiron.appconnect.action.REQUEST_APP_CONFIG"; public static void requestConfig(Context context) { Intent intent = new Intent(ACTION_REQUEST_APP_CONFIG); context.sendBroadcast(intent); } }
This code results in an asynchronous call to your callback method that handles app-specific configuration.
Although the app can request the configuration at any time, typically the app requests it only once, when the app launches. After that, whenever the Ivanti server administrator updates the configuration on the server, your callback method is automatically called.
Add callback information to AndroidManifest.xml
Add a <meta-data> element to your app’s AndroidManifest.xml file as a child of your <application> element. The <meta-data> element contains name-value pairs that specify your callback class and method for handling app-specific configuration updates from the Ivanti server.
The <meta-data> element looks like this:
<application> <meta-data android:name="com.mobileiron.appconnect.config.callback_class" android:value="<fully-qualified-class-name>" /> <meta-data android:name="com.mobileiron.appconnect.config.callback_method" android:value="<callback method>" /> </application>
For example, in HelloAppConnect, the lines in AndroidManifest.xml are:
<application> <meta-data android:name="com.mobileiron.appconnect.config.callback_class" android:value="com.mobileiron.helloappconnect.AppConfigCallback" /> <meta-data android:name="com.mobileiron.appconnect.config.callback_method" android:value="onConfigReceived" /> </application>
Specify app configuration and policies in .properties files
You can include the following .properties files with your app:
-
appconnectconfig.properties
This file specifies your app’s configuration keys and their default values, if any. Providing this .properties file causes the Ivanti server to automatically configure the keys and their default values on the server.
-
appconnectpolicy.properties
This file specifies the default data loss prevention policy for screen capture for the app. Specifically, it specifies whether screen capture is allowed in the app. The policy is enforced by the AppConnect wrapping technology.
If your app contains these .properties files, the Ivanti server automatically configures the key-value pairs and the screen capture policy that you specified. This automatic configuration occurs when the Ivanti server administrator uploads your app to the server’s App Catalog.
The administrator can then change the default values on the server as necessary for that enterprise.
File location of the .properties files
Put the .properties files in this directory in your app:
<application root directory>/res/raw
Example of the appconnectconfig.properties file
An example of an appconnectconfig.properties file is available in HelloAppConnect.
It contains the following:
# This sample appconnectconfig.properties file uses rules found at
# http://en.wikipedia.org/wiki/.properties.
server=www.myCompanyApplicationServer.com
port=8080
# In the following example, the resulting property value contains only single spaces.
# It contains no other whitespace.
# Therefore, the value is: "I'm also demonstrating a multi-line property!"
name\ with\ spaces:I'm also demonstrating \
a multi-line property!
# Use an empty value for keys that have no default value.
nodefault=
! You can also start comments with exclamation marks.
# You can use these Ivanti variables for values:
# $USERID$, $EMAIL$, $PASSWORD$,
# $USER_CUSTOM1$, $USER_CUSTOM2$, $USER_CUSTOM3$, $USER_CUSTOM4$
# You can use these Ivanti Neurons for MDM variables for values:
# ${userUID}, ${userEmailAddress}
# ${USER_CUSTOM1}, ${USER_CUSTOM2}, ${USER_CUSTOM3}, ${USER_CUSTOM4}
userid=$USERID$
email=$EMAIL$
user_custom1=$USER_CUSTOM1$
combined=$USERID$::$EMAIL$
Format of the appconnectconfig.properties file
Use the rules for well-formed Java property files given in the Java Properties class. For example, use the characters = or : or a space to separate the key from the value. Use \ before each of these characters if the character is part of the key.
The values that you specify are the default values for the key. If the value has no default, leave the value empty.
A value can be any string. The value can also use one of the following server variables:
Core variable |
Ivanti Neurons for MDM variable |
Description |
$USERID$ |
${userUID} |
The device user’s enterprise user ID, typically an LDAP ID. |
$PASSWORD$ |
Not available |
The device user’s enterprise user password, typically an LDAP password. |
$EMAIL$ |
${userEmailAddress} |
The device user’s enterprise email address. |
$USER_CUSTOM1$ $USER_CUSTOM2$ $USER_CUSTOM3$ $USER_CUSTOM4$ |
${USER_CUSTOM1} ${USER_CUSTOM2} ${USER_CUSTOM3} ${USER_CUSTOM4} |
Custom variables that the Core server administrator sets up. Only use these variables if you are developing an app for a specific Ivanti customer. Contact the server administrator to determine the values of these variables. |
You can also specify values that are combinations of text and server variables. For example, using Core variables:
•$USERID$::$EMAIL$
•$USERID$@somedomain.com
Use server variables for default values in your appconnectconfig.properties only if you know what kind of server ( Core or Ivanti Neurons for MDM) your app will be used with. If you don’t know, leave the value empty. The server administrator will fill in the value.
Example of the appconnectpolicy.properties file
An example of an appconnectpolicy.properties file is available in HelloAppConnect.
It contains the following:
# A sample appconnectpolicy.properties file
screencapture=disable
Format of the appconnectpolicy.properties file
To disable screen capture in the app, include the following line in appconnectpolicy.properties:
screencapture=disable
To allow screen capture:
screencapture=allow
Changing from the legacy configuration handling to the new mechanism
If you used the legacy mechanism for app-specific configuration handling, change your app to use the new mechanism.
To change your app to use the new mechanism, do the following:
- In the legacy method, you created a class that extends IntentService(), and implemented onHandleConfig() to handle the received Intent object with the action "com.mobileiron.HANDLE_CONFIG" . Replace this class with a class of your choice with a callback method with a name of your choice. Move the code from your legacy onHandleConfig() to your new callback method. See Create a callback method to receive configuration updates.
- In the legacy method, when your app starts, it requests the app-specific configuration by calling startService() with an Intent object with the action "com.mobileiron.REQUEST_CONFIG". Replace this code with a call to sendBroadcast() with an Intent object with the action "com.mobileiron.appconnect.action.REQUEST_APP_CONFIG". See Request the configuration when your app starts.
- In the legacy method, you added information to the app's AndroidManifest.xml file to add a service for handling configuration intents. Remove the <service> element. Add the information about your callback method. See Add callback information to AndroidManifest.xml.