Skip to main content

Overview

Protect sensitive AppTrove SDK credentials (SDK Key, Secret ID, Secret Key) by storing them securely using the Native Development Kit (NDK). This prevents keys from being exposed in plain text within your app's source code, reducing the risk of unauthorized access.

Two methods are provided:

  1. Using the com.klaxit.hiddensecrets Gradle plugin for automated key hiding
  2. Manual NDK setup with JNI for custom control

Purpose

Key hiding is essential for securing your AppTrove SDK integration:

  • Safeguard SDK Key, Secret ID, and Secret Key from reverse engineering
  • Available methods:
    • Method 1: Use com.klaxit.hiddensecrets plugin to automate key encryption in C++
    • Method 2: Manually create JNI C files for custom key storage

Prerequisites

  • AppTrove SDK: Version com.trackier:android-sdk:1.6.68 or later
  • Android: API 19+ (Android 4.4)
  • NDK: Installed via Android Studio (Tools > SDK Manager > SDK Tools > NDK)
  • CMake: Installed for Method 1 (same menu as NDK)
  • Trackier Panel: SDK Key, Secret ID, and Secret Key retrieved (see SDK Signing)
  • Permissions: Internet access

Method 1: Keys Hiding with com.klaxit.hiddensecrets Plugin

Use the com.klaxit.hiddensecrets Gradle plugin to automate key hiding in native C++ code, generating a Secrets class to access keys securely.

Setup

  1. Add Plugin: In your module-level build.gradle (e.g., app/build.gradle):

    plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'com.klaxit.hiddensecrets' version '0.2.0'
    }
  2. Sync Project:

    • Click "Sync Project with Gradle Files" in Android Studio
    • Verify the hideSecret task appears in Gradle tasks (View > Tool Windows > Gradle)

  1. Hide Keys: Run the following commands in the terminal (from your project root):

    ./gradlew hideSecret -Pkey=YOUR_SDK_KEY -PkeyName=SDKKey
    ./gradlew hideSecret -Pkey=YOUR_SECRET_ID -PkeyName=SecretId
    ./gradlew hideSecret -Pkey=YOUR_SECRET_KEY -PkeyName=SecretKey
    • Replace YOUR_SDK_KEY, YOUR_SECRET_ID, YOUR_SECRET_KEY with actual values from the Trackier Panel
    • keyName is optional; defaults to a random name if omitted
  2. Enable CMake: Add CMake configuration to your module-level build.gradle:

    android {
    // ...
    externalNativeBuild {
    cmake {
    path "src/main/cpp/CMakeLists.txt"
    }
    }
    }
  3. Verify Secrets Class: After running hideSecret, a Secrets class is generated in your project (e.g., app/src/main/java/com/example/myapp/Secrets.kt):

package com.example.myapp
public class Secrets {

static {
System.loadLibrary("secrets");
}

public native String getSDKKey(String packageName);
public native String getSecretId(String packageName);
public native String getSecretKey(String packageName);
}

Implementation

Use the Secrets class to retrieve hidden keys and initialize the AppTrove SDK.

MainApplication.java
package com.example.myapp;

import android.app.Application;
import com.trackier.sdk.TrackierSDK;
import com.trackier.sdk.TrackierSDKConfig;

public class MainApplication extends Application {

@Override
public void onCreate() {
super.onCreate();

// Retrieve hidden keys
Secrets secrets = new Secrets();
String sdkKey = secrets.getSDKKey(getPackageName());
String secretId = secrets.getSecretId(getPackageName());
String secretKey = secrets.getSecretKey(getPackageName());

// Configure SDK
TrackierSDKConfig sdkConfig = new TrackierSDKConfig(this, sdkKey, "development");
sdkConfig.setAppSecret(secretId, secretKey);
sdkConfig.disableOrganicTracking(true); // Optional

// Initialize SDK
TrackierSDK.initialize(sdkConfig);
}
}

Method 2: Keys Hiding with Custom NDK and JNI

Manually create JNI C files to store keys in native code, offering full control over the implementation.

Setup

  1. Create JNI Folder: In your project, create a folder: app/src/main/jni

  2. Add JNI Files: Create the following files in app/src/main/jni:

    Android.mk
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE := keys
    LOCAL_SRC_FILES := keys.c
    include $(BUILD_SHARED_LIBRARY)
    Application.mk
    APP_ABI := all
    keys.c
    #include <jni.h>

    JNIEXPORT jstring JNICALL
    Java_com_example_myapp_MainApplication_getSDKKey(JNIEnv *env, jobject instance) {
    return (*env)->NewStringUTF(env, "YOUR_SDK_KEY");
    }

    JNIEXPORT jstring JNICALL
    Java_com_example_myapp_MainApplication_getSecretId(JNIEnv *env, jobject instance) {
    return (*env)->NewStringUTF(env, "YOUR_SECRET_ID");
    }

    JNIEXPORT jstring JNICALL
    Java_com_example_myapp_MainApplication_getSecretKey(JNIEnv *env, jobject instance) {
    return (*env)->NewStringUTF(env, "YOUR_SECRET_KEY");
    }
    • Replace YOUR_SDK_KEY, YOUR_SECRET_ID, YOUR_SECRET_KEY with actual values
    • Update the JNI function names to match your package (com_example_myapp)
  3. Configure NDK Build: Add NDK configuration to your module-level build.gradle:

    android {
    // ...
    externalNativeBuild {
    ndkBuild {
    path "src/main/jni/Android.mk"
    }
    }
    }

  4. Sync Project: Sync Gradle to compile the native library

Implementation

Load the native library and call JNI methods to retrieve keys.

Kotlin Code (MainApplication.kt):

MainApplication.java
package com.example.myapp;

import android.app.Application;
import com.trackier.sdk.TrackierSDK;
import com.trackier.sdk.TrackierSDKConfig;

public class MainApplication extends Application {

static {
System.loadLibrary("keys");
}

public native String getSDKKey();
public native String getSecretId();
public native String getSecretKey();

@Override
public void onCreate() {
super.onCreate();

// Retrieve hidden keys
String sdkKey = getSDKKey();
String secretId = getSecretId();
String secretKey = getSecretKey();

// Configure SDK
TrackierSDKConfig sdkConfig = new TrackierSDKConfig(this, sdkKey, "development");
sdkConfig.setAppSecret(secretId, secretKey);
sdkConfig.disableOrganicTracking(true); // Optional

// Initialize SDK
TrackierSDK.initialize(sdkConfig);
}
}