Sample Code

HTCpro MDM Sample Code

The HTCpro MDM API includes a sample application that illustrates all the major functionality for managing access to the various components and uses the standard Android Device Admin enablement APIs.

Installing the MDM sample code: The sample project is already an Eclipse based project so you may simply import from within Eclipse.  If working on a different environment make sure to target the OpenSense SDK Add-on.  For both cases, the OpenSense SDK Add-on can be installed from the Android SDK Manager:

Please note: the HTCpro MDM APIs are only available starting with Sense 4.x devices. Sense 3.x ICS devices are not supported.

Here are the screenshots of the main activity screens of the sample application:


First Screen
     
Second Screen

A requirement to access device admin APIs is to first activate Device Admin capability for this activity. The second screen is the standard window that appears when one presses the "Enable Admin" button on the main activity screen.

After activating Device Admin, you will be returned to the first screen where you will see the Enable Admin button toggle to Disable Admin (as shown).

Once activated, many of the items on the screen, buttons, check boxes and text fields will be enabled (otherwise the components are disabled).

Shown on this first screen is a form to fill for adding a new EAS account. Towards the bottom of this screen is the top of the VPN configuration form (the screen scrolls) where you can add or delete VPN adapters and get additional info.

Scrollng down on the main activity's initial screen, we can see the following:

Following the bottom half of the VPN configration form, we find 4 additional features:

  • Install Certification:  it will search and filter certification files (primiarily based on file extension) for installation
  • Get Active Sync ID: returns unique active sync ID
  • Encrypt SD Cards: sets requirement for SD card. It can test if already encrypted (as of HTC SDK API Level 22 - see About HTC SDK API Levels within sample code below)
  • Wipe SD Cards: can wipe SD card(s) which includes internal "SD card"

MDM Framework Overview

The following diagram provides an overview of the components involved:


The following calls out the API calls for each component as featured in the sample code:

EAS

add an EAS Account
delete an EAS Account
obtain ActiveSync device id
VPN

add VPN adapter
delete VPN adapter
obtain VPN adapter by configuration id
SD Card

wipe SD cards
encrypt SD cards
Additional

install certificate

Note: this is an initial set, future updates will add additional components and features or integrate with 3rd party solutions.

The following flow diagram illustrates the flow between the various components and standard Device Admin functionality:


Here is the code listing excerpt from MdmApiSample.java:


public class MdmApiSample extends Activity implements FileFilter {
    
/** Called when the activity is first created. */
    
private final static String TAG="MdmApiSample";
    static final 
int RESULT_ENABLE 1;
    static final 
String ACTIVE_ADMIN "com.htc.sample.mdm.ACTIVE_ADMIN";

    
DevicePolicyManager mDPM;
    
ComponentName mDeviceAdmin;
    
Button btEnableAdmin;
    
ArrayList<ButtonmTestButtons = new ArrayList<Button>();

    
BroadcastReceiver receiver = new BroadcastReceiver() {

        
@Override public void onReceiveContext contextIntent intent {
            Log
.d(TAG, new Exception("Debug Tracing").getStackTrace()[0].toString());
            
DevicePolicyManager Dpm getDPM();
            
enableTestButtons(((DevicePolicyManager)Dpm).isAdminActive(mDeviceAdmin));
        
}
    }

As show above, a broadcast reciever is used for recieving a notification that we're ready to create a device policy manager (more on that in a bit)

There are also additional broadcast receivers declared in our manifest:


<receiver android:name="com.htc.sample.mdm.ResultReceiver" 
            
android:permission="android.permission.BIND_DEVICE_ADMIN">
            <
intent-filter>
                <
action android:name="com.htc.app.admin.dpm.action.DPM_ERROR_STATUS" />
            </
intent-filter>
        </
receiver>

