SDK Configuration
Prerequisites
- The push notification provider SDKs are integrated into the app project (see the push provider integration instructions).
- A class extending Application has been added to the app.
- The Maven Central repository is connected in the project.
- The SDK module dependencies have been added to the app-level
build.gradle.ktsfile (app level):
dependencies {
implementation("com.altcraft:android-sdk-core:X.Y.Z")
implementation("com.altcraft:android-sdk-push:X.Y.Z")
// if needed — other modules:
// implementation("com.altcraft:android-sdk-target:X.Y.Z")
// implementation("com.altcraft:android-sdk-profile:X.Y.Z")
// implementation("com.altcraft:android-sdk-inapp:X.Y.Z")
}
A module is activated by adding its dependency: each module registers automatically at app startup, no separate registration is required.
App preparation
Setting up the JWT interface (optional)
JWTInterface is the interface for requesting a JWT token. It provides the current JWT token from the app upon SDK request. Implementing this interface is required if JWT authentication of API requests is used. The JWT confirms that the user identifiers are authenticated by the app.
Implementing JWT authentication is mandatory if a matching type other than push data from the subscription is used (for example, the user identifier is an email or phone number).
SDK interface:
interface JWTInterface {
fun getJWT(): String?
}
Implementation on the app side
import android.content.Context
import com.altcraft.sdk.platform.authenticate.external.jwt.JWTInterface
class JWTProvider(): JWTInterface {
override fun getJWT(): String? {
// code that returns the JWT token
}
}
Registering the provider in Application.onCreate()
import android.app.Application
import com.altcraft.sdk.AltcraftSDK
class App : Application() {
override fun onCreate() {
super.onCreate()
AltcraftSDK.auth.setJWTProvider(JWTProvider(applicationContext))
}
}
getJWT() is a synchronous function. The SDK execution flow will be suspended until the JWT is received. It is recommended that getJWT() return a value immediately — from a cache (in-memory, SharedPreferences, or EncryptedSharedPreferences) — this will speed up request execution. It is advisable to prepare the current JWT as early as possible (at app startup) and store it in a cache so that when the SDK accesses it, the token is available without delays. If no value is available, it is permissible to return null.
Preparing to work with push providers
To preliminarily prepare the app for working with push providers, you need to:
- Integrate the push provider SDKs into the project;
- Implement the SDK interfaces for transferring and deleting the push token;
- Extend the push provider services;
- Register the push provider service in
AndroidManifest.xml.
Firebase Cloud Messaging
Integrating the FCM SDK into the project
The article on integrating FCM is available here.
Implementing the Altcraft SDK interface
FCMInterface is the interface for requesting and deleting the FCM push token:
- Transfers the FCM token to Altcraft SDK
- Deletes the FCM token upon Altcraft SDK request
SDK interface:
interface FCMInterface {
suspend fun getToken(): String?
fun deleteToken(completion: (Boolean) -> Unit)
}
Recommended implementation on the app side
import com.altcraft.sdk.push.platform.token.provider.FCMInterface
import com.google.firebase.Firebase
import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.messaging.messaging
import kotlinx.coroutines.tasks.await
class FCMProvider : FCMInterface {
override suspend fun getToken(): String? = try {
Firebase.messaging.token.await()
} catch (_: Exception) {
null
}
override fun deleteToken(completion: (Boolean) -> Unit) {
try {
FirebaseMessaging.getInstance().deleteToken().addOnCompleteListener {
completion(it.isSuccessful)
}
} catch (_: Exception) {
completion(false)
}
}
}
Registering the provider in Application.onCreate()
import android.app.Application
import com.altcraft.sdk.AltcraftSDK
import com.altcraft.sdk.push.push
class App : Application() {
override fun onCreate() {
super.onCreate()
AltcraftSDK.push.token.setFCMTokenProvider(FCMProvider())
}
}
Implementing the provider service
Recommended implementation of FCMService that passes the notification to the takePush() function:
import com.altcraft.sdk.AltcraftSDK
import com.altcraft.sdk.push.push
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
/**
* FCM service for handling push tokens and messages.
*/
class FCMService : FirebaseMessagingService() {
/**
* Called when a new FCM token is generated.
*
* @param token The new FCM token.
*/
override fun onNewToken(token: String) {
super.onNewToken(token)
}
/**
* Called when a push message is received.
*
* @param message The received [RemoteMessage].
*/
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
AltcraftSDK.push.receiver.takePush(this@FCMService, message.data)
}
}
Registering the push provider service in AndroidManifest.xml
<service
android:name="<your_package_name>.FCMService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Huawei Mobile Services
Integrating the HMS SDK into the project
The article on integrating HMS is available here.
Implementing the Altcraft SDK interface
HMSInterface is the interface for requesting and deleting the HMS push token.
SDK interface:
import android.content.Context
interface HMSInterface {
suspend fun getToken(context: Context): String?
fun deleteToken(context: Context, complete: (Boolean) -> Unit)
}
Recommended implementation on the app side
import android.content.Context
import com.altcraft.sdk.push.platform.token.provider.HMSInterface
import com.huawei.agconnect.AGConnectOptionsBuilder
import com.huawei.hms.aaid.HmsInstanceId
import com.huawei.hms.api.HuaweiApiAvailability
private const val APP_ID = "client/app_id"
private const val TOKEN_SCOPE = "HCM"
class HMSProvider : HMSInterface {
override suspend fun getToken(context: Context): String? = try {
val availability = HuaweiApiAvailability.getInstance()
.isHuaweiMobileServicesAvailable(context)
if (availability != com.huawei.hms.api.ConnectionResult.SUCCESS) return null
val appId = AGConnectOptionsBuilder().build(context).getString(APP_ID)
HmsInstanceId.getInstance(context).getToken(appId, TOKEN_SCOPE)
} catch (e: Exception) {
null
}
override fun deleteToken(context: Context, complete: (Boolean) -> Unit) {
try {
val appId = AGConnectOptionsBuilder().build(context).getString(APP_ID)
HmsInstanceId.getInstance(context).deleteToken(appId, TOKEN_SCOPE)
complete(true)
} catch (e: Exception) {
complete(false)
}
}
}
Registering the provider in Application.onCreate()
import android.app.Application
import com.altcraft.sdk.AltcraftSDK
import com.altcraft.sdk.push.push
class App : Application() {
override fun onCreate() {
super.onCreate()
AltcraftSDK.push.token.setHMSTokenProvider(HMSProvider())
}
}
Implementing the provider service
Recommended implementation of HMSService that passes the notification to the takePush() function:
import com.altcraft.sdk.AltcraftSDK
import com.altcraft.sdk.push.push
import com.huawei.hms.push.HmsMessageService
import com.huawei.hms.push.RemoteMessage
/**
* HMS service for handling push tokens and incoming notifications.
*
* Extends [HmsMessageService] and overrides key HMS callback methods.
*/
class HMSService : HmsMessageService() {
/**
* Called when a new HMS token is generated.
*
* @param token The new HMS token.
*/
override fun onNewToken(token: String) {
super.onNewToken(token)
}
/**
* Called when a push message is received from HMS.
*
* Forwards the message with additional metadata to all receivers.
*
* @param message The received [RemoteMessage].
*/
override fun onMessageReceived(message: RemoteMessage) {
AltcraftSDK.push.receiver.takePush(this@HMSService, message.dataOfMap)
}
}
Registering the push provider service in AndroidManifest.xml
<service
android:name="<your_package_name>.HMSService"
android:exported="false">
<intent-filter>
<action android:name="com.huawei.push.action.MESSAGING_EVENT" />
</intent-filter>
</service>
RuStore
Integrating the RuStore SDK into the project
The article on integrating RuStore is available here.
Implementing the Altcraft SDK interface
RustoreInterface is the interface for requesting and deleting the RuStore push token.
SDK interface:
interface RustoreInterface {
suspend fun getToken(): String?
fun deleteToken(complete: (Boolean) -> Unit)
}
Recommended implementation on the app side
import com.altcraft.sdk.push.platform.token.provider.RustoreInterface
import kotlinx.coroutines.CompletableDeferred
import ru.rustore.sdk.core.feature.model.FeatureAvailabilityResult
import ru.rustore.sdk.pushclient.RuStorePushClient
class RuStoreProvider : RustoreInterface {
override suspend fun getToken(): String? {
val deferred = CompletableDeferred<String?>()
try {
val token = RuStorePushClient.getToken().await()
RuStorePushClient.checkPushAvailability()
.addOnSuccessListener { result ->
when (result) {
FeatureAvailabilityResult.Available -> deferred.complete(token)
is FeatureAvailabilityResult.Unavailable -> deferred.complete(null)
}
}
.addOnFailureListener { deferred.complete(null) }
} catch (e: Exception) {
return null
}
return deferred.await()
}
override fun deleteToken(complete: (Boolean) -> Unit) {
try {
RuStorePushClient.deleteToken()
.addOnSuccessListener { complete(true) }
.addOnFailureListener { complete(false) }
} catch (e: Exception) {
complete(false)
}
}
}
Registering the provider in Application.onCreate()
import android.app.Application
import com.altcraft.sdk.AltcraftSDK
import com.altcraft.sdk.push.push
class App : Application() {
override fun onCreate() {
super.onCreate()
AltcraftSDK.push.token.setRuStoreTokenProvider(RuStoreProvider())
}
}
Implementing the provider service
Recommended implementation of RuStoreService that passes the notification to the takePush() function:
import com.altcraft.sdk.AltcraftSDK
import com.altcraft.sdk.push.push
import ru.rustore.sdk.pushclient.messaging.model.RemoteMessage
import ru.rustore.sdk.pushclient.messaging.service.RuStoreMessagingService
/**
* RuStore service for handling push notifications.
*
* Extends [RuStoreMessagingService] and overrides key callbacks.
*/
class RuStoreService : RuStoreMessagingService() {
override fun onNewToken(token: String) {
super.onNewToken(token)
}
/**
* Called when a push message is received.
*
* Forwards the message to all receivers with added metadata.
*
* @param message The received RemoteMessage.
*/
override fun onMessageReceived(message: RemoteMessage) {
AltcraftSDK.push.receiver.takePush(this, message.data)
}
}
Registering the push provider service in AndroidManifest.xml
<service
android:name="<your_package_name>.RuStoreService"
android:exported="true"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="ru.rustore.sdk.pushclient.MESSAGING_EVENT" />
</intent-filter>
</service>
SDK initialization
Initialization parameters
The AltcraftConfiguration class is used to pass configuration parameters:
class AltcraftConfiguration private constructor(
val apiUrl: String,
val rToken: String? = null,
val appInfo: AppInfo? = null,
val enableLogging: Boolean? = null
)
The settings of individual modules are passed as separate configurations and added to the Builder via addModuleConfiguration(). For the push and in-app modules, the SDK provides the pushConfig() and inAppConfig() extensions.
Parameter descriptions:
apiUrl String
Mandatory: Yes
Description: URL of the Altcraft API endpoint
rToken String?
Default: null
Mandatory: No
Description: Altcraft role token (identifies a resource, database, or account). Used when the only matching type is the device push token issued by a provider.
appInfo AppInfo?
Default: null
Mandatory: No
Description: Basic app metadata for Firebase Analytics. To set it, use the SDK's public data class AppInfo (package com.altcraft.sdk.data.models):
data class AppInfo(
/** Firebase app_id */
val appID: String = "",
/** Firebase app_instance_id */
val appIID: String = "",
/** Firebase app_version */
val appVer: String = ""
)
enableLogging Boolean?
Default: null
Mandatory: No
Description: Enables/disables logging. Logs can be found by the logCat tag altcraft_lib.
Push module configuration
The PushConfiguration class (package com.altcraft.sdk.push.config) contains the push module settings and is added to the Builder by calling pushConfig():
class PushConfiguration(
val icon: Int? = null,
val providerPriority: List<String> = emptyList(),
val pushReceiverModules: List<String> = emptyList(),
val pushChannelName: String? = null,
val pushChannelDescription: String? = null
)
icon Int?
Default: null
Mandatory: No
Description: Identifier of the drawable resource used as the notification icon
providerPriority List<String>
Default: empty list
Mandatory: No
Description: List of provider priorities. Used to automatically update the subscription push token if the token of a higher-priority provider is unavailable. Priority is determined by the index in the list: the element with index 0 is the highest priority.
Usage example:
providerPriority = listOf(
Constants.FCM_PROVIDER,
Constants.HMS_PROVIDER,
Constants.RUS_PROVIDER
)
With this configuration:
- The SDK first requests the FCM token; if FCM is unavailable — HMS; if HMS is unavailable — RuStore;
- It works provided that the interfaces of the corresponding providers are implemented in the app.
For convenience when setting the parameter value, the SDK contains public constants in the Constants object (package com.altcraft.sdk.push.data):
object Constants {
const val FCM_PROVIDER: String = "android-firebase"
const val HMS_PROVIDER: String = "android-huawei"
const val RUS_PROVIDER: String = "android-rustore"
}
If the value is not set, the provider priority is as follows:
FCM_PROVIDER —> HMS_PROVIDER —> RUS_PROVIDER
The parameter value can contain a single element — in this case, only one provider is used, regardless of push token availability.
The parameter can be omitted if:
- only one provider is used in the project;
- the default priority meets the requirements.
Case 1. Priority RUS_PROVIDER —> FCM_PROVIDER. The user deletes RuStore — RuStore notifications become unavailable. With the recommended implementation of RustoreInterface.getToken(), null is returned, the SDK automatically switches to FCM, updates the subscription token, and communications are preserved.
Case 2. The parameter is not set; the default values FCM_PROVIDER —> HMS_PROVIDER —> RUS_PROVIDER apply. On a Huawei device without Google services, the SDK automatically switches to HMS without additional code.
pushReceiverModules List<String>
Default: empty list
Mandatory: No
Description: List of package names containing the implementations of AltcraftPushReceiver : PushReceiver().
If specified, the SDK detects these classes and passes the incoming notification to them (via pushHandler(context: Context, message: Map<String, String>)). If the classes are not found in any of the packages, the notification is displayed by the SDK itself.
Example of creating the AltcraftPushReceiver class
package com.altcraft.altcraftmobile.test
import android.content.Context
import androidx.annotation.Keep
import com.altcraft.sdk.push.PushReceiver
@Keep
class AltcraftPushReceiver: PushReceiver() {
override suspend fun pushHandler(context: Context, message: Map<String, String>) {
// handle the notification using SDK functions
super.pushHandler(context, message)
// additional notification handling logic
}
}
Case: The app contains several modules that need the data of incoming Altcraft push notifications. In each of these modules, you can create a class AltcraftPushReceiver: PushReceiver() and receive the incoming push notification as message: Map<String, String>.
Note that the class must be named AltcraftPushReceiver.
If the project has only one AltcraftPushReceiver class, the pushHandler method must call super.pushHandler(context, message) so that the notification is correctly processed by the SDK. If there are several such classes, the super.pushHandler call should be kept in only one of them — otherwise each notification will be duplicated. If you want to fully control the handling of push notifications yourself, the super.pushHandler call can be omitted.
pushChannelName String?
Default: null
Mandatory: No
Description: Base name of the push notification channel (visible in Android settings). Depending on the sound and vibration settings of the push template in Altcraft Platform, a suffix is added to the name:
allSignal— sound and vibration enabled;soundless— silent channel;onlySound— sound only (no vibration).
Example: with pushChannelName = "Altcraft" and the allSignal mode, the visible channel name is "Altcraft_allSignal". If the parameter is not specified — the SDK uses the default names: "allSignal", "soundless", "onlySound".
pushChannelDescription String?
Default: null
Mandatory: No
Description: Description of the push channel (visible in Android settings). The notification mode is added to the description:
Vibration and sound enabled;Vibration and sound disabled;Sound enabled, vibration disabled.
Example: "Altcraft notification channel. (vibration and sound enabled)".
If the parameter is not specified — the SDK uses the default values:
- icon — the icon from the SDK resources (if icon = null);
- providerPriority —
FCM_PROVIDER —> HMS_PROVIDER —> RUS_PROVIDER(if the list is empty); - pushChannelName —
"allSignal", "soundless", "onlySound"(if null); - pushChannelDescription —
"Vibration and sound enabled", "Vibration and sound disabled", "Sound enabled, vibration disabled"(if null).
In-App module configuration
The InAppConfiguration class (package com.altcraft.sdk.inapp.config) contains the In-App module settings and is added to the Builder by calling inAppConfig():
class InAppConfiguration(
val inAppAutoRequest: Boolean = true
)
inAppAutoRequest Boolean
Default: true
Mandatory: No
Description: When set to true, the SDK automatically requests In-App placements at initialization and every 30 minutes. If false, the placements request is performed only upon an explicit call to getPlacements() or when triggers fire.
Performing initialization
Call AltcraftSDK.initialization(...) when needed, but only after registering all the providers (the JWT provider and the push token providers). Requests should be performed after the configuration is set.
The fun initialization(context: Context, configuration: AltcraftConfiguration, complete: ((Result<Unit>) -> Unit)? = null) function is used to initialize the SDK:
// SDK initialization and configuration setup
AltcraftSDK.initialization(
context = context,
configuration = config,
complete = null // optional
)
Example of the correct initialization order in Application.onCreate() (after registering the providers)
import android.app.Application
import com.altcraft.sdk.AltcraftSDK
import com.altcraft.sdk.config.AltcraftConfiguration
import com.altcraft.sdk.push.config.PushConfiguration
import com.altcraft.sdk.push.config.pushConfig
import com.altcraft.sdk.push.push
import <your_package_name>.FCMProvider
import <your_package_name>.HMSProvider
import <your_package_name>.RuStoreProvider
import ru.rustore.sdk.pushclient.RuStorePushClient
class App : Application() {
override fun onCreate() {
super.onCreate()
// Initialize the Rustore provider SDK (if used)
RuStorePushClient.init(this, "rustore-project-id-1234")
// Register the providers before SDK initialization
AltcraftSDK.auth.setJWTProvider(JWTProvider(applicationContext))
AltcraftSDK.push.token.setFCMTokenProvider(FCMProvider())
AltcraftSDK.push.token.setHMSTokenProvider(HMSProvider())
AltcraftSDK.push.token.setRuStoreTokenProvider(RuStoreProvider())
// SDK configuration
val config = AltcraftConfiguration.Builder(
apiUrl = "https://pxl-example.altcraft.com"
)
.pushConfig(
PushConfiguration(
icon = R.drawable.ic_notification
)
)
.build()
// Initialization
AltcraftSDK.initialization(this, config)
}
}
Example of a minimal working configuration
val config = AltcraftConfiguration.Builder(
apiUrl = "https://pxl-example.altcraft.com"
).build()
AltcraftSDK.initialization(context, config)
Example of configuring all parameters
val config = AltcraftConfiguration.Builder(
apiUrl = "https://pxl-example.altcraft.com",
rToken = null,
appInfo = AppInfo(
appID = "com.example.app",
appIID = "8b91f3a0-1111-2222-3333-c1a2c1a2c1a2",
appVer = "1.0.0"
),
enableLogging = true
)
.pushConfig(
PushConfiguration(
icon = R.drawable.ic_notification,
providerPriority = listOf(
Constants.FCM_PROVIDER,
Constants.HMS_PROVIDER,
Constants.RUS_PROVIDER
),
pushReceiverModules = listOf(
context.packageName,
"com.example.push_receiver",
"com.example.feature.test"
),
pushChannelName = "Altcraft",
pushChannelDescription = "Altcraft notifications channel"
)
)
.inAppConfig(
InAppConfiguration(
inAppAutoRequest = true
)
)
.build()
AltcraftSDK.initialization(context, config)
Example of initialization with a completion callback
AltcraftSDK.initialization(context, config) { result ->
when {
result.isSuccess -> {
// actions on successful initialization
}
result.isFailure -> {
// initialization error handling
}
}
}