Перейти к основному содержимому

SDK push-уведомлений для Kotlin и Java (версия 2.0.0)

Ниже перечислены условия работы push-уведомлений.

Важно
  • Подпись тестируемой сборки (например, debug) приложения должна совпадать с подписью сборки приложения, которая была загружена в консоль и прошла модерацию ранее (например, release).
  • Используется актуальная версия SDK.
  • Приложение загружено в Консоль RuStore.
  • Приложение прошло модерацию (публиковать приложение необязательно).
  • На устройстве пользователя установлена актуальная версия RuStore.
  • Приложение RuStore поддерживает функциональность push-уведомлений.
  • Приложению RuStore разрешен доступ к работе в фоновом режиме.
  • Пользователь авторизован в RuStore.
  • Отпечаток подписи приложения, установленного на девайсе, совпадает с отпечатком подписи приложения, которое загружено в Консоль RuStore.

Пример реализации

Ознакомьтесь с приложением-примером, чтобы узнать, как правильно интегрировать SDK push-уведомлений:

Подключение в проект

Добавление репозитория

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

Подключение зависимости

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

Редактирование манифеста приложения

Объявите службу, расширяющую 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>

Если нужно изменить иконку или цвет стандартной нотификации, добавьте следующий код.

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" />

Если нужно переопределить канал уведомлений, добавьте следующий код.

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

При добавлении канала push-уведомлений вы должны создать канал самостоятельно.

Запрос разрешения на показ уведомлений в Android 13+

В версии Android 13 появилось новое разрешение для отображения push-уведомлений. Это затронет все приложения, которые работают на Android 13 или выше и используют RuStore Push SDK.

По умолчанию RuStore Push SDK версии 1.4.0 и выше включает разрешение POST_NOTIFICATIONS, определённое в манифесте. Однако приложению также нужно запросить это разрешение во время выполнения через константу android.permission.POST_NOTIFICATIONS. Приложение сможет показывать push-уведомления, только когда пользователь предоставит на это разрешение.

Запрос разрешения на показ push-уведомлений.

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)
}
}
}

Инициализация

Для инициализации понадобится идентификатор проекта из RuStore Консоль. Чтобы получить его, на странице приложения перейдите в раздел Push-уведомления > Проекты и скопируйте значение в поле ID проекта.

img

Ручная инициализация в Application

Для инициализации добавьте в Application вашего проекта следующий код.

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

override fun onCreate() {
super.onCreate()
RuStorePushClient.init(
application = this,
projectId = "i5UTx96jw6c1C9LvdlE4cdNrWHMNyRBt",
logger = DefaultLogger()
)
}
}
  • application — экземпляр класса Application.
  • projectId — идентификатор вашего проекта из RuStore Консоль.
  • logger — логгер, по умолчанию используется вывод в logcat (опционально).

Автоматическая инициализация

Для автоматической инициализации добавьте в AndroidManifest.xml следующий код.

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 — идентификатор вашего проекта из RuStore Консоль.
  • (опционально) com.example.RuStorePushClientParams — полное имя класса своей реализации AbstractRuStorePushClientParams или SimpleRuStorePushClientParams. Нужен для указания дополнительных параметров инициализации push-клиента.

Пример реализации 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) }
}
предупреждение

В реализации класса AbstractRuStorePushClientParams должен быть только один конструктор с одним аргументом Context.

Ручной вызов RuStorePushClient.init() после автоматической инициализации будет проигнорирован.

Логирование событий

Если вы хотите логировать события библиотеки push-уведомлений, добавьте в вызов RuStorePushClient.init параметр logger. Этот параметр необязателен для инициализации.

Создайте интерфейс Logger.

Интерфейс 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
}

Если не передать Logger, SDK использует реализацию по умолчанию с AndroidLog.

Пример реализации логгера
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)
}
}

Проверка возможности получать push-уведомления

Ниже перечислены условия работы push-уведомлений.

Важно
  • Подпись тестируемой сборки (например, debug) приложения должна совпадать с подписью сборки приложения, которая была загружена в консоль и прошла модерацию ранее (например, release).
  • Используется актуальная версия SDK.
  • Приложение загружено в Консоль RuStore.
  • Приложение прошло модерацию (публиковать приложение необязательно).
  • На устройстве пользователя установлена актуальная версия RuStore.
  • Приложение RuStore поддерживает функциональность push-уведомлений.
  • Приложению RuStore разрешен доступ к работе в фоновом режиме.
  • Пользователь авторизован в RuStore.
  • Отпечаток подписи приложения, установленного на девайсе, совпадает с отпечатком подписи приложения, которое загружено в Консоль RuStore.
