Android Mobile SDK
Introduction
Arkose Labs' mobile SDKs let you wrap our solution with Android native function calls. This guarantees seamless integration of your mobile apps with Arkose's full interactive challenges on detection and enforcement and does so without the extended wait times for separate mobile solutions.
This page covers the Mobile SDK for Android. If you are developing in iOS, see the Mobile SDK for iOS page.
The Arkose Mobile SDK v1:
-
Wraps Arkose's Advanced Enforcement Challenge in native Android OS "Web View"
-
Has 1-to-1 feature availability between web and mobile solutions.
-
Integrates with your apps through native functions.
-
Handles errors through callback events.
-
Complies with Arkose Internal Security guidelines.
-
Complies with Google Play Store guidelines for ease of integration.
-
Is fully compatible with new Enforcement Challenge-API (EC-API) releases.
-
Supports minimum version Android OS 5.0
Mobile SDK High Level Design
Mobile SDK Builds Availability
The Arkose Labs Mobile SDKs are available via the Mobile SDK's Support page. Please talk with your CSM (Customer Success Manager) about your intended usage and request access.
Compatibility
The Arkose Labs Mobile SDK for Android works with Android 5.0 and up.
All existing detection and challenge features on our web solutions are also available on the Mobile SDKs. All new ones are automatically added; you don't need to update your application every time we release a new Web platform. All challenge updates can be done without updating the SDKs or releasing a new version of your application.
Security
The Arkose Labs Mobile SDKs are Arkose Labs Security reviewed and comply with Google Play Store guidelines.
Performance
We created the Arkose Labs Mobile SDKs with stability and performance in mind. Their use has no significant impact on the host application’s performance.
Installation
Follow the steps below to set up Arkose Labs Mobile SDK for Android in Android Studio in your host application. This applies to both our detection and enforcement components.
Prerequisites
-
A host Android application. You must be able to build and run this application.
-
For the full end-to-end Arkose setup, you must also complete the standard Arkose Server-Side setup instructions.
Steps for Integration in an XML-based Application
Include the dependencies and ProGuard rules
-
Under
src/main
, create alibs
folder. -
Copy your
.aar
file (s) tosrc/main/libs
-
In the app level
build.gradle
file, add this line to itsdependencies
block.
implementation fileTree(dir: "libs", include: ["*.aar"])
implementation 'androidx.biometric:biometric:1.2.0-alpha04'
implementation 'com.google.code.gson:gson:2.11.0'
- Update the Android ProGuard or R8 configuration with the following rule sets:
-dontwarn com.google.android.play.core.integrity.IntegrityManagerFactory -dontwarn com.google.android.play.core.integrity.StandardIntegrityManager -dontwarn okhttp3.OkHttpClient$Builder -dontwarn okhttp3.OkHttpClient -dontwarn okhttp3.logging.HttpLoggingInterceptor$Level -dontwarn okhttp3.logging.HttpLoggingInterceptor$Logger -dontwarn okhttp3.logging.HttpLoggingInterceptor -dontwarn retrofit2.Converter$Factory -dontwarn retrofit2.Retrofit$Builder -dontwarn retrofit2.Retrofit -dontwarn retrofit2.converter.gson.GsonConverterFactory
- In the toolbar, click on File. Then in its menu click Sync Project with Gradle Files.
Import and add Arkose code to your application
-
Import the necessary SDK classes. Add the below code in your main file, right after you import your
android
andandroidx
classes and before your class definition statements.import com.arkoselabs.sdk.ArkoseChallenge; import com.arkoselabs.sdk.ArkoseConfig; import com.arkoselabs.sdk.ArkoseManager;
-
In the main screen activity section (Under src/main/java), in the onCreate method of the activity, initialize the SDK with ArkoseConfig object with API URL, API Key and other parameters.
// Build the configuration object final ArkoseConfig arkoseConfig = new ArkoseConfig.Builder() .apiKey(SPECIFY_YOUR_API_KEY) .blobData("") //encrypted blob data (optional) .loading(true) // setting this to false will not show the default loading spinner .enableBackButton(true) // To disable/enable device back button in EC process. Default is 'true' .setDismissChallengeOnTouchOutside(false) // To disable/enable touch outside of EC dialog to dismiss EC. Default is 'true' .language("") // Can set language here (optional) .setClientAPIRetryCount(0) // Can set number of retry count for when onError is triggered for certain client-side errors (optional) .setStyleTheme("") // Can set EC style theme (optional) .viewFrameAnimation(R.anim.custom_animation) // This to set animation while EC will be loading. You can set your own custom animation by putting value R.anim.<AnimStyle> .build(); // Set the log level ArkoseManager.setLogLevel(ArkoseManager.INFO); // Initialize the SDK // For v2.0.0 SDK //ArkoseManager.initialize(arkoseConfig); // For v2.1.0 SDK ArkoseManager.initialize(arkoseConfig, getApplication());
-
If you want to add your own custom animation, then the value of
viewFrameAnimation
will beR.anim.<CustomAnimStyle>
. TheCustomAnimStyle
is your animation xml file.-
We provide a number of inbuilt animations in the Mobile SDK. Use the desired animation style by replacing the
<AnimStyle>
inR.anim.<AnimStyle>
parameter.- blink
- fade
- scale_center
- sequential
- slide_down
- slide_left
- slide_right
- slide_up
- zoom_in
- zoom_out
-
-
To show the Enforcement View from the
onClick()
method of the Login Button, callshowEnforcementChallenge
method withFragmentActivity
as its parameter. This will run Arkose detection component (when running Arkose enforcement component, it also runs Arkose’s Enforcement Challenge). Fill in the method definitions with what you want to happen when that method is invoked as described in the comments. Note there are separate code examples for our detection and enforcement components.ArkoseChallenge arkoseChallenge = ArkoseManager.showEnforcementChallenge(this); arkoseChallenge. .addOnCompletedListener(arkoseChallengeResponse -> { // invoked On Enforcement Challenge completed }) .addOnFailureListener(arkoseChallengeResponse -> { // invoked on Enforcement Challenge failed }) .addOnErrorListener(arkoseChallengeResponse -> { // invoked on getting error while loading EC }) .addOnWarningListener(arkoseChallengeResponse -> { // invoked when an issue occurs which needs to be shared with the app as a warning }) .addOnResizeListener(arkoseChallengeResponse -> { // Provides the width and height of the visible EC from an SDK call // While you cannot set the width and height values yourself, // you can make use of their new values from the resizing // as you'd like, such as putting them in a log entry. }) .addOnReadyListener(() -> { //Do Something on ready callback received }) .addOnShowListener(() -> { //Do Something on show callback received }) .addOnShownListener(() -> { //Do Something on shown callback received }) .addOnHideListener(() -> { //Do Something on hide callback received }) .addOnResetListener(() -> { //Do Something on reset callback received }) .addOnViewFramePosition(arkoseChallengeResponse -> { // Do Something to set the position of view frame // Example: // arkoseECResponse.getWindow().getAttributes().gravity = Gravity.BOTTOM; // arkoseECResponse.getWindow().getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT; }) .addOnSuppressListener(() -> { //Do Something on suppress callback received } });
ArkoseLabs.getActivityClient(this).ShowEnforcementChallenge(arkoseConfig) .addOnCompletedListener(new OnCompletedListener < ArkoseECResponse > () { @Override public void onCompleted(ArkoseECResponse arkoseEnforcementChallengeResponse) { // invoked On Detection completed } }) .addOnErrorListener(new OnErrorListener<ArkoseECResponse>() { @Override public void onError(ArkoseECResponse arkoseECResponse) { // invoked on getting error while loading detection } }) .addOnWarningListener(new OnErrorListener<ArkoseECResponse>() { @Override public void onWarning(ArkoseECResponse arkoseECResponse) { // invoked on getting warning while loading detection } }) .addOnReadyListener(new OnReadyListener() { @Override public void onReady() { //Do Something on ready callback received } }) .addOnShowListener(new OnShowListener() { @Override public void onShow() { //Do Something on show callback received } .addOnHideListener(new OnHideListener() { @Override public void onHide() { //Do Something on hide callback received } }) .addOnSuppressListener(new OnSuppressListener() { @Override public void onSuppress() { //Do Something on suppress callback received } });
-
To create a view Fragment that can be embedded in another activity, use
ArkoseLabs.createEnforcementChallenge()
method which returns an instance ofArkoseChallenge
. This will create and set up a view Fragment which can be accessed using the methodArkoseChallenge.getEnforcementChallengeFragment
. The example below shows how you can create the ArkoseLabs challenge view Fragment and embed it into your app's activity.// Create Arkose challenge fragment ArkoseChallenge arkoseChallenge = ArkoseManager.createEnforcementChallenge(); arkoseChallenge .addOnCompletedListener(arkoseChallengeResponse -> { // invoked On Enforcement Challenge completed }) .addOnFailureListener(arkoseChallengeResponse -> { // invoked on Enforcement Challenge failed }); // Add other listeners as needed // Add the fragment to the activity FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.frameLayout, arkoseChallenge.getEnforcementChallengeFragment()); ft.commit();
Steps for Integration in a Compose-based Application
Include dependencies and ProGuard rules
-
Under
src/main
, create alibs
folder. -
Copy your
.aar
files tosrc/main/libs
- ArkoseLabsSDK.aar
- ArkoseLabsSDKCompose.aar
- NOTE: this companion framework file is intended for Jetpack Compose integrations.
-
In the app level
build.gradle
file, add this line to itsdependencies
block.implementation fileTree(dir: "libs", include: ["*.aar"]) implementation 'androidx.biometric:biometric:1.2.0-alpha04' implementation 'com.google.code.gson:gson:2.11.0'
-
Update the Android ProGuard or R8 configuration with the following rule sets:
-dontwarn com.google.android.play.core.integrity.IntegrityManagerFactory -dontwarn com.google.android.play.core.integrity.StandardIntegrityManager -dontwarn okhttp3.OkHttpClient$Builder -dontwarn okhttp3.OkHttpClient -dontwarn okhttp3.logging.HttpLoggingInterceptor$Level -dontwarn okhttp3.logging.HttpLoggingInterceptor$Logger -dontwarn okhttp3.logging.HttpLoggingInterceptor -dontwarn retrofit2.Converter$Factory -dontwarn retrofit2.Retrofit$Builder -dontwarn retrofit2.Retrofit -dontwarn retrofit2.converter.gson.GsonConverterFactory
-
In the toolbar, click on File. Then in its menu click Sync Project with Gradle Files.
-
Import the necessary SDK classes. Add the below code in your Activity class, before your class definition statements.
import com.arkoselabs.compose.sdk.ArkoseConfigCompose import com.arkoselabs.compose.sdk.EnforcementChallenge
-
Initialize the
mutableStateOf
state object to show/hide Enforcement Challenge.val showEc = remember { mutableStateOf(false) }
-
To show the Enforcement Challenge dialog from the
onClick
lambda function of a Login Button, update themutableStateOf
that controls the visibility of theEnforcementChallenge()
composable.var sessionResetTime by remember { mutableIntStateOf(0) } //in milliseconds ... ... ... when { showEc.value -> EnforcementChallenge( onDismiss = { showEc.value = false }, sessionResetTime = sessionResetTime, //optional config = ArkoseConfigCompose( apiKey = apiKeyText, enableBackButton = true, //optional noSuppress = true, //optional blobData = "", //optional loading = true, //optional language = "", //optional dismissChallengeOnTouchOutside = false, //optional clientAPIRetryCount = 0, //optional styleTheme = "" //optional ), onCompleted = { "Arkose Enforcement Challenge onCompleted -> ${it.response}".log() }, onFailure = { "Arkose Enforcement Challenge OnFailure -> ${it.response}".log() }, onError = { "Arkose Enforcement Challenge OnError -> ${it.response}".log() }, onWarning = { "Arkose Enforcement Challenge OnWarning".log() }, onResize = { "Arkose Enforcement Challenge OnResize -> ${it.response}".log() }, onViewFramePosition = { "Arkose Enforcement Challenge OnViewFramePosition -> ${it.response}".log() }, onReady = { "Arkose Enforcement Challenge OnReady".log() }, onShow = { "Arkose Enforcement Challenge OnShow".log() }, onShown = { "Arkose Enforcement Challenge OnShown".log() }, onHide = { "Arkose Enforcement Challenge OnHide".log() }, onReset = { "Arkose Enforcement Challenge OnReset".log() }, onSuppress = { "Arkose Enforcement Challenge OnSuppress".log() } ) }
Alternatively:
-
To embed the Enforcement Challenge in an Activity, create a new
InlineActivity
.import com.arkoselabs.compose.sdk.ArkoseConfigCompose import com.arkoselabs.compose.sdk.EnforcementChallengeInline class InlineActivity : ComponentActivity() {
-
Use the inline composable object
EnforcementChallengeInline()
, which will be tied to the lifecycle ofInlineActivity
.@Composable fun InlineScreen(onFinish: () -> Unit) { val isVisible = remember { mutableStateOf(true) } var sessionResetTime by remember { mutableIntStateOf(0) } //in milliseconds ... ... Column { EnforcementChallengeInline( onDismiss = { onFinish() }, sessionResetTime = sessionResetTime, //optional isVisible = isVisible, //optional config = ArkoseConfigCompose( apiKey = AppConfig.API_KEY, enableBackButton = true, //optional noSuppress = false //optional ), onCompleted = { "Arkose Enforcement Challenge onCompleted -> ${it.response}".log() }, onFailure = { "Arkose Enforcement Challenge OnFailure -> ${it.response}".log() }, onError = { "Arkose Enforcement Challenge OnError -> ${it.response}".log() }, onWarning = { "Arkose Enforcement Challenge OnWarning".log() }, onResize = { "Arkose Enforcement Challenge OnResize -> ${it.response}".log() }, onViewFramePosition = { "Arkose Enforcement Challenge OnViewFramePosition -> ${it.response}".log() }, onReady = { "Arkose Enforcement Challenge OnReady".log() }, onShow = { "Arkose Enforcement Challenge OnShow".log() }, onShown = { "Arkose Enforcement Challenge OnShown".log() }, onHide = { "Arkose Enforcement Challenge OnHide".log() }, onReset = { "Arkose Enforcement Challenge OnReset".log() }, onSuppress = { "Arkose Enforcement Challenge OnSuppress".log() } ) }
-
Invoke
finish()
onInlineActivity
when exiting the screen to prevent memory leaks.class InlineActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ... ... InlineScreen(onFinish = { finish() }) ... ... }
Build the revised project
-
Go to the Build menu and click on Clean Project.
-
Go to the Build menu and click on Rebuild Project.
Run and test the app
-
Run your Android application.
-
- If running Arkose enforcement component the view shows an Arkose Labs Enforcement Challenge.
- If running Arkose detection component, the view runs Arkose detection component.
-
If running Arkose enforcement component, verify the challenge.
-
When the verification or detection is successful, the
onCompleted
event returns a response token. The following sample code shows what this should look like and what to do with the token. Note there are separate code samples for detection and enforcement.
.addOnCompletedListener(arkoseChallengeResponse -> {
// invoked On Enforcement Challenge completed
String userResponseToken = arkoseChallengeResponse.getResponse().toString();
// Get value of the token
String userResponseToken = arkoseChallengeResponse.getResponse().getString("token");
Log.i(TAG,"Arkose EC completed: " + userResponseToken);
// sendToBackendServer(userResponseToken);
})
public void onCompleted(ArkoseECResponse arkoseECResponse) {
String userResponseToken = arkoseECResponse.getResponse().toString();
// Get value of the token
String userResponseToken = arkoseECResponse.getResponse().getString("token");
Log.i(TAG,"Arkose Detection completed: " + userResponseToken);
// sendToBackendServer(userResponseToken);
}
Jetpack Compose Support
Integrating the Arkose Mobile SDKs into Jetpack Compose apps is straightforward, eliminating the need for extra configuration and allowing developers to incorporate SDK features into composable objects with ease.
For optimal app and SDK performance, it's advised to utilize baseline profiles, which leverage Jetpack Compose's just-in-time (JIT) compilation. This approach, especially when creating baseline profiles for critical user actions like showing the Enforcement Challenge, prompts Android Runtime to optimize execution through ahead-of-time (AOT) compilation, significantly boosting performance. For guidance on crafting a Baseline Profile, consult the Android Documentation.
ArkoseConfig
Configuration
ArkoseConfig
ConfigurationNote that Arkose’s detection component is part of our overall Arkose Bot Manager platform. Thus the names of some methods and variables refer only to enforcement when actually dealing with detection as well. Unless otherwise specified, the configuration components apply to both detection and enforcement components, although perhaps in different ways as specified.
Configuration Object | Type | Description | Applicable Component |
---|---|---|---|
ArkoseConfig (or) ArkoseConfigCompose | Public component | Enables a consistent public parameter data model for the View in which it is called. An initialized model object later passed as parameters to the showEnforcementChallenge() Arkose Labs Mobile SDK.Note that our detection component is part of our overall Arkose Bot Manager platform. Thus the names of some methods and variables refer only to enforcement when actually dealing with detection as well. | Detection Enforcement |
showEnforcementChallenge | Public Method | Method that starts the Arkose Labs detection when using our detection component and enforcement when using our enforcement component. Before calling this method, the model object ( ArkoseConfig ) must be initialized with the additional configuration parameters.This method adds two listeners: - addOnCompletedListener : Invoked on completion of verification. Overrides the onCompleted method with a response.- addOnFailureListener : Invoked when Enforcement Challenge verification fails. Overrides the onFailed method with a response. | Detection Enforcement |
createEnforcementChallenge | Public Method | Method that creates the Arkose Labs object without invoking the display function. Before calling this method, the model object ( ArkoseConfig ) must be initialized with the additional configuration parameters given in the next table. These values are set in the strings.xml file.This method is used in conjunction with getEnforcementChallengeFragment method to allow embedding into the parent app activity as a fragment. | Detection Enforcement |
OnLoadedListener | Function | Listener function invoked when the SDK has been loaded. | Detection Enforcement |
OnReadyListener | Function | Listener function invoked when the Enforcement or Detection is ready. The Enforcement or Detection cannot be triggered before this event. You may want to disable the UI you are protecting until this event has been triggered. | Detection Enforcement |
OnShowListener | Function | Listener function invoked when the Enforcement or Detection is completed. The function is also invoked when an Enforcement Challenge or detection is re-displayed (e.g. if the user closes the EC or detection view and tries to continue). Note that the close button only appears when in Lightbox mode. | Detection Enforcement |
OnShownListener | Function | Listener function invoked when the Enforcement Challenge or Detection is displayed. The function is only invoked the first time an Enforcement Challenge is displayed. | Enforcement |
OnCompletedListener | Function | Listener function invoked when either: a. For our enforcement component, a session is classified as not needing a challenge or a challenge has been successfully completed. b. For our detection component, a session detection has been successfully completed. A Response Object is passed to this function. | Detection Enforcement |
OnHideListener | Function | Listener function invoked when the EC or detection view is hidden. For example, this happens after an EC or detection is completed or if the user clicks the close button. Note that the close button only appears when in Lightbox mode. | Detection Enforcement |
OnSuppressListener | Function | Listener function invoked when: a. The Enforcement Challenge is suppressed (i.e. A session was classified as not requiring a challenge). b. The Detection is running and is analyzing the user intent. | Detection Enforcement |
OnResetListener | Function | Listener function invoked after the Enforcement resets. Typically occurs after a challenge has been successfully answered. | Enforcement |
OnErrorListener | Function | Listener function invoked when an error occurs when loading the challenge or detection. A Response Object is passed to this function. | Detection Enforcement |
OnWarningListener | Function | Listener function invoked when an issue occurs which needs to be shared with the app as a warning, based on which App can take custom actions, when loading the challenge or detection. A Response Object is passed to this function. | Detection Enforcement |
OnFailedListener | Function | Listener function invoked when a challenge has failed (the user has failed the challenge multiple times and is not allowed to continue the session). A Response Object is passed to this function. | Enforcement |
OnResizeListener | Function | Listener function invoked when a challenge is loaded. It provides the width and height of the visible EC from an SDK call. A Response Object is passed to this function. | Enforcement |
OnViewFramePositionListener | Function | Listener function invoked when a challenge is loaded. It allows the parent APP to set the view frame window attributes as desired by calling the getWindow() function on the ArkoseECResponse parameter.E.g. arkoseECResponse.getWindow().getAttributes().gravity = Gravity.BOTTOM; A Response Object is passed to this function. | Enforcement |
Enforcement Challenge Configuration Parameters / strings.xml
strings.xml
You can change the following Enforcement Challenge configuration parameters by specifying their values in the ArkoseConfig
object.
EC Configuration Methods | Description |
---|---|
Builder apiBaseUrl(String apiBaseUrl) | Base URL of Arkose Bot Manager as supplied by Arkose Labs. |
Builder apiKey(String apiKey) | Public key for your account. |
Builder apiFile(String apiFile) | JavaScript file name of Arkose Labs EC as supplied by Arkose Labs. |
Builder blobData(String blobData) | Mainly used to share any client encrypted data blobs with Arkose Bot Manager. It is optional. Default: "" |
Builder language(String language) | Not applicable to our detection component. Language setting for the EC. Default: "en" |
Builder userAgent(String userAgent) | Specify any userAgent setting for ease of testing forced Enforcement Challenge for a session. It is optional. Please talk with your CSM (Customer Success Manager) about your intended usage and request backend configuration. Default: (inbuilt webview’s userAgent string) |
Builder loading(Boolean val) | Specify whether loading spinner is shown or not. Default: true |
Builder enableBackButton(Boolean val) | Specify whether device back button dismisses EC dialog or not. If this configuration is enabled, and the user uses the back button, onHide listener is triggered and EC dialog is dismissed. Default: true |
Builder setDismissChallengeOnTouchOutside(Boolean val) | Specify whether touching outside of EC dialog will dismiss the EC dialog or not. If this configuration is enabled, and user touches outside of the EC dialog, onHide listener is triggered and EC dialog is dismissed. Default: true |
Builder setClientAPIRetryCount(int count) | Specify the number of retries when network issues are triggered when the client app tries to connect to the apiBaseUrl .The retry only works for onError events with error codes below. When the configured number of retries is exhausted, the last error code is returned.1. Challenge load error. 2. API_REQUEST_ERROR 3. API_REQUEST_TIMEOUTIt is optional.Default: 0 |
Builder setStyleTheme(String styleTheme) | Style theme setting for the EC. It is optional. Default: "" |
Logging and Troubleshooting
Prerequisites
-
Install the Android Debug Bridge (adb) binary or driver on the machine where the logs will go.
-
An Android phone or Android emulator. On it, under Settings > Developer, enable the USB Debugging option
Steps
On the machine where the logs will go:
-
Download the SDK platform for your platform (Windows / Mac) from SDK Platform Tools release notes | Android Developers
-
Unzip the folder and check it contains an
adb.exe
file. -
From the command prompt, enter the path where
adb
is located on the machine. This image shows an example of what you get after you enter the path.
-
On your Android device, enable USB debugging:
-
At Phone>Settings>About Phone>, tap Build Number seven times. You should see a message saying that you are now a developer.
-
On the device, go to Developer options and turn on USB debugging.
-
Connect the device to the system and trust/allow the system.
-
To test if
adb
is working properly:-
Use a USB cable to connect your Android device to your computer.
-
At the computer’s command prompt, run the command
adb devices
to show the devices connected to the system.
-
-
- To start verbose logging in the terminal window, at the computer’s command prompt, run
adb logcat -s ArkoseLabsShowEnforcementChallenge:v
If instead, you want to save the logs, runadb logcat -d > <path-where-you-want-to-save-file>/<filename>.txt
Ctrl+C stops the logging.
adb logcat
Options
adb logcat
Optionsadb logcat
has several command options. These include:
-
adb logcat
: Prints log data to the screen. -
adb logcat *:V
: Lowest priority, filter to only show Verbose level log entries. -
adb logcat --help
: Shows alllogcat
options and arguments. -
adb logcat -c
: Clears the logs . -
adb logcat -s <TAG>:<PRIORITY>
:-
-s
: Sets default filter to silent. -
<TAG>
: A log component tag (or*
for all). -
<PRIORITY>
can be:-
V
: Verbose (default for<TAG>
) -
D
: Debug (default for*
) -
I
: Info -
W
: Warn -
E
: Error -
F
: Fatal -
S
: Silent (suppress all output)
-
-
Updated about 1 month ago