        <
receiver android:name="com.htc.sample.mdm.DeviceAdmin" android:label="@string/app_name"
            
android:permission="android.permission.BIND_DEVICE_ADMIN">
            <
meta-data android:name="android.app.device_admin"
                
android:resource="@xml/device_admin" />
            <
intent-filter>
                <
action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
            </
intent-filter>
        </
receiver

As you'll notice the second receiver is defined in DeviceAdmin.java, the DeviceAdmin receiver (this whether we activated via our sample project or from device settings -> security:)


public class DeviceAdmin extends DeviceAdminReceiver {
    
private static final String TAG="DeviceAdmin";
    
void showToast(Context contextCharSequence msg{
        Toast
.makeText(contextmsgToast.LENGTH_SHORT).show();
    
}

    
@Override public void onEnabled(Context contextIntent intent{
        Log
.d(TAG, new Exception("Debug Tracing").getStackTrace()[0].toString());
        
Intent i = new Intent(MdmApiSample.ACTIVE_ADMIN);
        
context.sendBroadcast(i);
        
showToast(context"Sample Device Admin: enabled");
    

Additional call backs include:

onDisabled()
onDisableRequested()
onPasswordChanged()
onPasswordFailed()
onPasswordSucceeded()

Additional device admin management restrictions can be added here to handle number of failed password attempts for example.

The first receiver maps to ResultReceiver.java and as expected this handles all the results of the DM operations on the various components.

Let's follow one starting with the result for a request for an Active Sync ID:


@Override public void onReceiveContext contextIntent intent {
        Log
.d(TAG, new Exception("Debug Tracing").getStackTrace()[0].toString());
        
Log.vTAG" ResultReceiver.onReceive " );

        
String intentString intent.getAction();
        
Log.vTAG"onReceive(), received intent:" intentString );

        if ( 
intentString.equals(DpmErrorCode.ACTION_DPM_ERROR_STATUS) ) {        

            
// Check error code
            
int resultCode = (int)intent.getIntExtraDpmErrorCode.EXTRA_ERROR_CODE, -);      
            
Log.vTAG"resultCode:" resultCode );

            
showToastcontext" Code: " resultCode );                  

            
// Handle error codes accordingly. In this sample application we simply display a Toast to user
            
switch( resultCode {
            
// ************** Success ***************
            // Get Active Sync ID Success 
                
case DpmErrorCode.DPM_ERROR_GET_ACTIVE_SYNC_ID_SUCCESS :
                    
String activeSyncId intent.getStringExtra(DpmErrorCode.EXTRA_ACTIVE_SYNC_DEVICE_ID);
                    
Log.v(TAG"activeSyncId="activeSyncId);
                    
showToast(context"activeSyncId="activeSyncId);
                    break; 

Remember, following the flow diagram above, after we're sure that the Device Admin is activated we need to obtain the request method from the device policy manager. For this specific case, this is initiated from the corresponding button in MdmApiDemo.java:


void testGetActiveSyncDeviceId() {
        Log
.d(TAG, new Exception("Debug Tracing").getStackTrace()[0].toString());
        
HtcIfDevicePolicyManager Dpm = (HtcIfDevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
        
Dpm.getActiveSyncDeviceId();
    

Success and error codes are handled together as shown in the onReceive() snippet from ResultReceiver.java shown above.



Handling different MDM API versions


About HTC SDK API Levels:

You may find the following under Settings->About->Software Information:

HTC SDK API Level 4.1x (or 4.2x depending on the device)

There are several reasons for having several versions of the SDK API supported (note this versioning is not the same as Sense version). One reason is the capabilities of the device. Note that MDM is supported starting with API Level 4.11, but additions have been made to more recent versions, starting with 4.2x notably new error codes corresponding to SD card encryption.

An addition to the sample code (bottom of ResultReceiver.java) to handle new codes in HTC SDK API Level 4.2x would be as follows:

 // Encrypt SD card failure
case DpmErrorCode.DPM_ERROR_ENCRYPT_SD_ALREADY_ENCRYPTED:
case DpmErrorCode.DPM_ERROR_ENCRYPT_SD_NO_SDCARD:
case DpmErrorCode.DPM_ERROR_ENCRYPT_SD_PASSWORD_REQUIRED:
case DpmErrorCode.DPM_ERROR_ENCRYPT_SD_UNDEFINED:
Log.v(TAG, "Encrypt SD card failed.");
showToast(context, "Encrypt SD card failed.");
break;


The JavaDoc API Reference Documentation of the MDM API contains standard JavaDoc style "Since" tags that will indicate when an API was addded (which API Level it was added in). Please take note of which corresponding APIs for a  corresponding API Level for your application is supported being by your target device(s).


API Documentation:

The HTCpro MDM API Reference Documentation