Для проверки того, что приложение RuStore установлено на устройстве пользователя, используйте метод RuStorePushClient.checkPushAvailability.
Пример реализации 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-токеном

Получение push-токена пользователя

предупреждение

Если у пользователя нет push-токена, метод создаст и вернёт новый push-токен.

После инициализации библиотеки вы можете использовать метод RuStorePushClient.getToken(), чтобы получить текущий push-токен пользователя.
Пример реализации RuStorePushClient.getToken
RuStorePushClient.getToken()
.addOnSuccessListener { result ->
// Process success
}
.addOnFailureListener { throwable ->
// Process error
}

Удаление push-токена пользователя

После инициализации библиотеки вы можете использовать метод RuStorePushClient.deleteToken(), чтобы удалить текущий push-токен пользователя.
Пример реализации RuStorePushClient.deleteToken
RuStorePushClient.deleteToken()
.addOnSuccessListener { result ->
// Process success
}
.addOnFailureListener { throwable ->
// Process error
}

Методы для работы с push-топиком

Подписка на push-уведомления по топику

После инициализации библиотеки вы можете использовать метод RuStorePushClient.subscribeToTopic(your_topic_name) для подписки на топик.
Пример реализации RuStorePushClient.subscribeToTopic(your_topic_name)
RuStorePushClient.subscribeToTopic("your_topic_name")
.addOnSuccessListener { result ->
// Process subscribe success
}
.addOnFailureListener { throwable ->
// Process subscribe error
}

Отписка от push-уведомлений по топику

После инициализации библиотеки вы можете использовать метод RuStorePushClient.unsubscribeFromTopic(your_topic_name) для отписки от топика.
Пример реализации RuStorePushClient.unsubscribeFromTopic(your_topic_name)
RuStorePushClient.unsubscribeFromTopic("your_topic_name")
.addOnSuccessListener { result ->
// Process unsubscribe success
}
.addOnFailureListener { throwable ->
// Process unsubscribe error
}

Получение данных от RuStore SDK

Чтобы получить данные от RuStore SDK, создайте свой сервис, который наследуется от RuStoreMessagingService.

RuStoreMessagingService
class MessagingService: RuStoreMessagingService() {

override fun onNewToken(token: String) {
}

override fun onMessageReceived(message: RemoteMessage) {
}

override fun onDeletedMessages() {
}

override fun onError(errors: List<RuStorePushClientException>) {
}
}
Название методаОписание

onNewToken

Метод вызывается при получении нового push-токена. После вызова этого метода ваше приложение становится ответственно за передачу нового push-токена на свой сервер. Метод возвращает значение нового токена.

onMessageReceived

Метод вызывается при получении нового push-уведомления.

Если в объекте notification есть данные, RuStore SDK самостоятельно отображает уведомление. Если вы не хотите этого, используйте объект data, а notification оставьте пустым. Метод вызывается в любом случае.

Получить payload push-уведомления Map<String, String> можно из поля message.data.

onDeletedMessages

Метод вызывается, если один или несколько push-уведомлений не доставлены на устройство. Например, если время жизни уведомления истекло до момента доставки.

При вызове этого метода рекомендуется синхронизироваться со своим сервером, чтобы не пропустить данные.

onError

Метод вызывается, если в момент инициализации возникает ошибка. Он возвращает массив объектов с ошибками.

Возможные ошибки:

  • UnauthorizedException — пользователь не авторизован в RuStore. Ошибка может не возникать, даже если пользователь не авторизован в RuStore. Это поведение управляется динамически в Push SDK. Если ваши пользователи не получают такую ошибку, то все равно имеет смысл ее обрабатывать;
  • HostAppNotInstalledException — RuStore отсутствует на устройстве пользователя;
  • HostAppBackgroundWorkPermissionNotGranted — у RuStore нет разрешения на работу в фоне. Ошибка не критична. Пуши продолжат приходить, но хуже, чем если бы разрешение на работу в фоне было выдано.

Все перечисленные методы вызываются в фоновом потоке.

Структура уведомления

