Integrate AirWatch Android SDK with Room Finder app

The AirWatch Software Development Kit (SDK) for Android allows you to enhance your enterprise applications with EMM capabilities. By incorporating AirWatch SDK code within your Android app project, you can use AirWatch information such as enrollment or compromised status to add a layer of security and business logic however you see fit within your application.

The Android SDK has two primary components or libraries:

  1. Client SDK - The client SDK is a lightweight library for retrieving basic management and device information such as compromised status, environment info, and user information.
  2. AWFramework - The AWFramework is a heavier library for more advanced SDK functionality such as application proxy and tunneling, integrated authentication, and encryption functions.

1. Add the required Gradle Dependancies

We have already included the required libraries in your folder. In this section, we are going to update our Gradle configuration to reference these libraries into Room Finder app.

Code snippets as shown in the screenshot:

  1. Click on "App/ Gradle Scripts/ build.gradle (app)".
  2. Add build types using the code snippet below:

apply plugin: 'com.android.application'

android {

   compileSdkVersion 23

   buildToolsVersion "23.0.3"

   useLibrary 'org.apache.http.legacy'

   defaultConfig {

       applicationId "com.airwatch.roomfinder"

       minSdkVersion 16

       targetSdkVersion 23

       versionCode 1

       versionName "1.0"

       multiDexEnabled = true

   }

   dexOptions {

       jumboMode = true

       javaMaxHeapSize "4g"

   }

   buildTypes {

       release {

           minifyEnabled false

           proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

       }

   }

}

repositories{

   flatDir{

       dirs 'libs'

   }

}

dependencies {

   //from libs

   compile fileTree(dir: 'libs', include: ['*.jar'])

   compile (name:'sqlcipher-3.5.3', ext:'aar')

   compile (name:'AWFramework-release-16.08.37-SNAPSHOT', ext:'aar')

   compile (name:'AirWatchSDK-16.08-SNAPSHOT', ext:'aar')

   testCompile 'junit:junit:4.12'

   compile "com.android.support:support-v13:23.1.1"

   compile "com.android.support:appcompat-v7:23.1.1"

   compile "com.android.support:cardview-v7:23.1.1"

   compile "com.android.support:recyclerview-v7:23.1.1"

   compile "com.android.support:design:23.1.1"

}

1.1. Copy the required libraries in the libs folder

  1. Extract Android-AirWatchSDK.zip.
  2. Copy the libraries to path /Android - roomfinder2016 / app / libs folder.

1.2. Source Tree Checkout to add the required Framework

Source Tree Checkout to add the required Framework

For this lab, we have setup Source Tree along with the correct repository. You can also import the gradle changes by from the repository "Android-roomfinder2016".

  1. Checkout the commit "Adding Airwatch libraries and other dependencies to gradle"

2. Integrate with AirWatch SDK to setup App Passcode

An organization requires granular security and data loss protection within enterprise applications to prevent sensitive data and documents from leaking outside company control. Rather than relying solely on device passcode, it is beneficial to setup an application level authentication.

In this section, we will perform code implementation to setup an application level passcode.

2.1. Changes in the AndroidManifest.xml File

  1. Navigate to AndroidManifest.xml file from in the project structure.
  2. Add the Android name (line 17as per the screenshot):

<activity android:name="com.airwatch.gateway.ui.GatewaySplashActivity">

3.     Add the activity provider (line 24 as per the screenshot):

<activity android:name=".MainActivity"/>

       <provider

           android:name="com.airwatch.storage.PreferencesProvider"

           android:authorities="com.airwatch.roomfinder.securepreferences"

           android:exported="false"/>

2.2. Change the MainActivity to extend SDKBaseActivity

  1. Navigate to "MainActivity".
  2. Import com.airwatch.login.SDKBaseActivity.
  3. Extend MainActivity class using (as per line 27 in screenshot):

public class MainActivity extends SDKBaseActivity implements IAppStateHandler{

2.3. Changes in the RoomFinderApp

We will now change the class RoomFinderApp to extend AWApplication and to implement NetworkRequestFactory.

  1. Navigate to class "RoomFinderApp".
  2. With method overrides, the new RoomFinder App class source code is now changed to:

package com.airwatch.roomfinder;

import android.app.Application;

import android.content.Intent;

import android.support.multidex.MultiDex;

import com.airwatch.app.AWApplication;

import com.airwatch.gateway.ui.GatewaySplashActivity;

import com.airwatch.roomfinder.network.INetworkRequest;

import com.airwatch.roomfinder.network.NetworkRequest;

import com.airwatch.roomfinder.network.NetworkRequestFactory;

 

public class RoomFinderApp extends AWApplication implements NetworkRequestFactory {

   private INetworkRequest networkRequest = new NetworkRequest();

   @Override

   public void onCreate() {

       MultiDex.install(this);

       super.onCreate();

   }

   @Override

