To configure anti-crawler rules for your Android apps, you must first integrate the app protection SDK. This topic provides the required integration steps.
Background information
The app protection SDK ensures trusted communication by signing all requests initiated from your app. The Web Application Firewall (WAF) server then verifies these signatures. This process lets WAF identify and block malicious requests from bots and other attackers, securing your application's services.
Limits
The SDK supports the arm64-v8a and armeabi-v7a architectures for Android OS.
The API level for Android OS must be 16 or higher.
The
initmethod performs time-consuming operations. To ensure security features are fully initialized, wait at least 2 seconds after callinginitbefore calling thevmpSignmethod. This is a recommended delay to maximize protection and can be adjusted as needed. However, shorter delays may prevent the security capabilities from taking full effect.When using ProGuard for code obfuscation, use the -keep option to preserve the SDK's API methods. For example:
-keep class com.aliyun.TigerTally.** {*;}
-keep class com.aliyun.captcha.* {*;}
-keepclassmembers,allowobfuscation class * {
@com.alibaba.fastjson.annotation.JSONField <fields>;
}
-keep class com.alibaba.fastjson.** {*;}Prerequisites
You have obtained the SDK for your Android apps.
To get the SDK, submit a ticket.
The SDK for Android apps includes two AAR files:
AliTigerTally_X.Y.Z.aarandAliCaptcha_X.Y.Z.aar, whereX.Y.Zrepresents the version number.Obtain the SDK authentication key (appkey).
After you enable Bot Management, navigate to the page and click Obtain and Copy AppKey to obtain the appkey. This key serves as a credential and is required to initialize the SDK in your application code.
NoteEach Alibaba Cloud account is assigned a single, unique appkey that applies to all domains protected by WAF. This key is used for SDK integration across Android, iOS, and HarmonyOS apps.
Sample appkey: ****OpKLvM6zliu6KopyHIhmneb_****u4ekci2W8i6F9vrgpEezqAzEzj2ANrVUhvAXMwYzgY_****vc51aEQlRovkRoUhRlVsf4IzO9dZp6nN_****Wz8pk2TDLuMo4pVIQvGaxH3vrsnSQiK****.
Step 1: Create a project
Use Android Studio as an example.
Create an Android project by following the configuration wizard. The project directory is shown in the following figure.

