Skip to content

Class MicroVPNSDK

java.lang.Object
    com.citrix.mvpn.api.MicroVPNSDK
public class MicroVPNSDK
extends java.lang.Object

Citrix Micro VPN SDK provides per-app VPN connection without requiring MDM (Mobile Device Management). This SDK exposes APIs that can be called directly from the App in order to start a secure network tunnel and configure different network objects (WebView, OkHttp and URL) for tunneling through the already established tunnel.

Setting up the SDK

  1. Open your Android App project in an IDE. Update build.gradle to point to the MVPN SDK libraries.

    dependencies {
        …
        implementation "com.citrix.mvpn:mvpnsdk:1.0.0@aar"
        implementation "com.citrix.auth:authsdk:1.0.0@aar"
        implementation "com.citrix.sdk:loggersdk:1.0.0@aar"
        …
    }
    
  2. If your App has proguard settings enabled, then add the following in your proguard file.

    -keep class com.citrix.** {*;}
    -keepattributes Exceptions
    
  3. Please enable desugaring by adding the following to build.gradle.

    android {
        compileOptions {
            sourceCompatibility 1.8
            targetCompatibility 1.8
        }
    }
    
  4. Alternatively, increase the minSdkVersion to 26 or above

    android {
        defaultConfig {
            minSdkVersion 26
        }
    }
    

MicroVPNSDK.java - It is the entry class for Micro VPN SDK. This class provides #startTunnel(...) method to start Micro VPN network tunnel asynchronously. App should invoke #startTunnel(...) method from an activity and pass that activity instance as an argument to this method. This method also takes a messenger object that is needed for async communication. It throws NetworkTunnelAlreadyRunningException when there is already a network tunnel is running. TunnelConfigException is thrown when network tunnel configuration couldn't be retrieved from the Provider for any reason. All other exceptions can be caught through MvpnException.

Sample code for reference:

try {
    MicroVPNSDK.startTunnel(this, new Messenger(handler));
} catch (NetworkTunnelAlreadyRunningException e) {
    MvpnLogger.getLogger().error(LOG_TAG, "Network Tunnel is already running.");
} catch (TunnelConfigException te) {
    MvpnLogger.getLogger().error(LOG_TAG, "Exception occurred while getting tunnel configuration");
} catch (MvpnException e) {
    MvpnLogger.getLogger().error(LOG_TAG, "Micro VPN exception occurred");
}

Messenger object should have a custom Handler that will override Handler#handleMessage() method. When the tunnel starts successfully or fails to start, it will send start or failure Message using the input messenger object. If the value of msg.what is 0 then tunnel established successfully. If the value is 9999 then some exception occurred.

private final MvpnDefaultHandler handler = new MvpnDefaultHandler() {
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        if(isNetworkTunnelRunning()) {
            runOnUiThread(() -> Toast.makeText(TestStartTunnelActivity.this, "Micro VPN tunnel started successfully. " +
                    "Please start sending network requests now...", Toast.LENGTH_LONG).show());
        }
    }
};

It also provides methods to configure WebView, OkHttp and URL objects for tunnelling through the MVPN tunnel.

MicroVPNSDK.enableWebViewObjectForNetworkTunnel(...) method is used to update an webview object before loading the webview. Once the network tunnel is established successfully, then MicroVPNSDK.enableWebViewObjectForNetworkTunnel(...) needs to be called before calling webView.loadUrl(url). This method returns the modified webview object that is enabled for tunnelling.

try {
    OkHttpClient client = new OkHttpClient.Builder().build();
    Request request = new Request.Builder().url(url).build();
    client = (OkHttpClient) MicroVPNSDK.enableOkHttpClientObjectForNetworkTunnel(context, client);
    Response response = client.newCall(request).execute();
    responseHtml = response.body().string();
} catch(NetworkTunnelNotStartedException nse) {
    MvpnLogger.getLogger().error(LOG_TAG, nse.getMessage());
} catch(MvpnException e) {
    MvpnLogger.getLogger().error(LOG_TAG, e.getMessage());
}

