How to integrate the SDK in your application
  • 13 Feb 2024
  • Dark
    Light

How to integrate the SDK in your application

  • Dark
    Light

Article Summary

v2.x

Introducing the software documentation and the demo app!

The software documentation provides elaborated information on every class, function and member in the SDK. Please choose the relevant SDK version:

v2.2.9v2.2.6v2.2.5v2.2.4v2.2.3v2.2.2v2.2.1v2.2.0v2.1.1v2.1.0v2.0.1v2.0.0

The demo app gives you a general idea on how you should implement the SDK in you app. To download, please follow those steps:

  1. Open the demo app repo.
  2. Download the content of the repo.
  3. Unzip the file and open the Android demo app.

Prerequisites

The following are required to install the SDK:

  1. Administrative access to the HUMANPortal to:
    1. Retrieve the HUMAN application ID (AppID).
    2. Set the token expiration and validity.
  2. An active HUMAN Enforcer.

Permissions and dependencies

Add the following permissions to your AndroidManifest.xml file:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
<uses-permission android:name="android.permission.INTERNET" />

Add the following dependencies to your build.gradle file (please refer to the relevant SDK version):

implementation 'com.google.android.material:material:1.5.0'  
implementation 'com.google.android.gms:play-services-instantapps:18.0.1'
implementation 'io.ktor:ktor-client-okhttp:2.0.3'
implementation 'com.google.android.material:material:1.5.0'  
implementation 'com.google.android.gms:play-services-instantapps:18.0.1'
implementation 'io.ktor:ktor-client-okhttp:1.6.8'
implementation 'com.google.android.material:material:1.5.0'  
implementation 'com.google.android.gms:play-services-instantapps:18.0.1'
implementation 'io.ktor:ktor-client-okhttp:1.6.7'
implementation 'com.google.android.material:material:1.4.0'  
implementation 'com.google.android.gms:play-services-instantapps:18.0.0'
implementation 'io.ktor:ktor-client-okhttp:1.6.7'

The SDK depends on few AndroidX libraries. If your project does not includes AndroidX, you should add the following dependencies:

implementation "androidx.lifecycle:lifecycle-common-java8:2.4.1"
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"

The "Doctor App" feature requires the AndroidX's fragment library. If your project does not includes AndroidX, you should add the following dependency:

implementation 'androidx.fragment:fragment:1.3.6'

Update your OkHttp library to v4
If your app is using OkHttp v3, there will be a conflict that could cause unexpected errors in runtime. Notice that you should update both `okhttp` and `logging-interceptor` libraries.

Adding HUMAN SDK to your project

You can add the SDK to your project with one of the following options:

JFrog

Add the following repository to your build.gradle and settings.gradle:

maven { url 'https://perimeterx.jfrog.io/artifactory/px-Android-SDK/' }
maven { url = uri("https://perimeterx.jfrog.io/artifactory/px-Android-SDK/") }

Add the following dependency to your build.gradle and set the HUMAN Android SDK version:

implementation 'com.perimeterx.sdk:msdk:<Version>'
implementation("com.perimeterx.sdk:msdk:<Version>")

Manual

  1. Download the AAR file from https://perimeterx.jfrog.io/ui/repos/tree/General/px-Android-SDK or use the following command line:
curl -LO https://perimeterx.jfrog.io/artifactory/px-Android-SDK/com/perimeterx/sdk/msdk/2.2.6/msdk-2.2.6.aar
  1. Put the HUMAN-release.aar in the libs folder of your app.
  2. Add the following dependency to your build.gradle:
implementation files('libs/PerimeterX-release.aar')

How to start the SDK

