Skip to main content

SDK push notifications for Kotlin and Java (version 6.4.0)

Push notifications prerequisites.

Important
  • Test build signature (for example: debug) of the app must match the signature of the app build that was uploaded to the console and passed moderation (for example, release).
  • The SDK used is up-to-date.
  • App uploaded to RuStore Console.
  • App passed moderation (you don't have to publish the app).
  • The current version of RuStore is installed on the user's device.
  • RuStore app supports push notifications.
  • The RuStore app is allowed to run in the background. Without this permission push notification will still be received, although, with a significant lag.
  • The signature fingerprint of the app installed on the device matches the signature fingerprint of the app uploaded to RuStore Console.

Implementation example

Check out the example app to learn how to properly integrate Push Notifications SDK.

Integrate into your project

Connect the repository

build.gradle
repositories {
maven {
url = uri("https://artifactory-external.vkpartner.ru/artifactory/maven")
}
}

Dependency injection

build.gradle
dependencies {
implementation("ru.rustore.sdk:pushclient:6.4.0")
}

Edit app manifest

Declare a service that extends RuStoreMessagingService:

AndroidManifest.xml
<service
android:name=".MyRuStoreMessagingService"
android:exported="true"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="ru.rustore.sdk.pushclient.MESSAGING_EVENT" />
</intent-filter>
</service>

If you need to change the icon or colour of the standard notification, add:

AndroidManifest.xml
<meta-data
android:name="ru.rustore.sdk.pushclient.default_notification_icon"
android:resource="@drawable/ic_baseline_android_24" />
<meta-data
android:name="ru.rustore.sdk.pushclient.default_notification_color"
android:resource="@color/your_favorite_color" />

If you need to override the notification channel, add:

AndroidManifest.xml
<meta-data
android:name="ru.rustore.sdk.pushclient.default_notification_channel_id"
android:value="@string/pushes_notification_channel_id" />

You must create the channel yourself if you add a push notification channel.

Request permission to show push notifications in Android 13+

The Android 13 version has a new permission to display push notifications. This will affect all apps that run on Android 13 or higher and use RuStore Push SDK.

By default, RuStore Push SDK version 1.4.0 and above includes the POST_NOTIFICATIONS permission defined in the manifest. However, the application also needs to request this permission at runtime via the android.permission.POST_NOTIFICATIONS constant. The app will only be able to show push notifications if the user grants a permission.

Request permission to show push notifications:

Activity/Fragment
// Declare the launcher at the top of your Activity/Fragment:
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission(),
) { isGranted: Boolean ->
if (isGranted) {
// RuStore Push SDK (and your app) can post notifications.
} else {
// TODO: Inform user that your app will not show notifications.
}
}

private fun askNotificationPermission() {
// This is only necessary for API level>= 33 (TIRAMISU)
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) ==
PackageManager.PERMISSION_GRANTED
) {
// RuStore Push SDK (and your app) can post notifications.
} else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
// TODO: display an educational UI explaining to the user the features that will be enabled
// by them granting the POST_NOTIFICATION permission. This UI should provide the user
// "OK" and "No thanks" buttons. If the user selects "OK," directly request the permission.
// If the user selects "No thanks," allow the user to continue without notifications.
} else {
// Directly ask for the permission
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
}
}

Initialization

For initialisation you will need project ID from the RuStore Console. To get the project ID on the app page navigate to Push notifications > Projects and copy the value in the Project ID field.

img

Manual initialization in Application

Add the following code to the Application of your project to initialise it:

Инициализация
class App : Application() {

override fun onCreate() {
super.onCreate()
RuStorePushClient.init(
application = this,
projectId = "i5UTx96jw6c1C9LvdlE4cdNrWHMNyRBt",
logger = DefaultLogger()
)
}
}
  • application is an instance of the Application class.
  • projectId — your project ID from RuStore Console.
  • (optional) logger — logger, defaults to output in logcat.

