Essential

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:

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 PerimeterX Portal to:
    1. Retrieve the PerimeterX application ID (AppID).
    2. Set the token expiration and validity.
  2. An active PerimeterX 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: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'

Adding PerimeterX 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 PerimeterX 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
  2. Put the PerimeterX-release.aar in the libs folder of your app.
  3. 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;
  1. Make your Application class to implement the PerimeterXDelegate. Implement all functions in the interface.
class MainApplication: Application(), PerimeterXDelegate
class MainApplication extends Application implements PerimeterXDelegate
  1. Call the PerimeterX/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;
});
  1. 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);
  1. Add the PerimeterX's interceptor (PXInterceptor) 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);
  1. 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 PerimeterX, 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.