Starting the SDK should be the first thing that runs in your app. Therefore, you should start it in your Application class:

  1. Import the SDK:
    import com.perimeterx.mobile_sdk.PerimeterX
    import com.perimeterx.mobile_sdk.PerimeterXDelegate
    import com.perimeterx.mobile_sdk.main.PXPolicy
    import com.perimeterx.mobile_sdk.PerimeterX;
    import com.perimeterx.mobile_sdk.PerimeterXDelegate;
    import com.perimeterx.mobile_sdk.main.PXPolicy;
  2. Make your Application class to implement the HUMANDelegate. Implement all functions in the interface.
    class MainApplication: Application(), PerimeterXDelegate
    class MainApplication extends Application implements PerimeterXDelegate
  3. Call the HUMAN/start(appId:delegate:enableDoctorCheck:completion:) function with your AppID in the Application's onCreate function.
    PerimeterX.INSTANCE.start(this, "<APP_ID>", this, false) { success ->  
    	if (!success) {  
    		// make sure to start the sdk again when it fails (network issue, etc.)
    	}   
    }
    PerimeterX.INSTANCE.start(this, "<APP_ID>", this, false, success -> {  
    	if (!success) {  
    		 // make sure to start the sdk again when it fails (network issue, etc.)
    	}
      	return null;
    });
  4. You can set the SDK's policy to configure custom configurations and behaviors:
    val policy = PXPolicy()
    // configure the policy instacne
    PerimeterX.INSTANCE.setPolicy(policy, null)
    PXPolicy nativePolicy = new PXPolicy();
    // configure the policy instacne
    PerimeterX.INSTANCE.setPolicy(policy, null);
  5. Add the HUMAN's interceptor (HUMANInterceptor) to your HttpClient's interceptors list at the end. This is required for the automatic interception.

OkHttp:

private var okHttpClient: OkHttpClient = OkHttpClient.Builder()  
	.addInterceptor(MyInterceptor())  
	.addInterceptor(PXInterceptor()) // MUST BE THE LAST INTERCEPTOR IN THE CHAIN  
	.build()
private final OkHttpClient httpClient = new OkHttpClient.Builder()  
	.addInterceptor(new MyInterceptor())  
	.addInterceptor(new PXInterceptor()) // MUST BE THE LAST INTERCEPTOR IN THE CHAIN  
	.build();

ktor:

private val httpClient: HttpClient = HttpClient(OkHttp) {  
	engine {  
		addInterceptor(MyInterceptor())  
		addInterceptor(PXInterceptor()) // MUST BE THE LAST INTERCEPTOR IN THE CHAIN  
	}  
}

That's it! 🎉 Your code should be like this:

PerimeterX.INSTANCE.start(this, "<APP_ID>", this, false) { success ->  
    if (!success) {  
        // make sure to start the sdk again when it fails (network issue, etc.)
    }
}

val policy = PXPolicy()
// configure the policy instacne
PerimeterX.INSTANCE.setPolicy(policy, null)
PerimeterX.INSTANCE.start(this, "<APP_ID>", this, false, success -> {  
    if (!success) {  
        // make sure to start the sdk again when it fails (network issue, etc.)
    }
	return null;
});

PXPolicy nativePolicy = new PXPolicy();
// configure the policy instacne
PerimeterX.INSTANCE.setPolicy(policy, null);

How to include SDK’s headers in your URL requests

SDK's headers must be included in your URL requests. To your delight, the SDK is automatically intercepts URL requests from your app which sent with OkHttp client. By doing so, the SDK takes care of adding those headers to your URL requests, which means you don't have to do anything else.

However, you may choose to include those headers by yourself. To do so, please follow those steps:

  1. In the policy, set the PXPolicy/requestsInterceptedAutomaticallyEnabled to false:
    policy.requestsInterceptedAutomaticallyEnabled = false
    policy.setRequestsInterceptedAutomaticallyEnabled(false);
  2. Before sending your URL request, take HTTP headers from the SDK and add them to your request:
    val headers = PerimeterX.INSTANCE.headersForURLRequest()
    
    // add those headers to your URL request
    HashMap<String, String> headers = PerimeterX.INSTANCE.headersForURLRequest(null);
        
    // add those headers to your URL request
Don't cache headers!

You should not cache those headers. Those headers contain a token with expiration data. The SDK manages this token to be up-to-date.

How to handle the block response from the server

To your delight, the SDK is automatically intercepts URL requests from your app which which sent with OkHttp client. By doing so, the SDK takes care of handling the block response from your server, which means you don't have to do anything else.