   public Intent getMainActivityIntent() {

       return new Intent(this, MainActivity.class);

   }

   @Override

   public Intent getMainLauncherIntent() {

       return new Intent(this, GatewaySplashActivity.class);

   }

   @Override

   public INetworkRequest getNetworkRequest() {

       return networkRequest;

   }

}

2.4. Add SDK Branding Icon

To add the branding icon:

  1. Navigate to "app/src/main/res/values/styles.xml".
  2. Add the following line (line 10 as per the screenshot):

<item name="sdkBrandingIcon">@mipmap/ic_launcher</item>

 

2.5. Register the receiver.

The AirWatch SDK receives notifications from the AirWatch Admin Console through the implementation of a class which extends the AirWatchSDKBaseIntentService.

  1. Navigate to AndroidManifest.xml via "app/src/main/AndroidManifest.xml".
  2. Code changes to add a receiver as the per screenshot (line 31):

       <receiver

           android:name="com.airwatch.sdk.AirWatchSDKBroadcastReceiver"

           android:permission="com.airwatch.sdk.BROADCAST" >

           <intent-filter>

               <action android:name="com.airwatch.roomfinder.airwatchsdk.BROADCAST" />

           </intent-filter>

           <intent-filter>

               <action android:name="android.intent.action.PACKAGE_ADDED" />

               <action android:name="android.intent.action.PACKAGE_REMOVED" />

               <action android:name="android.intent.action.PACKAGE_REPLACED" />

               <action android:name="android.intent.action.PACKAGE_CHANGED" />

               <action android:name="android.intent.action.PACKAGE_RESTARTED" />

               <data android:scheme="package" />

           </intent-filter>

       </receiver>

       <service android:name=".AirWatchSDKIntentService" />

2.6. Receive callback methods via AirWatchSDKBaseIntentService

Implement the AirWatchSDKBaseIntentService to receive the callback methods. Create a class that extends AirWatchSDKBaseIntentService.

  1. Create a new class at "app/src/main/java/com/airwatch/roomfinder/AirWatchSDKIntentService.java".
  2. Code for the new class implementation is:

package com.airwatch.roomfinder;

import android.content.Context;

import android.content.Intent;

import android.os.Bundle;

import android.support.v4.content.LocalBroadcastManager;

import android.util.Log;

import com.airwatch.login.SDKAppAuthenticator;

import com.airwatch.login.timeout.SDKSessionManagerInternal;

import com.airwatch.sdk.AirWatchSDKBaseIntentService;

import com.airwatch.sdk.context.SDKContext;

import com.airwatch.sdk.context.SDKContextManager;

import com.airwatch.sdk.profile.AnchorAppStatus;

import com.airwatch.sdk.profile.ApplicationProfile;

 

public class AirWatchSDKIntentService extends AirWatchSDKBaseIntentService {

   private static final String TAG = "AirWatchSDKIntent";

   private static final String CLEAR_APP_DATA_BROADCAST = "com.airwatch.roomfinder.clearappdata.BROADCAST";

   @Override

   protected void onClearAppDataCommandReceived(Context context) {

       Intent clearAppDataIntent = new Intent(CLEAR_APP_DATA_BROADCAST);

       LocalBroadcastManager.getInstance(context).sendBroadcast(clearAppDataIntent);

       SDKContextManager.getSDKContext().init(context);

       SDKContextManager.getSDKContext().getSDKSecurePreferences().edit().clear();

   }

   @Override

   protected void onAnchorAppStatusReceived(Context ctx, AnchorAppStatus appStatus) {

       if(appStatus.getWorkspaceExitMode() == 0

               && SDKContextManager.getSDKContext().getCurrentState() != SDKContext.State.IDLE){

           SDKSessionManagerInternal manger = SDKSessionManagerInternal.getsSdkSessionDelegate(ctx);

           if(SDKAppAuthenticator.AUTHENTICATION_MODE_SSO.equalsIgnoreCase(manger.getAuthenticationMode())){

               manger.handleAuthenticationTimeOut();

           }

       }

   }

   @Override

   protected void onAnchorAppUpgrade(Context ctx, boolean isUpgrade) {

       Log.d(TAG, "Received AnchorAppUpgrade broadcast. AnchorApp is " + (isUpgrade ? "upgrading" : "removed"));

   }

   @Override

   protected void onApplicationConfigurationChange(Bundle applicationConfiguration) {

       Log.d(TAG, "received application configuration change "+applicationConfiguration);

   }

   @Override

