Push notifications SDK for Kotlin и Java (version 2.1.1)
Push notification terms and conditions:
- 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.
- User is authorized in RuStore.
- The signature fingerprint of the app must match the fingerprint added to the RuStore Console.
Implementation example
Ознакомьтесь с example app , чтобы узнать, как правильно интегрировать SDK push-уведомлений:
Connecting to project
Adding repository
repositories {
maven {
url = uri("https://artifactory-external.vkpartner.ru/artifactory/maven")
}
}
Connecting dependency
dependencies {
implementation("ru.rustore.sdk:pushclient:2.1.1")
}
Editing app manifest
Declare a service that extends RuStoreMessagingService
:
<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:
<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:
<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.
Requesting permissions for displaying notifications in Android 13+
- Kotlin
- Java
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:
// 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)
}
}
}
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:
// Declare the launcher at the top of your Activity/Fragment:
private final ActivityResultLauncher<String> requestPermissionLauncher =
registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
if (isGranted) {
// RuStore Push SDK (and your app) can post notifications.
} else {
// TODO: Inform user that your app will not show notifications.
}
});
private void 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.
Manual initialization in Application
- Kotlin
- Java
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 theApplication
class.projectId
— your project ID from RuStore Console.- (optional)
logger
— logger, defaults to output inlogcat
.
Add the following code to the Application
of your project to initialise it:
class App : Application() {
@Override
public void onCreate() {
super .onCreate()
RuStorePushClient.INSTANCE.init(
this ,
"i5UTx96jw6c1C9LvdlE4cdNrWHMNyRBt" ,
DefaultLogger()
);
}
}
application
is an instance of theApplication
class.projectId
— your project ID from RuStore Console.- (optional)
logger
— logger, defaults to output inlogcat
.
Auto initialization
- Kotlin
- Java
Add the following code to AndroidManifest.xml
to automatically initialise it:
<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 ofAbstractRuStorePushClientParams
orSimpleRuStorePushClientParams
. It is required to specify additional parameters for push client initialisation.
Example of AbstractRuStorePushClientParams
:
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) }
}
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.
Add the following code to AndroidManifest.xml
to automatically initialise it:
<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 ofAbstractRuStorePushClientParams
orSimpleRuStorePushClientParams
. It is required to specify additional parameters for push client initialisation.
Example of AbstractRuStorePushClientParams
:
public class RuStorePushClientParams extends AbstractRuStorePushClientParams {
public RuStorePushClientParams(@NonNull Context context) {
super(context);
}
@NonNull
@Override
public Logger getLogger() {
return new DefaultLogger("your_tag");
}
@Override
public boolean getTestModeEnabled() {
return false;
}
@Nullable
@Override
public ClientIdCallback getClientIdCallback() {
return () -> new ClientId("your_gaid_or_oaid", ClientIdType.GAID);
}
}
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
- Kotlin
- Java
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:
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)
}
}
`
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:
public interface Logger {
void verbose(String message, Throwable throwable);
void debug(String message, Throwable throwable);
void info(String message, Throwable throwable);
void warn(String message, Throwable throwable);
void error(String message, Throwable throwable);
Logger createLogger(String tag);
}
The SDK uses the default implementation with AndroidLog
if you don't pass Logger
:
public class PushLogger implements Logger {
private final String tag;
public PushLogger(String tag) {
this.tag = tag;
}
@Override
public void debug( @NonNull String message, Throwable throwable) {
Log.d(tag, message, throwable);
}
@Override
public void error( @NonNull String message, Throwable throwable) {
Log.e(tag, message, throwable);
}
@Override
public void info( @NonNull String message, @Nullable Throwable throwable) {
Log.i(tag, message, throwable);
}
@Override
public void verbose( @NonNull String message, @Nullable Throwable throwable) {
Log.v(tag, message, throwable);
}
@Override
public void warn( @NonNull String message, @Nullable Throwable throwable) {
Log.w(tag, message, throwable);
}
@NonNull
@Override
public Logger createLogger( @NonNull String newTag) {
String combinedTag = (tag != null ) ? tag + ":" + newTag : newTag;
return new PushLogger(combinedTag);
}
}
Push notifications availability check
Push notification terms and conditions:
- 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.
- User is authorized in RuStore.
- The signature fingerprint of the app must match the fingerprint added to the RuStore Console.
- Kotlin
- Java
To check the listed prerequisites, use the RuStorePushClient.checkPushAvailability
method.
RuStorePushClient.checkPushAvailability()
.addOnSuccessListener { result ->
when (result) {
FeatureAvailabilityResult.Available -> {
// Process push available
}
is FeatureAvailabilityResult.Unavailable -> {
result.cause.resolveForPush(requireContext())
}
}
}
.addOnFailureListener { throwable ->
// Process error
}
To check the listed prerequisites, use the RuStorePushClient.INSTANCE.checkPushAvailability
method.
RuStorePushClient.INSTANCE.checkPushAvailability()
.addOnSuccessListener(result -> {
// Process result
}
).addOnFailureListener(throwable -> {
// Process error
}
);
Push token methods
Getting user push token
- Kotlin
- Java
The method will create and return a new push token if the user does not have one.
RuStorePushClient.getToken()
, method to get the user's current push token.
RuStorePushClient.getToken()
.addOnSuccessListener { result ->
// Process success
}
.addOnFailureListener { throwable ->
// Process error
}
The method will create and return a new push token if the user does not have one.
RuStorePushClient.INSTANCE.getToken()
, method to get the user's current push token.
RuStorePushClient.INSTANCE.getToken()
.addOnSuccessListener(result -> {
// Process success
}
).addOnFailureListener(throwable -> {
// Process error
}
);
Deleting user push token
- Kotlin
- Java
After the library has been initialised, the user's current push token can be removed using the RuStorePushClient.deleteToken()
method.
RuStorePushClient.deleteToken()
.addOnSuccessListener(result -> {
// Process success
}
).addOnFailureListener(throwable -> {
// Process error
}
);
After the library has been initialised, the user's current push token can be removed using the RuStorePushClient.deleteToken()
method.
RuStorePushClient.INSTANCE.deleteToken()
.addOnSuccessListener(result -> {
// Process success
}
).addOnFailureListener(throwable -> {
// Process error
}
);
Push topic methods
Push topic subscription
- Kotlin
- Java
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")
.addOnSuccessListener { result ->
// Process subscribe success
}
.addOnFailureListener { throwable ->
// Process subscribe error
}
Once the library is initialised, you can use the RuStorePushClient.subscribeToTopic(your_topic_name)
method to subscribe to a topic.
RuStorePushClient.INSTANCE.subscribeToTopic("your_topic_name")
.addOnSuccessListener(result -> {
// Process subscribe success
}
).addOnFailureListener(throwable -> {
// Process subscribe error
}
);
Unsubscribe from push topic
- Kotlin
- Java
RuStorePushClient.unsubscribeFromTopic(your_topic_name)
method to unsubscribe from the topic.
RuStorePushClient.unsubscribeFromTopic("your_topic_name")
.addOnSuccessListener { result ->
// Process unsubscribe success
}
.addOnFailureListener { throwable ->
// Process unsubscribe error
}
RuStorePushClient.unsubscribeFromTopic(your_topic_name)
method to unsubscribe from the topic.
RuStorePushClient.INSTANCE.unsubscribeFromTopic("your_topic_name")
.addOnSuccessListener(result -> {
// Process unsubscribe success
}
).addOnFailureListener(throwable -> {
// Process unsubscribe error
}
);
Retrieving data from RuStore SDK
- Kotlin
- Java
To get data from RuStore SDK, create your service that inherits from RuStoreMessagingService
.
class MessagingService: RuStoreMessagingService() {
override fun onNewToken(token: String) {
}
override fun onMessageReceived(message: RemoteMessage) {
}
override fun onDeletedMessages() {
}
override fun onError(errors: List<RuStorePushClientException>) {
}
}
Method name | Description |
---|---|
| 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. |
| Called when a new push token is received
< p/>
If there is data in |
| 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. |
| Called when an error occurs during initialisation. It returns an array of objects with errors. < p/> Possible errors:
|
All of the methods listed above will be called in the background thread.
public class MessagingService extends RuStoreMessagingService {
@Override
public void onNewToken(String token) {
}
@Override
public void onMessageReceived(RemoteMessage message) {
}
@Override
public void onDeletedMessages() {
}
@Override
public void onError(List<RuStorePushClientException> errors) {
}
}
Method name | Description |
---|---|
| 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. |
| Called when a new push token is received
< p/>
If there is data in |
| 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. |
| Called when an error occurs during initialisation. It returns an array of objects with errors. < p/> Possible errors:
|
All of the methods listed above will be called in the background thread.
Notification structure
- Kotlin
- Java
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:
0
—UNKNOWN
.1
—HIGH
.2
—NORMAL
.
< p/>
-
ttl
— push notification lifetime ofInt
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 ofdata
as an array of bytes. -
notification
— notification object.
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 fromres/drawable
in a string format that matches the resource name. < p/> For example,res/drawable
has an iconsmall_icon.xml
, which is accessible in code viaR.drawable.small_icon
. For the icon to be displayed in the notification, the server must specify aicon
value ofsmall_icon
. < p/> -
clickAction
— field which will be used to generate an action when clicking on the notification. -
clickActionType
—clickAction
field type.
enum class ClickActionType {
DEFAULT,
DEEP_LINK
}
-
DEFAULT
— field typeclickAction
whereclickAction
will be used asintent action
to open the activity when clicking on the notification. More details here. -
DEEP_LINK
— field typeclickAction
whereclickAction
will be used asdeep link
to open the activity when clicking on the notification. More details here.
public final class RemoteMessage {
public String getMessageId();
public int getPriority();
public int getTtl();
public String getFrom();
public String getCollapseKey();
public Map<String, String> getData();
public byte [] getRawData();
public Notification getNotification();
}
-
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:
0
—UNKNOWN
.1
—HIGH
.2
—NORMAL
.
< p/>
-
ttl
— push notification lifetime ofInt
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 ofdata
as an array of bytes. -
notification
— notification object.
public final class Notification {
public String getTitle();
public String getBody();
public String getChannelId();
public Uri getImageUrl();
public String getColor();
public String getIcon();
public String getClickAction();
public ClickActionType getClickActionType();
}
-
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 fromres/drawable
in a string format that matches the resource name. < p/> For example,res/drawable
has an iconsmall_icon.xml
, which is accessible in code viaR.drawable.small_icon
. For the icon to be displayed in the notification, the server must specify aicon
value ofsmall_icon
. < p/> -
clickAction
— field which will be used to generate an action when clicking on the notification. -
clickActionType
—clickAction
field type.
enum ClickActionType {
DEFAULT,
DEEP_LINK
}
-
DEFAULT
— field typeclickAction
whereclickAction
will be used asintent action
to open the activity when clicking on the notification. More details here. -
DEEP_LINK
— field typeclickAction
whereclickAction
will be used asdeep link
to open the activity when clicking on the notification. More details here.
Creating notification channel
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 inAndroidManifest.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 inAndroidManifest.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..
Errors processing
- Kotlin
- Java
-
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:
fun RuStoreException.resolveForPush(context: Context)
-
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:
public void PushRuStoreExceptionExtKt.resolveForPush(context);
SDK integration testing
Push notification terms and conditions:
- 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.
- User is authorized in RuStore.
- The signature fingerprint of the app must match the fingerprint added to the RuStore Console.
- Kotlin
- Java
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:
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
}
})
To start testing the SDK, enable test mode:
RuStorePushClient.INSTANCE.init(
this ,
"your_push_project_id" ,
true
)
In this mode, a test push token is generated and only test push notifications are delivered. They are sent in the following way:
TestNotificationPayload testNotificationPayload = new TestNotificationPayload(
"Test notification title" ,
"Test notification message" ,
"some_image_http_url" ,
data
);
RuStorePushClient.INSTANCE.sendTestNotification(testNotificationPayload)
.addOnCompleteListener( new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
if (task.isSuccessful()) {
// Process send test push success
} else {
Exception exception = task.getException();
// Process send test push error
}
}
});