Skip to main content
Documentation for version v73

SDK Configuration

Prerequisites

  • The app includes a class that extends Application.
  • The project is connected to the Maven Central repository.
  • Add the library dependency to the app-level build.gradle.kts file:
    dependencies {
implementation("com.altcraft:android-sdk:0.0.1")
}

App Preparation

Configuring the JWT interface (optional)

JWTInterface is an interface for requesting a JWT token. It provides the current JWT token from the app on demand by the SDK. Implement this interface if you use JWT authentication for API requests. JWT confirms that user identifiers are authenticated by the application.

JWT authentication is required if you use a matching type other than push data from subscription (for example, the user identifier is an email or a phone number).

SDK interface:

interface JWTInterface {
fun getJWT(): String?
}
App-side implementation
import android.content.Context
import com.altcraft.sdk.interfaces.JWTInterface

class JWTProvider(): JWTInterface {
override fun getJWT(): String? {
// code that returns a 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.setJWTProvider(JWTProvider(applicationContext))
}
}
Note

getJWT() is a synchronous function. The SDK execution thread will be paused until the JWT is obtained. It is recommended that getJWT() return a value immediately from a cache (in-memory, SharedPreferences, or EncryptedSharedPreferences) to speed up requests. Ideally, prepare a current JWT as early as possible (at app start) and store it in cache so the token is available to the SDK without delays. If no value is available, returning null is acceptable.

Preparing to work with push providers

To prepare the app for working with push providers, you need to:

  • Integrate the push providers’ SDKs into the project.
  • Implement the SDK interfaces for passing and deleting the push token.
  • Extend the push providers’ services.
  • Register the push provider service in AndroidManifest.xml.

Firebase Cloud Messaging

Integrating the FCM SDK into the project

LINK TO DOCUMENTATION

Altcraft SDK interface implementation

FCMInterface is an interface for requesting and deleting the FCM push token:

  • Passes the FCM token to Altcraft SDK
  • Deletes the FCM token at the request of Altcraft SDK

SDK interface:

interface FCMInterface {
suspend fun getToken(): String?
suspend fun deleteToken(completion: (Boolean) -> Unit)
}
Recommended app-side implementation
import com.altcraft.sdk.interfaces.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 suspend 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

class App : Application() {
override fun onCreate() {
super.onCreate()
AltcraftSDK.pushTokenFunctions.setFCMTokenProvider(FCMProvider())
}
}
Extending the provider service

Recommended FCMService implementation that forwards the notification to the takePush() function:

import com.altcraft.sdk.AltcraftSDK
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.PushReceiver.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

LINK TO DOCUMENTATION

Altcraft SDK interface implementation

HMSInterface is an interface for requesting and deleting the HMS push token.

SDK interface:

import android.content.Context

interface HMSInterface {
suspend fun getToken(context: Context): String?
suspend fun deleteToken(context: Context, complete: (Boolean) -> Unit)
}
Recommended app-side implementation
import android.content.Context
import com.altcraft.sdk.interfaces.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 suspend 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

class App : Application() {
override fun onCreate() {
super.onCreate()
AltcraftSDK.pushTokenFunctions.setHMSTokenProvider(HMSProvider())
}
}
Extending the provider service

Recommended HMSService implementation that forwards the notification to the takePush() function:

import com.altcraft.sdk.AltcraftSDK
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.PushReceiver.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

LINK TO DOCUMENTATION

Altcraft SDK interface implementation

RustoreInterface is an interface for requesting and deleting the RuStore push token.

SDK interface:

interface RustoreInterface {
suspend fun getToken(): String?
suspend fun deleteToken(complete: (Boolean) -> Unit)
}
Recommended app-side implementation
import com.altcraft.sdk.interfaces.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 suspend 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

class App : Application() {
override fun onCreate() {
super.onCreate()
AltcraftSDK.pushTokenFunctions.setRuStoreTokenProvider(RuStoreProvider())
}
}
Extending the provider service

Recommended RuStoreService implementation that forwards the notification to the takePush() function:

import com.altcraft.sdk.AltcraftSDK
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.PushReceiver.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

Use the AltcraftConfiguration class to pass configuration parameters:

class AltcraftConfiguration private constructor(
private val apiUrl: String,
private val icon: Int? = null,
private val rToken: String? = null,
private val usingService: Boolean = false,
private val serviceMessage: String? = null,
private val appInfo: DataClasses.AppInfo? = null,
private val providerPriorityList: List<String>? = null,
private val pushReceiverModules: List<String>? = null,
private val pushChannelName: String? = null,
private val pushChannelDescription: String? = null
)

Parameter descriptions:

apiUrl String

Required: Yes Description: URL of the Altcraft API endpoint.


icon Int?

Default: null Required: No Description: Resource ID of the drawable used as the notification icon.


rToken String?

Default: null Required: No Description: Altcraft role token (identifies a resource, database, or account). Used when the only matching type is the device push token issued by the provider.


usingService Boolean

Default: false Required: No Description: Enables use of foreground services when subscribing and when updating the push token. Provides up to ~1 minute of guaranteed network window even if the app is minimized/closed (Android requirement: show a service notification). Not mandatory in most cases, but useful on unstable networks.


serviceMessage String?

Default: null Required: No Description: Notification text for foreground services and WorkManager tasks (if null, "background process" is used). It’s recommended to set explicitly—notifications may appear in the background while processing push content.


appInfo DataClasses.AppInfo?

Default: null Required: No Description: Basic app metadata for Firebase Analytics. To set it, use the public SDK data class AppInfo (package com.altcraft.sdk.data.DataClasses):

data class AppInfo(
/** Firebase app_id */
val appID: String,
/** Firebase app_instance_id */
val appIID: String,
/** Firebase app_version */
val appVer: String
)

providerPriorityList List<String>?

Default: null Required: No Description: Provider priority list. Used to automatically refresh the subscription’s push token if a higher-priority provider’s token is unavailable. Priority is defined by index in the list: index 0 is the highest.

Usage example:

providerPriorityList = listOf(
"android-firebase",
"android-huawei",
"android-rustore"
)

With this setup:

  • The SDK first requests FCM; if FCM is unavailable—HMS; if HMS is unavailable—RuStore.
  • Works provided the corresponding provider interfaces are implemented in the app.

For convenience, the SDK exposes public constants:

const val FCM_PROVIDER: String = "android-firebase"
const val HMS_PROVIDER: String = "android-huawei"
const val RUS_PROVIDER: String = "android-rustore"

If not set, the default provider priority is:

FCM_PROVIDER → HMS_PROVIDER → RUS_PROVIDER

The value may contain a single element—in this case only that provider will be used, regardless of push-token availability.

You can omit this parameter if:

  • the project uses only one provider;
  • the default priority meets your requirements.
Use cases

Case 1. Priority RUS_PROVIDER → FCM_PROVIDER. A user removes RuStore—RuStore notifications become unavailable. With the recommended RustoreInterface.getToken() implementation returning null, the SDK automatically switches to FCM, updates the subscription token, and communications continue. Case 2. Parameter not set; defaults FCM_PROVIDER → HMS_PROVIDER → RUS_PROVIDER apply. On a Huawei device without Google services the SDK automatically switches to HMS with no extra code.


pushReceiverModules List<String>?

Default: null Required: No Description: List of package names containing implementations of AltcraftPushReceiver : AltcraftSDK.PushReceiver().

If set, the SDK discovers these classes and forwards incoming notifications to them via pushHandler(context: Context, message: Map<String, String>). If no classes are found in any of the packages, the notification will be displayed by the SDK.

Example of creating an AltcraftPushReceiver class
package com.altcraft.altcraftmobile.test

import android.content.Context
import androidx.annotation.Keep
import com.altcraft.sdk.AltcraftSDK

@Keep
class AltcraftPushReceiver: AltcraftSDK.PushReceiver() {
override fun pushHandler(context: Context, message: Map<String, String>) {

// handle the notification using SDK functions
super.pushHandler(context, message)

// additional notification handling logic
}
}
Use case

Case: The app contains multiple modules that need Altcraft incoming push data. In each module you can create a class AltcraftPushReceiver: AltcraftSDK.PushReceiver() and receive the incoming push as message: Map<String, String>.

Note the class must be named exactly AltcraftPushReceiver.

If the project has only one AltcraftPushReceiver, call super.pushHandler(context, message) inside pushHandler so the SDK processes the notification correctly. If there are multiple such classes, keep the super.pushHandler call in only one of them—otherwise each notification will be duplicated. If you want full manual control of push handling, you can omit super.pushHandler.


pushChannelName String?