You can verify the error object that was received with those APIs:

  1. PerimeterX/isRequestBlockedError(error:) - the request was blocked; Called immediately when the response from the server reach the device.
  2. PerimeterX/isChallengeSolvedError(error:) - the request was blocked and the user solved the challenge; Called after the user solved the challenge.
  3. PerimeterX/isChallengeCancelledError(error:) - the request was blocked and the user cancelled the challenge; Called after the user cancelled the challenge.

However, if you choose to include headers from the SDK to your URL request manually, you have to provide the SDK with the response as well:

After receiving an error in the response, pass the information to SDK:

val isHandledByPX = PerimeterX.INSTANCE.handleResponse(null, responseString, response.code)  
if (isHandledByPX) {  
    println("block response was handled by PX")
}
boolean isHandledByPX = PerimeterX.INSTANCE.handleResponse(null, responseString, response.code());  
if (isHandledByPX) {  
    Log.i("tag", "block response was handled by PX");
}

Hybrid App support

The hybrid App uses both native URL requests and web views to communicate with the server. In the context of HUMAN, it's important to make sure both native requests and web views are synced together to make sure end users will get the expected behavior from your app. To help the SDK achieve that, you should set your domain in the policy for the relevant AppID. Here is an example:

policy.domains.add("my-domain.com")
policy.getDomains().add("my-domain.com");

In addition, you need to setup your web view with the PerimeterX/setupWebView(webView:webViewClilent:) function. The first parameter is the web view instance. The second parameter (optional) is your web view client instance. You should not set your web view client directly to the web view, but using this function instead. Here is an example:

Kotlin:

PerimeterX.INSTANCE.setupWebView(webView, webViewClient)

Java:

PerimeterX.INSTANCE.setupWebView(webView, webViewClient)

Enable support for Account Defender

In order to enable Account Defender, a user ID must be set. You can set it by calling the PerimeterX/setUserId(userId:forAppId:) function with a non null value. When the current user logout, you should call this function again with null. This will turn off the Account Defender.

PerimeterX.INSTANCE.setUserId("<the current user ID>", null)
PerimeterX.INSTANCE.setUserId("<the current user ID>", null);

In order to tell Account Defender about the user's flow, you should call this function for each URL request that been send to your server. Notice that when the PXPolicy/requestsInterceptedAutomaticallyEnabled is set to true, the SDK registers URL requests automatically and you don't need to call this function.

PerimeterX.INSTANCE.registerOutgoingUrlRequest("<URL>", null)
PerimeterX.INSTANCE.registerOutgoingUrlRequest("<URL>", null);

Understanding how the SDK works

What happens when you start the SDK

The PerimeterX/start(appId:delegate:enableDoctorCheck:completion:) function sets up the session for a given AppID. Without setting up the session, most APIs in the SDK won't work (for example, set policy or get headers). Notice that you don't need to wait until the completion handler is called in order to call other APIs. When the process ends successfully, the completion handler is called with success as true. However, this process can fail due to network issue. In this case, you should call the function again (we recommend waiting one second before calling it again).

When you call the PerimeterX/start(appId:delegate:enableDoctorCheck:completion:) function, the SDK is creating a background thread to perform its work. You don't need to worry about any performance issue when calling it from the main thread.

While this function is working in the background, the SDK will still provide the required headers. It's essential to call this function as early as possible in your application and before any URL request to your server.

What is included in the SDK's headers

The headers includes a token that allow your server to verify that the URL request comes from your app, which running the SDK. The SDK receives this token from PerimeterX's backend when you call the PerimeterX/start(appId:delegate:enableDoctorCheck:completion:) function. Every few minutes the SDK communicates with PerimeterX's backend to get a new token.

However, you don't need to verify that the token is exists in the headers. For example, when sending a request while the SDK is starting, the SDK's header will have an indication that the token is not available yet. This case is relevant for the first time you app launches on a device, because the token is saved persistently in the SDK and will used in the next app launch.

How the SDK presents the block page to the user

When the SDK receives the block response from the server it performs the following actions:

  1. Presenting a block activity in the app, over your other activities.
  2. In the block activity the SDK presents a web view which loads the challenge that must be solved by the user (or the bot).
  3. Once the challenge is solved, the SDK removes the block activity and allow the user to continue working in your app.

Next steps

Review the following topics:


Was this article helpful?