Using Behavioral Module with Dynamic Feature
The Behavioral Module in the Credolab SDK enables passive, privacy-compliant behavioral events collection used for risk assessment and scoring. Proper initialization is required to ensure reliable data collection, especially when the module is packaged in a dynamic feature module (DFM) rather than the base APK.

Determine if manual initialization is required for your app
Auto Initialization
When the Behavioral Module is bundled into the base APK, it is initialized automatically via a ContentProvider
declared in the SDK. In this setup, no action is required from your side. Initialization occurs early in the application lifecycle and is safe to use immediately.
Auto-init is on if:
- The SDK is included directly in the base APK
- You don’t load the module conditionally at runtime
Dynamic Feature Modules
If the Behavioral Module is delivered as a dynamic feature module, auto-initialization will not work. Android does not process the ContentProvider
defined in the module’s manifest unless it is installed at app startup. As a result, the module must be initialized manually.
Use manual initialization if:
- The module is installed at runtime (e.g., via Play Feature Delivery)
- You want to defer initialization until a specific point
Manual Initialization
Manual initialization support was introduced in BehavioralModule
version 4.13.0
.
Step 1
To avoid compiling errors, ignore Behavioral Module's Content Provider from your app's AndroidManifest.
<application>
<!-- ignore Behavioral Module's ContentProvider if using manual init -->
<provider
android:authorities="${applicationId}.credoapp.behavioral.provider"
android:name="credoapp.module.behavioral.BehavioralProvider"
tools:node="remove"
tools:ignore="MissingClass" />
</application>
Step 2
CallBehavioralModule.init(context)
method
override fun onStateUpdate(state: SplitInstallSessionState) {
if (state.sessionId() == mySessionId) {
when (state.status()) {
SplitInstallSessionStatus.INSTALLED -> {
try {
// Load the BehavioralModule class
val clazz = Class.forName("credoapp.module.behavioral.BehavioralModule")
// init
clazz.getMethod("init", Context::class.java).invoke(null, applicationContext)
val intent =
Intent().setClassName("com.example", "com.example.dynamic.FeatureActivity")
startActivity(intent)
} catch (e: Exception) {
Log.e("SplitInstallManager", "Failed to initialize BehavioralModule", e)
}
}
}
}
}
class ExampleApp : SplitCompatApplication() {
override fun onCreate() {
super.onCreate()
initBehavioralModule(applicationContext)
}
private fun initBehavioralModule(context: Context) {
CoroutineScope(Dispatchers.Default).launch {
try {
val clazz = Class.forName("credoapp.module.behavioral.BehavioralModule")
// init
clazz.getMethod("init", Context::class.java).invoke(null, context)
Log.d("ExampleApp", "BehavioralModule initialized successfully")
} catch (e: ClassNotFoundException) {
Log.d("ExampleApp", "BehavioralModule not found")
} catch (e: Exception) {
Log.e("ExampleApp", "init() failed", e)
}
}
}
}
Initialize earlyCall
init(context)
method early, before transitioning to any activity expected to be tracked.
Step 3
Now you can safely callstartTracking()
method later in your code. Just make sure to call init before starting that Activity or any other user flow.
class FeatureActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
BehavioralModule.startTracking()
}
}
FAQ
Can I call startTracking() before init() method?
No. The SDK requires successful initialization first.
Is init() thread-safe?
Yes. Parallel calls are safely handled.
Updated about 23 hours ago