MicroVPNSDK.createURLConnection(...) method is used to configure an URL object for tunneling through MVPN tunnel. This method returns the modified URLConnection object that is enabled for tunnelling.

try {
    URL url = new URL(strUrl[0]);
    URLConnection urlConnection = MicroVPNSDK.createURLConnection((Context)delegate, url);

    HttpURLConnection conn = (HttpURLConnection) urlConnection;
    int responseCode = conn.getResponseCode();
    InputStream inputStream;
    if (200 <= responseCode && responseCode <= 299) {
        inputStream = conn.getInputStream();
    } else {
        inputStream = conn.getErrorStream();
    }
    BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
    String currentLine;
    while ((currentLine = in.readLine()) != null) {
        response.append(currentLine);
    }
    in.close();

} catch (NetworkTunnelNotStartedException e) {
    MvpnLogger.getLogger().error(LOG_TAG, e.getMessage());
} catch(MvpnException e) {
    MvpnLogger.getLogger().error(LOG_TAG, e.getMessage());
}

Constructors

Constructor and Description Detail
MicroVPNSDK() public MicroVPNSDK()

Methods

Modifier and Type Field Description
static java.net.URLConnection createURLConnection(android.content.Context context, java.net.URL url) This method is used to configure an URL object for tunneling through MVPN tunnel.
static java.lang.Object enableOkHttpClientObjectForNetworkTunnel(android.content.Context context, java.lang.Object okHttpClient) This method is used to update an OkHttpClient object before OkHttp network call.
static android.webkit.WebView enableWebViewObjectForNetworkTunnel(android.content.Context context, android.webkit.WebView webView) This method update WebView for tunnelling through the MVPN tunnel.
static void startTunnel(android.app.Activity activity, android.os.Messenger messenger) This method will start network tunnel.
static void `startTunnel (android.content.Context context, android.os.Messenger messenger) This method will start network tunnel

Method Detail

startTunnel

public static void startTunnel(android.app.Activity activity,
                               android.os.Messenger messenger)
                        throws java.lang.IllegalArgumentException,
                               NetworkTunnelAlreadyRunningException,
                               NetworkTunnelStartFailedException,
                               TunnelConfigException,
                               MvpnAuthenticationException,
                               ClientDeviceSettingsException

This method will start network tunnel. App should invoke MicroVPNSDK.startTunnel(...) method from an activity and pass that activity instance as an argument to this method. This method also takes a messenger object that is needed for async communication. This method throws NetworkTunnelAlreadyRunningException when there is already a network tunnel is running. TunnelConfigException is thrown when there is network tunnel configuration couldn't be retrieved from the Provider for any reason. All other exceptions can be caught through MvpnException.

Sample code for reference:

try {
     MicroVPNSDK.startTunnel(this, new Messenger(handler));
} catch (NetworkTunnelAlreadyRunningException e) {
     MvpnLogger.getLogger().error(LOG_TAG, "Network Tunnel is already running.");
} catch (TunnelConfigException te) {
     MvpnLogger.getLogger().error(LOG_TAG, "Exception occurred while getting tunnel configuration");
} catch (MvpnException e) {
     MvpnLogger.getLogger().error(LOG_TAG, "Micro VPN exception occurred");
     }

Messenger object should have a custom Handler that will override Handler#handleMessage() method. When the tunnel starts successfully or fails to start, it will send start or failure Message using the input messenger object. If the value of msg.what is "0" then it established tunnel successfully. If the value is "9999" then some failure occurred.

private final Handler handler = new Handler() {
public void handleMessage(Message msg) {
    super.handleMessage(msg);
    switch (msg.what) {
    case 0:
        MvpnLogger.getLogger().info(LOG_TAG, "Tunnel Started. Send requests now.");
        break;
    case 1:
        MvpnLogger.getLogger().info(LOG_TAG, "Session Expired. Start Tunnel Again.");
        break;
    case 9999:
        MvpnLogger.getLogger().info(LOG_TAG, "Tunnel Failed to start.");
        break;
    default:
        break;
    }
}
};

Parameters

Parameter Description
activity this is the app activity that tries to start the tunnel
messenger this is the messenger object that is used to return response message back to the app.

Throws

Exception Description
java.lang.IllegalArgumentException throws this exception when activity or messenger is null
NetworkTunnelAlreadyRunningException throws this exception when tunnel is already running but app sends another request to start the tunnel
NetworkTunnelStartFailedException throws this exception when fails to start network tunnel.
TunnelConfigException throws this exception when fails to tunnel configuration (e.g. netscaler cookie or config)
MvpnAuthenticationException throws this exception when AuthSDK.login fails
ClientDeviceSettingsException throws this exception when device settings is incorrect (for example, No Internet connection)

startTunnel (android.app.Activity activity, android.os.Messenger messenger)

public static void startTunnel(android.content.Context context,
                               android.os.Messenger messenger)
                        throws java.lang.IllegalArgumentException,
                               NetworkTunnelAlreadyRunningException,
                               NetworkTunnelStartFailedException,
                               TunnelConfigException,
                               MvpnAuthenticationException,
                               ClientDeviceSettingsException

This method will start network tunnel. This method can be called to start network tunnel when there is a valid AG session already exists.

Parameters

Parameter Description
context this is the context of the application that tries to start the tunnel
messenger this is the messenger object that is used to return response message back to the app.

Throws

Exception Description
java.lang.IllegalArgumentException throws this exception when activity or messenger is null
NetworkTunnelAlreadyRunningException throws this exception when tunnel is already running but app sends another request to start the tunnel
NetworkTunnelStartFailedException throws this exception when fails to start network tunnel.
TunnelConfigException throws this exception when fails to tunnel configuration (e.g. netscaler cookie or config)
MvpnAuthenticationException throws this exception when AuthSDK.login fails
ClientDeviceSettingsException throws this exception when device settings is incorrect (for example, No Internet connection)

createURLConnection

public static java.net.URLConnection createURLConnection(android.content.Context context,
                                                         java.net.URL url)
                                                  throws NetworkTunnelNotStartedException,
                                                         ClientConfigurationException

This method is used to configure an URL object for tunneling through MVPN tunnel. This method returns the modified URLConnection object that is enabled for tunnelling. It throws NetworkTunnelNotStartedException when called before starting network tunnel.

This method does not validate if netscaler cookie is expired or not. So, after sending the actual network request, if it finds Netscaler session is expired then tunnel will send response header "X-Citrix-Session-Expired" = true. Developers can call utility method ResponseValidator.isNetScalerCookieExpired(response) to validate the response.

Sample code for reference:

try {
    URL url = new URL(strUrl[0]);
    URLConnection urlConnection = MicroVPNSDK.createURLConnection((Context)delegate, url);

    HttpURLConnection conn = (HttpURLConnection) urlConnection;
    int responseCode = conn.getResponseCode();
    InputStream inputStream;
    if (200 <= responseCode && responseCode <= 299) {
        inputStream = conn.getInputStream();
    } else {
        inputStream = conn.getErrorStream();
    }
    BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
    String currentLine;
    while ((currentLine = in.readLine()) != null) {
        response.append(currentLine);
    }
    in.close();

} catch (NetworkTunnelNotStartedException e) {
    MvpnLogger.getLogger().error(LOG_TAG, e.getMessage(), e);
} catch(MvpnException e) {
    MvpnLogger.getLogger().error(LOG_TAG, e.getMessage(), e);
}

Parameters

Parameter Description
context this is the context of the application that tries to start the tunnel
url this the url object that is enabled for network tunneling

Returns

return URLConnection object enabled for Micro VPN tunnel.

Throws

Exception Description
NetworkTunnelNotStartedException throws this exception when app tries to call this method before starting network tunnel
ClientConfigurationException throws this exception when WebView object could not be modified.

enableOkHttpClientObjectForNetworkTunnel

public static java.lang.Object enableOkHttpClientObjectForNetworkTunnel(android.content.Context context,
                                                                        java.lang.Object okHttpClient)
                                                                 throws NetworkTunnelNotStartedException,
                                                                        ClientConfigurationException

This method is used to update an OkHttpClient object before OkHttp network call. Once the network tunnel is established successfully, then MicroVPNSDK.enableOkHttpClientObjectForNetworkTunnel(...) needs to be called before making actual network request okHttpClient.newCall(request).execute(). This method returns the modified OkHttpClient object that is enabled for tunnelling. If this method is called before starting the network tunnel then will throw NetworkTunnelNotStartedException.

This method does not validate if netscaler cookie is expired or not. So, after sending the actual network request, if it finds Netscaler session is expired then tunnel will send response header "X-Citrix-Session-Expired" = true. Developers can call utility method ResponseValidator.isNetScalerCookieExpired(response) to validate the response.

Sample code for reference:

try {
    OkHttpClient client = new OkHttpClient.Builder().build();
    Request request = new Request.Builder().url(url).build();
    client = (OkHttpClient) MicroVPNSDK.enableOkHttpClientObjectForNetworkTunnel(context, client);
    Response response = client.newCall(request).execute();
    responseHtml = response.body().string();
} catch(NetworkTunnelNotStartedException nse) {
    MvpnLogger.getLogger().error(LOG_TAG, nse.getMessage(), nse);
} catch(MvpnException e) {
    MvpnLogger.getLogger().error(LOG_TAG, e.getMessage(), e);
}

Parameters

Parameter Description
context this is the context of the application that tries to start the tunnel
okHttpClient this the OkHttpClient object that is enabled for network tunneling

Returns

returns modified OkHttpClient

Throws

Exception Description
NetworkTunnelNotStartedException throws this exception when app tries to call this method before starting network tunnel
ClientConfigurationException throws this exception when WebView object could not be modified.

enableWebViewObjectForNetworkTunnel

public static android.webkit.WebView enableWebViewObjectForNetworkTunnel(android.content.Context context,
                                                                         android.webkit.WebView webView)
                                                                  throws NetworkTunnelNotStartedException,
                                                                         ClientConfigurationException

This method update WebView for tunnelling through the MVPN tunnel. Once the network tunnel is established successfully, then MicroVPNSDK.enableWebViewObjectForNetworkTunnel(...) needs to be called before calling webView.loadUrl(url). This method returns the modified webview object that is enabled for tunnelling. If this method is called before starting the network tunnel then will throw NetworkTunnelNotStartedException.

This method does not validate if netscaler cookie is expired or not. So, after sending the actual network request, if it finds Netscaler session is expired then tunnel will send response header "X-Citrix-Session-Expired" = true. Developers can call utility method ResponseValidator.isNetScalerCookieExpired(response) to validate the response.

Sample code for reference:

WebView myWebView = findViewById(R.id.webview);
try {
    myWebView.setWebViewClient(new WebViewClient());
    webView = MicroVPNSDK.enableWebViewObjectForNetworkTunnel(this, webView);
    webView.loadUrl(url);
} catch(NetworkTunnelNotStartedException nse) {
    MvpnLogger.getLogger().error(LOG_TAG, nse.getMessage(), nse);
} catch(MvpnException e) {
    MvpnLogger.getLogger().error(LOG_TAG, e.getMessage(), e);
}

Parameters

Parameter Description
context This is the context of the application that tries to start the tunnel
webView This the WebView object that is enabled for network tunneling

Returns

returns modified WebView

Throws

Exception Description
NetworkTunnelNotStartedException Throws this exception when app tries to call this method before starting network tunnel
ClientConfigurationException Throws this exception when WebView object could not be modified.