   protected void onApplicationProfileReceived(Context context, String s, ApplicationProfile applicationProfile) {

       Log.d(TAG, "received application profile");

   }

}

2.7. Source Tree Checkout for Login Integration

Source Tree Checkout for Login Integration

The code implementation so far can be imported from Source Tree by checking out the commit "Login Integration".

2.8. Validate app level passcode on the enrolled device

In this section, we are going to validate the code implementation we performed in the previous step and confirm that we see a prompt to setup an authentication passcode on the initial launch. The complexity of this passcode is configured in a SDK profile in AirWatch Console.

3. Retrieve SDK Custom Settings

Many enterprise applications require users to enter URL, port, email address, and various configurations as part of a one time setup of an  application. These manual configurations can impact the adoption and success of an organization’s mobile app initiatives, increase the burden on a help desk fielding calls from users, and adds the burden of maintaining documentation that needs to be updated frequently as new updates to the application are made available.

In the previous section, we had to enter the Exchange URL manually. Now we will see how can we populate that URL automatically into our app via Custom Settings from a SDK profile pre-configured in the AirWatch EMM console.

3.1. Changes in the URL Fragment Entry

  1. Navigate to "app/src/main/java/com/airwatch/roomfinder/urlentry/URLEntryFragment.java".
  2. Add method  getExchangeURLFromCustomSettings() (as per line 187 in screenshot):

       getExchangeURLFromCustomSettings();

   }

   private void getExchangeURLFromCustomSettings(){

       new AsyncTask<Void, Void, String>(){

           @Override

           protected String doInBackground(Void... params) {

               String url = "";

               try {

                   SDKManager sdkManager = SDKManager.init(getActivity().getApplicationContext());

                   url = sdkManager.getCustomSettings();

               } catch (AirWatchSDKException e) {

                   e.printStackTrace();

               }

               return url;

           }

           @Override

           protected void onPostExecute(String s) {

               if (!TextUtils.isEmpty(s)){

                   urlEntry.setText(s);

               }

           }

       }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

   }

3.2. Source Tree checkout to Retrieve Custom Settings

Source Tree checkout to Retrieve Custom Settings

The code implementation so far can be imported from Source Tree by checking out the commit "Fetch Exchange URL from custom settings".

3.3. Validate that URL is auto-populated

In this section, we are going to validate the code implementation we performed in the previous step and confirm that URL is automatically populated.

4. Integrated Authentication

A typical enterprise application may be accessing a endpoints which would require authentication from the end user. Prompting the end user to authenticate every single time may not be the best user experience. AirWatch SDK addresses this problem by providing helper classes to perform Integrated Authentication. Integrated Auth allows you to capture the enrollment credentials/ AD User Certificates/ Kerberos Authentication and be presented to the authentication endpoints. AirWatch also allows the configuration where you can allow only certain domains so that the authentication credentials are not exposed unintentionally.

Let us see how can we implement integrated authentication in Room Finder app using AirWatch SDK.

4.1. Changes in NetworkRequest.java file

In order to achieve integrated authentication, we are going to customize implementation of httpClient class. Instead of using DefaultHttpClient, we will use this customised class called AWHttpClient.

  1. Navigate to "app/src/main/java/com/airwatch/roomfinder/network/NetworkRequest.java"
  2. Code changes (as per line 70 in the screenshot):

//DefaultHttpClient httpClient = new DefaultHttpClient();

//httpClient.getAuthSchemes().register(AUTH_TYPE, new NTLMSchemeFactory());

//httpClient.getCredentialsProvider().setCredentials(new AuthScope(url.getHost(), -1), new NTCredentials(username, password, "", ""));

DefaultHttpClient httpClient = new AWHttpClient();

4.2. Changes in the Validate Parameters method in the same class

Changes in the Validate Parameters method in the same class

Scroll down to the method Validate Parameters. The new implementation of this method is:

private boolean validateParams(){

       return Patterns.WEB_URL.matcher(url.toExternalForm()).matches();

       //return isUrlValid && !TextUtils.isEmpty(username) && !TextUtils.isEmpty(password);

}

4.3. Changes in the URLEntryFragment.java

Changes in the URLEntryFragment.java
  1. Navigate to "app/src/main/java/com/airwatch/roomfinder/urlentry/URLEntryFragment.java".
  2. Change the method afterTextChanged() (~line 70) as per the following code snippet:

   @Override

        public void afterTextChanged(Editable s) {

           //enableUserCredentials(validateURL(s.toString()));

           //User credentials will be obtained from Anchor app directly

           enableLoginButton(validateURL(s.toString()));

        }

    };

3.   Change method isUserAuthenticated() (~line 243) with the following code:

    private boolean isUserAuthenticated(){

        boolean isAuthenticated = false;

        INetworkRequest networkRequest = ((NetworkRequestFactory)getActivity().getApplicationContext()).getNetworkRequest();

       //User credentials will be obtained from Anchor app directly

       //networkRequest.setUserCredentials(usernameEntry.getText().toString().trim(), passwordEntry.getText().toString());

        try {

4.4. Source Tree Checkout for Integrated Authentication

Source Tree Checkout for Integrated Authentication

The code implementation so far can be imported from Source Tree by checking out the commit "Integrated Authentication".

0 Comments

Add your comment

E-Mail me when someone replies to this comment

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.