Структура полного уведомления
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 — уникальный ID сообщения. Является идентификатором каждого сообщения.
  • priority — возвращает значение приоритетности (на данный момент не учитывается). Сейчас заложены следующие варианты:
    • 0UNKNOWN;
    • 1HIGH;
    • 2NORMAL.
  • ttl — время жизни push-уведомления типа Int в секундах.
  • from — поле, по которому можно понять, откуда пришло уведомление:
    • для уведомлений, отправленных в топик, в поле отображается имя топика;
    • в других случаях — часть вашего сервисного токена.
    .
  • collapseKey — идентификатор группы уведомлений (на данный момент не учитывается).
  • data — словарь, в который можно передать дополнительные данные для уведомления.
  • rawData — словарь data в виде массива байтов.
  • notification — объект уведомления.
Структура объекта 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?
)
  • title — заголовок уведомления.
  • body — тело уведомления.
  • channelId — возможность задать канал, в который отправится уведомление. Актуально для Android 8.0 и выше.
  • imageUrl — прямая ссылка на изображение для вставки в уведомление. Изображение должно быть не более 1 Мбайт.
  • color — цвет уведомления в HEX-формате, строкой. Например, #0077FF.
  • icon — значок уведомления из res/drawable в формате строки, которая совпадает с названием ресурса.
    Например, в res/drawable есть значок small_icon.xml, который доступен в коде через R.drawable.small_icon.
    Чтобы значок отображался в уведомлении, сервер должен указать в параметре icon значение small_icon
    .
  • clickActionintent action, с помощью которого будет открыта активити при клике на уведомление.

Создание канала для отправки уведомления

Для канала, в который отправляется уведомление, действует следующий приоритет.

  • Если в push-уведомлении есть поле channelId, RuStore SDK отправит уведомление в указанный канал. Ваше приложение должно создать этот канал заранее.

  • Если в push-уведомлении нет поля channelId, но ваше приложение указало параметр с каналом в AndroidManifest.xml, используется указанный канал. Ваше приложение должно создать этот канал заранее.

  • Если в push-уведомлении нет поля channelId, и канал по умолчанию не задан в AndroidManifest.xml, RuStore SDK создаст канал и отправит уведомление в него. В дальнейшем все уведомления без явного указания канала будут отправляться в этот канал.

Обработка ошибок

  1. Публичные методы класса RuStorePushClient при возникновении ошибки возвращают Throwable.

  2. Метод onError класса RuStoreMessagingService может возвращать следующий набор ошибок:

  • UnauthorizedException — пользователь не авторизован в RuStore. Ошибка может не возникать, даже если пользователь не авторизован в RuStore. Это поведение управляется динамически в Push SDK. Если ваши пользователи не получают такую ошибку, то все равно имеет смысл ее обрабатывать;
  • HostAppNotInstalledException — RuStore отсутствует на устройстве пользователя;
  • HostAppBackgroundWorkPermissionNotGranted — у RuStore нет разрешения на работу в фоне. Ошибка не критична. Пуши продолжат приходить, но хуже, чем если бы разрешение на работу в фоне было выдано.
  • Вышеперечисленные ошибки являются наследниками класса RuStorePushClientException, который в свою очередь является наследником класса RuStoreException.

  1. Метод checkPushAvailability класса RuStorePushClient при успешном ответе в объекте FeatureAvailabilityResult.Unavailable возвращает ошибку HostAppNotInstalledException

Если вы хотите использовать UI-интерфейс для работы с ошибками, используйте метод resolveForPush.

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

Тестирование интеграции SDK

Ниже перечислены условия работы push-уведомлений.

Важно
  • Подпись тестируемой сборки (например, debug) приложения должна совпадать с подписью сборки приложения, которая была загружена в консоль и прошла модерацию ранее (например, release).
  • Используется актуальная версия SDK.
  • Приложение загружено в Консоль RuStore.
  • Приложение прошло модерацию (публиковать приложение необязательно).
  • На устройстве пользователя установлена актуальная версия RuStore.
  • Приложение RuStore поддерживает функциональность push-уведомлений.
  • Приложению RuStore разрешен доступ к работе в фоновом режиме.
  • Пользователь авторизован в RuStore.
  • Отпечаток подписи приложения, установленного на девайсе, совпадает с отпечатком подписи приложения, которое загружено в Консоль RuStore.

Чтобы начать тестирование SDK, включите тестовый режим.

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

В этом режиме формируется тестовый push-токен и работает доставка только тестовых push-уведомлений. Они отправляются следующим методом.

Пример отправки тестового 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
}
})

См. также