Auto initialization

Add the following code to AndroidManifest.xml to automatically initialise it:

AndroidManifest.xml
<meta-data
android:name="ru.rustore.sdk.pushclient.project_id"
android:value="i5UTx96jw6c1C9LvdlE4cdNrWHMNyRBt" />

<meta-data
android:name="ru.rustore.sdk.pushclient.params_class"
android:value="com.example.RuStorePushClientParams" />
  • projectId — your project ID from RuStore Console.
  • (optional) com.example.RuStorePushClientParams is the full class name of its implementation of AbstractRuStorePushClientParams or SimpleRuStorePushClientParams. It is required to specify additional parameters for push client initialisation.

Example of AbstractRuStorePushClientParams:

RuStorePushClientParams
class RuStorePushClientParams(context: Context)
: AbstractRuStorePushClientParams(context) {

override fun getLogger(): Logger = DefaultLogger("your_tag")

override fun getTestModeEnabled(): Boolean = false

override fun getClientIdCallback(): ClientIdCallback =
ClientIdCallback { ClientId("your_gaid_or_oaid", ClientIdType.GAID) }
}
caution

The implementation of the AbstractRuStorePushClientParams class should have only one constructor with one Context argument.

Calling RuStorePushClient.init() manually after automatic initialisation will be ignored.

Event logging

If you wish to log events of push notification library, add logger parameter to RuStorePushClient.init call. This parameter is not required for initialization.

Create the Logger interface:

Интерфейс Logger
interface Logger {

fun verbose(message: String, throwable: Throwable? = null)
fun debug(message: String, throwable: Throwable? = null)
fun info(message: String, throwable: Throwable? = null)
fun warn(message: String, throwable: Throwable? = null)
fun error(message: String, throwable: Throwable? = null)

fun createLogger(tag: String): Logger
}

The SDK uses the default implementation with AndroidLog if you don't pass Logger:

Пример реализации логгера
public class DefaultLogger(
private val tag: String? = null,
) : Logger {
override fun verbose(message: String, throwable: Throwable?) {
Log.v(tag, message, throwable)
}

override fun debug(message: String, throwable: Throwable?) {
Log.d(tag, message, throwable)
}

override fun info(message: String, throwable: Throwable?) {
Log.i(tag, message, throwable)
}

override fun warn(message: String, throwable: Throwable?) {
Log.w(tag, message, throwable)
}

override fun error(message: String, throwable: Throwable?) {
Log.e(tag, message, throwable)
}

override fun createLogger(tag: String): Logger {
val newTag = if (this.tag != null) {
"${this.tag}:$tag"
} else {
tag
}
return DefaultLogger(newTag)
}
}
`

Performance test

Push notifications prerequisites.

Important
  • Test build signature (for example: debug) of the app must match the signature of the app build that was uploaded to the console and passed moderation (for example, release).
  • The SDK used is up-to-date.
  • App uploaded to RuStore Console.
  • App passed moderation (you don't have to publish the app).
  • The current version of RuStore is installed on the user's device.
  • RuStore app supports push notifications.
  • The RuStore app is allowed to run in the background. Without this permission push notification will still be received, although, with a significant lag.
  • The signature fingerprint of the app installed on the device matches the signature fingerprint of the app uploaded to RuStore Console.

To check the listed prerequisites, use the RuStorePushClient.checkPushAvailability method.

Пример реализации RuStorePushClient.checkPushAvailability
RuStorePushClient.checkPushAvailability()
.addOnSuccessListener { result ->
when (result) {
FeatureAvailabilityResult.Available -> {
// Process push available
}

is FeatureAvailabilityResult.Unavailable -> {
result.cause.resolveForPush(requireContext())
}
}
}
.addOnFailureListener { throwable ->
// Process error
}

Push token methods

Retrieve user's push token

caution

The method will create and return a new push token if the user does not have one.

Once the library has been initialised, you can use the RuStorePushClient.getToken(), method to get the user's current push token.
Пример реализации RuStorePushClient.getToken
RuStorePushClient.getToken()
.addOnSuccessListener { result ->
// Process success
}
.addOnFailureListener { throwable ->
// Process error
}

Delete user's push token

After the library has been initialised, the user's current push token can be removed using the RuStorePushClient.deleteToken() method.

Пример реализации RuStorePushClient.deleteToken
RuStorePushClient.deleteToken()
.addOnSuccessListener(result -> {
// Process success
}
).addOnFailureListener(throwable -> {
// Process error
}
);

Push topic methods

Subscribe to topic-based push notifications

Once the library is initialised, you can use the RuStorePushClient.subscribeToTopic(your_topic_name) method to subscribe to a topic.

Пример реализации RuStorePushClient.subscribeToTopic(your_topic_name)
RuStorePushClient.subscribeToTopic("your_topic_name")
.addOnSuccessListener { result ->
// Process subscribe success
}
.addOnFailureListener { throwable ->
// Process subscribe error
}

Unsubscribe from topic-based push notifications

Once the library is initialised, you can use the RuStorePushClient.unsubscribeFromTopic(your_topic_name) method to unsubscribe from the topic.
Пример реализации RuStorePushClient.unsubscribeFromTopic(your_topic_name)
RuStorePushClient.unsubscribeFromTopic("your_topic_name")
.addOnSuccessListener { result ->
// Process unsubscribe success
}
.addOnFailureListener { throwable ->
// Process unsubscribe error
}

Retrieve data from RuStore SDK

To get data from RuStore SDK, create your service that inherits from RuStoreMessagingService.

warning

Your service has to process any method within 20 seconds from the moment it's called. After this time is passed, the serviced can be terminated by the system.

RuStoreMessagingService
class MessagingService: RuStoreMessagingService() {

override fun onNewToken(token: String) {
}

override fun onMessageReceived(message: RemoteMessage) {
}

override fun onDeletedMessages() {
}

override fun onError(errors: List<RuStorePushClientException>) {
}
}
Method nameDescription

onNewToken

Called when a new push token is received. After this method is called, your app will be responsible for delivering the new push token to its server. This method returns the value of the new token.

onMessageReceived

Called when a new push token is received < p/> If there is data in notification object, RuStoreSDK will display the notification itself. If you don’t want RuStoreSDK to display notification itself, use data object, and leave notification object empty. Called in any case. < p/> Push notification’s payload Map<String, String> may be obtained from message.data field.

onDeletedMessages

Called when one or more push notifications fail to reach the device. For example, if the notification's lifetime has expired before delivery. < p/> When calling this method, it is recommended that you synchronise with your server to avoid missing data.

onError

Called when an error occurs during initialisation. It returns an array of objects with errors. < p/> Possible errors:

  • UnauthorizedException — user not authorized on RuStore.
  • HostAppNotInstalledException — user’s device doesn’t have RuStore app installed.
  • HostAppBackgroundWorkPermissionNotGranted — RuStore app is not allowed to run in the background.

All of the methods listed above will be called in the background thread.

Notification structure

Структура полного уведомления
public data class RemoteMessage(
val messageId: String?,
val priority: Int,
val ttl: Int,
val from: String,
val collapseKey: String?,
val data: Map<String, String>,
val rawData: ByteArray?,
val notification: Notification?
)
  • messageId — unique message ID. It corresponds to an ID of each message.

  • priority — returns the priority value (currently disregarded).

    The following options are now available:

    • 0UNKNOWN.
    • 1HIGH.
    • 2NORMAL.

    < p/>

  • ttl — push notification lifetime of Int type in seconds.

  • from — field which shows the notification's origin: < p/>

    • The field displays the topic name for notifications sent to it.
    • Otherwise it is part of your service token.

    < p/>

  • collapseKey - notification group ID (currently disregarded).

  • data — dictionary to which additional notification data can be passed.

    .

  • rawData — dictionary of data as an array of bytes.

  • notification — notification object.

Структура объекта notification
public data class Notification(
val title: String?,
val body: String?,
val channelId: String?,
val imageUrl: Uri?,
val color: String?,
val icon: String?,
val clickAction: String?,
val clickActionType: ClickActionType?
)
  • title — notification header.

  • body — notification body
  • channelId — option to create the channel to which notification will be sent. For Android 8.0 or later.

  • imageUrl — direct link to an image to be inserted into the notification. The size of the image must not exceed 1 Mbyte .

    .

  • color — notification colour in HEX format, string. For example, #0077FF.

  • icon — notification icon from res/drawable in a string format that matches the resource name. < p/> For example, res/drawable has an icon small_icon.xml, which is accessible in code via R.drawable.small_icon. For the icon to be displayed in the notification, the server must specify a icon value of small_icon. < p/>

  • clickAction — field which will be used to generate an action when clicking on the notification.

  • clickActionTypeclickAction field type.

Структура объекта ClickActionType
enum class ClickActionType {
DEFAULT,
DEEP_LINK
}
  • DEFAULT — field type clickAction where clickAction will be used as intent action to open the activity when clicking on the notification. More details here.

  • DEEP_LINK — field type clickAction where clickAction will be used as deep link to open the activity when clicking on the notification. More details here.

Create notification channels

The channel to which the message is sent will be given the following priority:

  • If the push notification has a channelId field, RuStore SDK will send the notification to the specified channel. Your app must create this channel in advance.

  • If there is no channelId field in the push notification, but your app has specified a parameter with a channel in AndroidManifest.xml, the specified channel will be used. Your app must create this channel in advance.

  • If there is no channelId field in the push notification and the default channel is not set in AndroidManifest.xml, RuStore SDK will create a channel and send the notification to it. From now on, all notifications without an explicit channel will be sent to that channel..

Error handling

  • RuStoreNotInstalledException — RuStore is not installed on the user's device.

  • RuStoreOutdatedException — RuStore app on the user's device does not support push notifications.

  • RuStoreUserUnauthorizedException — user is not authorized in RuStore.

  • RuStoreFeatureUnavailableException — RuStore is not allowed to work in background.

  • RuStoreException — basic RuStore error from which other errors are inherited.

If you wish to use UI interface for error handling, then use resolveForPush() method:

Пример реализации resolveForPush
fun RuStoreException.resolveForPush(context: Context)

Testing SDK integration

Push notifications prerequisites.

Important
  • Test build signature (for example: debug) of the app must match the signature of the app build that was uploaded to the console and passed moderation (for example, release).
  • The SDK used is up-to-date.
  • App uploaded to RuStore Console.
  • App passed moderation (you don't have to publish the app).
  • The current version of RuStore is installed on the user's device.
  • RuStore app supports push notifications.
  • The RuStore app is allowed to run in the background. Without this permission push notification will still be received, although, with a significant lag.
  • The signature fingerprint of the app installed on the device matches the signature fingerprint of the app uploaded to RuStore Console.

To start testing the SDK, enable test mode:

Пример включения тестового режима
RuStorePushClient.init(
application = this ,
projectId = "your_push_project_id" ,
testModeEnabled = true
)

In this mode, a test push token is generated and only test push notifications are delivered. They are sent in the following way:

Пример отправки тестового push-уведомления
val testNotificationPayload = TestNotificationPayload(
title = "Test notification title",
body = "Test notification message",
imgUrl = "some_image_http_url",
data = mapOf("some_key" to "some_value")
)

RuStorePushClient.sendTestNotification(testNotificationPayload).addOnCompleteListener(object : OnCompleteListener<Unit> {
override fun onFailure(throwable: Throwable) {
// Process send test push error
}

override fun onSuccess(result: Unit) {
// Process send test push success
}
})

See also