Default: null Required: No Description: Base name of the push-notification channel (visible in Android settings). Depending on the sound/vibration settings of the Altcraft platform’s push template, a suffix is added:

  • allSignal — sound and vibration enabled
  • soundless — silent channel
  • onlySound — sound only (no vibration)

Example: with pushChannelName = "Altcraft" and mode allSignal, the visible channel name is "Altcraft_allSignal". If not set, the SDK uses default names: "allSignal", "soundless", "onlySound".


pushChannelDescription String?

Default: null Required: No Description: Description of the push channel (visible in Android settings). The notification mode is appended:

  • Vibration and sound enabled
  • Vibration and sound disabled
  • Sound enabled, vibration disabled

Example: "Altcraft notification channel. (vibration and sound enabled)". If not set, the SDK uses these defaults:

  • iconaltcraft-sdk/src/main/res/drawable/icon.xml (if icon = null)
  • serviceMessage"background process" (if serviceMessage = null)
  • providerPriorityListFCM_PROVIDER → HMS_PROVIDER → RUS_PROVIDER (if null)
  • pushChannelName"allSignal", "soundless", "onlySound" (if null)
  • pushChannelDescription"Vibration and sound enabled", "Vibration and sound disabled", "Sound enabled, vibration disabled" (if null)

Running initialization

Note

Call AltcraftSDK.initialization(...) when needed, but only after registering all providers (the JWT provider and push-token providers). Execute requests after the configuration is set.

Use fun initialization(context: Context, configuration: AltcraftConfiguration, complete: ((Result<Unit>) -> Unit)? = null) to initialize the SDK:

// Initialize the SDK and set configuration

AltcraftSDK.initialization(
context = context,
configuration = config,
complete = null // optional
)
Example of correct initialization order in Application.onCreate() (after registering providers)
import android.app.Application
import com.altcraft.sdk.AltcraftSDK
import com.altcraft.sdk.config.AltcraftConfiguration
import com.altcraft.sdk.data.DataClasses
import com.altcraft.fcm.FCMProvider
import com.altcraft.hms.HMSProvider
import com.altcraft.rustore.RuStoreProvider
import ru.rustore.sdk.pushclient.RuStorePushClient

class App : Application() {
override fun onCreate() {
super.onCreate()

// Initialize the RuStore SDK provider (if used)
RuStorePushClient.init(this, "rustore-project-id-1234")

// Register providers before initializing the SDK
AltcraftSDK.setJWTProvider(JWTProvider(applicationContext))
AltcraftSDK.pushTokenFunctions.setFCMTokenProvider(FCMProvider())
AltcraftSDK.pushTokenFunctions.setHMSTokenProvider(HMSProvider())
AltcraftSDK.pushTokenFunctions.setRuStoreTokenProvider(RuStoreProvider())

// SDK configuration
val config = AltcraftConfiguration.Builder(
apiUrl = "https://pxl-example.altcraft.com",
icon = R.drawable.ic_notification
).build()

// Initialization
AltcraftSDK.initialization(this, config)
}
}
Example of minimal working setup
val config = AltcraftConfiguration.Builder(
apiUrl = "https://pxl-example.altcraft.com"
).build()

AltcraftSDK.initialization(context, config)
Example of full parameter configuration
val config = AltcraftConfiguration.Builder(
apiUrl = "https://pxl-example.altcraft.com",
icon = R.drawable.ic_notification,
rToken = null,
usingService = true,
serviceMessage = "Processing Altcraft operations…",
appInfo = DataClasses.AppInfo(
appID = "com.example.app",
appIID = "8b91f3a0-1111-2222-3333-c1a2c1a2c1a2",
appVer = "1.0.0"
),
providerPriorityList = listOf(
FCM_PROVIDER, // "android-firebase"
HMS_PROVIDER, // "android-huawei"
RUS_PROVIDER // "android-rustore"
),
pushReceiverModules = listOf(
context.packageName,
"com.example.push_receiver",
"com.example.feature.test"
),
pushChannelName = "Altcraft",
pushChannelDescription = "Altcraft notifications channel"
).build()

AltcraftSDK.initialization(context, config)
Example of initialization with completion callback
AltcraftSDK.initialization(context, config) { result ->
when {
result.isSuccess -> {
// actions on successful initialization
}
result.isFailure -> {
// handle initialization errors
}
}
}