Step 2: Integrate the AAR package
Extract the tigertally-X.Y.Z-xxxxxx-android.tgz package. Copy all the AAR files from the resulting folder into the libs directory of your main module (note that the specific path may vary based on your project's configuration).

Open the build.gradle file of your app. Add the libs directory as a dependency source and add compilation dependencies for AliTigerTally_X.Y.Z.aar and AliCaptcha_X.Y.Z.aar.
ImportantYou must replace the version number X.Y.Z in the AliTigerTally_X.Y.Z.aar and AliCaptcha_X.Y.Z.aar file names with the actual one.
The configuration is shown as follows:
dependencies { // ... implementation files('libs/AliTigerTally_X.Y.Z.aar') implementation files('libs/AliCaptcha_X.Y.Z.aar') // Third-party library dependencies implementation 'com.alibaba:fastjson:1.2.83_noneautotype' implementation 'com.squareup.okhttp3:okhttp:3.11.0' implementation 'com.squareup.okio:okio:1.14.0 }
Step 3: Filter the SO CPU architecture
If your project has not used SO files before, add the following configuration in your build.gradle file.
android {
defaultConfig {
ndk {
abiFilters 'arm64-v8a', 'armeabi-v7a'
}
}
}Step 4: Request permissions for the apps
Required permissions
<uses-permission android:name="android.permission.INTERNET"/>Optional permissions
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
For Android 6.0 and later, you must dynamically request the android.permission.READ_EXTERNAL_STORAGE and android.permission.WRITE_EXTERNAL_STORAGE permissions.
Step 5: Add the integration code
Add header files
import com.alibaba.fastjson.*;
import com.aliyun.tigertally.*;Set data signing
Set a custom end user ID for your business.
This lets you flexibly configure WAF mitigation policies.
/** * Set the user account * * @param account The account * @return The error code */ public static int setAccount(String account)Parameters:
account: A string that identifies a user. We recommend using a desensitized format.
Return value: Returns 0 if the setting is successful, or -1 if it fails. Data type: int.
Sample code:
// For a guest, you can skip setAccount and directly initialize the SDK. After logon, call setAccount and re-initialize. String account = "user001"; TigerTallyAPI.setAccount(account);
Initialize the SDK and perform data collection.
An initialization process collects device information once. You can call the
initmethod again to start a new collection process based on different business requirements. There are three modes for initialization: full collection, custom privacy collection, and non-privacy collection. The non-privacy mode does not collect fields involving user privacy, such as imei, imsi, simSerial, wifiMac, wifiList, bluetoothMac, and androidId.NoteWe recommend that you select a collection mode that complies with your internal compliance requirements and ensures data integrity. Complete data helps identify potential risks more effectively.
// Initialization callback public interface TTInitListener { // code indicates the status code of the interface call void onInitFinish(int code); } /** * SDK initialization with callback * * @param appkey The appkey * @param type The type of data to collect * @param otherOptions Various parameter options * @return The error code */ public static int init(Context context, String appkey, int collectType, Map<String, String> otherOptions, TTInitListener listener);Parameters:
context: The context of your application. Data type: Context.
appkey: Your SDK appkey. Data type: String.
collectType: The data collection mode. Data type: int. Valid values:
Field name
Description
Example
TT_DEFAULT
Collects all data.
TigerTallyAPI.TT_DEFAULT
TT_NO_BASIC_DATA
Does not collect basic device data. Includes: device name (Build.DEVICE), Android version number (Build.VERSION#RELEASE), and screen resolution.
TigerTallyAPI.X | TigerTallyAPI.Y
(Indicates that neither X nor Y is collected. X and Y represent the field names of specific items.)
TT_NO_IDENTIFY_DATA
Does not collect device identifier data. Includes: IMEI, IMSI, SimSerial, BuildSerial (SN), and MAC address.
TT_NO_UNIQUE_DATA
Does not collect unique identifier data. Includes: OAID, Google Advertising ID, and Android ID.
TT_NO_EXTRA_DATA
Does not collect extended device data. Includes: malicious/gray-area app list, LAN IP, DNS IP, connected Wi-Fi information (SSID, BSSID), nearby Wi-Fi list, location information, and sensor information.
TT_NOT_GRANTED
Does not collect any of the privacy data listed above.
TigerTallyAPI.TT_NOT_GRANTED
otherOptions: Optional. Data type: Map<String,String>. Default value: null. Valid values:
Field name
Description
Example
IPv6
Specifies whether to use an IPv6 domain name to report device information. Valid values:
0 (default): Use an IPv4 domain name.
1: Use an IPv6 domain name.
1
Intl
Specifies the region where device information is reported. Valid values:
0 (default): the Chinese mainland
1: outside the Chinese mainland
Set this to 1 for WAF instances outside the Chinese mainland; otherwise, use the default of 0.
1
CustomUrl
Sets the domain name of the data reporting server.
https://cloudauth-device.us-west-1.aliyuncs.com
CustomHost
Sets the host of the data reporting server.
cloudauth-device.us-west-1.aliyuncs.com
NoteFor common international sites, setting the Intl parameter is sufficient. The CustomUrl and CustomHost parameters are only required when reporting to a specific site, such as the US (West) site: https://cloudauth-device.us-west-1.aliyuncs.com.
listener: The SDK initialization callback interface. Data type: TTInitListener. You can check the specific status of the initialization result in the callback. Default value: null.
TTCode
Code
Remarks
TT_SUCCESS
0
The SDK is initialized.
TT_NOT_INIT
-1
The SDK is not initialized.
TT_NOT_PERMISSION
-2
The required basic Android permissions are not fully granted to the SDK.
TT_UNKNOWN_ERROR
-3
An unknown system error occurred.
TT_NETWORK_ERROR
-4
A network error occurred.
TT_NETWORK_ERROR_EMPTY
-5
A network error occurred. The returned content is an empty string.
TT_NETWORK_ERROR_INVALID
-6
The format of the returned value is invalid.
TT_PARSE_SRV_CFG_ERROR
-7
Failed to parse the server configuration.
TT_NETWORK_RET_CODE_ERROR
-8
The gateway failed to return a value.
TT_APPKEY_EMPTY
-9
The appkey is empty.
TT_PARAMS_ERROR
-10
Other parameter errors occurred.
TT_FGKEY_ERROR
-11
A key calculation error occurred.
TT_APPKEY_ERROR
-12
The SDK version does not match the appkey version.
Return value: Returns 0 if the initialization is successful, or -1 if it fails. Data type: int.
Sample code:
// Appkey represents the authentication key assigned by the Alibaba Cloud customer platform. final String appkey="******"; // Optional parameters. You can configure IPv6 and international reporting. Map<String, String> options = new HashMap<>(); options.put("IPv6", "0"); // Configure as IPv4. //options.put("Intl", "0"); // Report to the Chinese mainland. options.put("Intl", "1"); // Report to regions outside the Chinese mainland. // Report to the US (West) site. //options.put("CustomUrl", "https://cloudauth-device.us-west-1.aliyuncs.com"); //options.put("CustomHost", "cloudauth-device.us-west-1.aliyuncs.com"); // An initialization collection indicates that the device information is collected once. You can call the init function again to re-initialize the collection based on different business requirements. // Full data collection. int ret = TigerTallyAPI.init(this.getApplicationContext(), appkey, TigerTallyAPI.TT_DEFAULT, options, null); // Specify privacy data collection. Different privacy data can be combined using "|". int privacyFlag = TigerTallyAPI.TT_NO_BASIC_DATA | TigerTallyAPI.TT_NO_UNIQUE_DATA; int ret = TigerTallyAPI.init(this.getApplicationContext(), appkey, privacyFlag, options, null); // Do not collect privacy fields. int ret = TigerTallyAPI.init(this.getApplicationContext(), appkey, TigerTallyAPI.TT_NOT_GRANTED, options, null); Log.d("AliSDK", "ret:" + ret);
Hash data.
This custom signing interface calculates a hash of the input data and returns the generated whash string as the custom signature. The request body must be passed as input for POST, PUT, and PATCH requests, while the complete URL must be used as input for GET and DELETE requests. Additionally, the whash string needs to be added to the ali_sign_whash field in the HTTP request header.
// Request type: public enum RequestType { GET, POST, PUT, PATCH, DELETE } /** * Custom hash signature data * * @param type Data type * @param input Hash data * @return whash */ public static String vmpHash(RequestType type, byte[] input);
Parameters:
type: The data type. Data type: RequestType. Valid values:
GET: A GET request.
POST: A POST request.
PUT: A PUT request.
PATCH: A PATCH request.
DELETE: A DELETE request.
input: The data to be signed. Data type: byte[].
Return value: A whash string. Data type: String.
Sample code:
// GET request String url = "https://tigertally.aliyun.com/apptest"; String whash = TigerTallyAPI.vmpHash(TigerTallyAPI.RequestType.GET, url.getBytes()); Log.d("AliSDK", "whash:" + whash); // POST request String body = "hello world"; String whash = TigerTallyAPI.vmpHash(TigerTallyAPI.RequestType.POST, body.getBytes()); Log.d("AliSDK", "whash:" + whash);This interface call is not required when using default signing. For custom signing, the interface must be called for hash verification before the data is signed.
Sign data.
This method uses vmp technology to sign the input data and returns a wtoken string for request authentication.
/** * Data signing * * @param type Signature type * @param input Signature data * @return wtoken */ public static String vmpSign(int type, byte[] input);
Parameters:
type: The data signature type. The value must be 1. Data type: int.
input: The data to be signed. This is typically the entire requestbody or the whash for custom signing. Data type: byte[].
Return value: A wtoken string. Data type: String.
Sample code:
// The console is configured with default signing, which means custom signing is not selected. String body = "i am the request body, encrypted or not!"; String wtoken = TigerTallyAPI.vmpSign(1, body.getBytes("UTF-8")); Log.d("AliSDK", "wToken:" + wtoken); // The console is configured with custom signing. // GET request. String url = "https://tigertally.aliyun.com/apptest"; String whash = TigerTallyAPI.vmpHash(TigerTallyAPI.RequestType.GET, url.getBytes()); String wtoken = TigerTallyAPI.vmpSign(1, whash.getBytes()); Log.d("AliSDK", "whash:" + whash + ", wtoken:" + wtoken); // POST request. String body = "hello world"; String whash = TigerTallyAPI.vmpHash(TigerTallyAPI.RequestType.POST, body.getBytes()); String wtoken = TigerTallyAPI.vmpSign(1, whash.getBytes()); Log.d("AliSDK", "whash:" + whash + ", wtoken:" + wtoken);ImportantWhen you call
vmpHashfor custom signing, the input parameter of thevmpSignmethod is the generated whash string. Furthermore, when you configure scenario-specific anti-bot policies for the app, the value of the Custom Signature Field must be set to ali_sign_whash.When you call
vmpHashto generate the whash for a GET request, ensure that the input URL is identical to the final URL used in the network request. Pay special attention to URL encoding. Some frameworks automatically perform URL encoding on Chinese characters or parameters.The input parameter of the
vmpHashmethod does not support empty strings. If the input is a URL, a path or parameter must exist.When you call
vmpSign, if the request body is empty (for example, the body of a POST or GET request is empty), pass a null object or the byte value of an empty string, such as "".getBytes("UTF-8").If the whash or wtoken is one of the following strings, an exception occurred during initialization:
you must call init first: Indicates that the
initmethod was not called.you must input correct data: Indicates that the input data is incorrect.
you must input correct type: Indicates that the input type is incorrect.
Perform two-factor authentication
Evaluate the result.
Check the cookie and body fields in the response to determine if a secondary verification is required. The header may contain multiple Set-Cookie entries, which must be merged into the cookie format before calling this interface.
/** * Evaluate whether to perform the two-factor authentication * * @param cookie Cookie * @param body Body * @return 0: Pass 1: Two-factor authentication */ public static int cptCheck(String cookie, String body)Parameters:
cookie: All cookies in the request response. Data type: String.
body: The entire body in the request response. Data type: String.
Return value: Returns the decision result. 0 indicates that the request passed. 1 indicates that two-factor authentication is required. Data type: int.
Sample code:
String cookie = "key1=value1;kye2=value2;"; String body = "...."; int recheck = TigerTallyAPI.cptCheck(cookie, body); Log.d("AliSDK", "recheck:" + recheck);
Create a slider.
Create a slider object based on the result returned by cptCheck. The TTCaptcha object provides the show and dismiss methods, which show and hide the slider window respectively. TTOption encapsulates the configurable parameters for the slider. TTListener contains two callback states for the slider. If you require a custom slider window, pass the address of the custom page. Both local HTML files and remote pages are supported.
/** * Create a slider object * * @param activity The current page activity * @param option The parameters * @param listener The callback * @return The slider verification object */ public static TTCaptcha cptCreate(Activity activity, TTOption option, TTListener listener); /** * The slider object */ public class TTCaptcha { /** * Show the slider */ public void show(); /** * Hide the slider */ public void dismiss(); /** * Obtain the slider traceId for data statistics */ public String getTraceId(); } /** * The slider parameters */ public static class TTOption { // Specifies whether to hide the slider by clicking a blank area. public boolean cancelable; // The custom page. Local HTML files and remote URLs are supported. public String customUri; // Set the language public String language; } /** * The slider callback */ public interface TTListener { /** * Verification successful * * @param captcha The slider object * @param data token, defaults to certifyId */ void success(TTCaptcha captcha, String data); /** * Verification failed * * @param captcha The slider object * @param code The error code */ void failed(TTCaptcha captcha, String code); }Parameters:
activity: The current page activity. Data type: Activity.
option: The slider configuration parameters. Data type: TTOption.
listener: The slider status callback. Data type: TTlistener.
Return value: A slider object. Data type: TTCaptcha.
Sample code:
TTCaptcha.TTOption option = new TTCaptcha.TTOption(); // option.customUri = "file:///android_asset/ali-tt-captcha-demo.html"; option.language = "cn"; option.cancelable = false; TTCaptcha captcha = TigerTallyAPI.cptCreate(this, option, new TTCaptcha.TTListener() { @Override public void success(TTCaptcha captcha, String data) { Log.d(TAG, "captcha check success:" + data); } @Override public void failed(TTCaptcha captcha, String code) { Log.d(TAG, "captcha check failed:" + code); } }); captcha.show();NoteAuthentication failed indicates that an exception was detected after the user finished sliding.
The following list describes the error codes:
1001: The verification failed.
1002: System exception.
1003: Parameter error.
1005: Verification canceled.
8001: Slider invocation error.
8002: Abnormal slider verification data.
8003: Internal slider verification exception.
8004: Network error.