Оглавление

Carrot quest для Android

Carrot quest для Android поддерживает API 21 и выше.

Подробная документация по SDK доступна на developers-sdk.carrotquest.io.

Установка

На данный момент Carrot quest для Android можно установить с помощью gradle. Для этого добавьте репозиторий в build.gradle файле проекта:

allprojects {
    ...
    repositories {
        ...
        maven { url "https://raw.github.com/carrotquest/android-sdk/carrotquest" }
        maven { url "https://jitpack.io" }
    }
}

Укажите зависимости в build.gradle файле вашего приложения:

android {
    ...
    packagingOptions {
        exclude 'META-INF/*.kotlin_module'
    }
}

dependencies {
    ...
    implementation 'io.carrotquest:android-sdk:3.3.0-commonRelease'
}

Библиотека использует Java 17. Если ваш проект использует версию Java ниже 17, добавьте следующие настройки:

android {
    ...
    compileOptions {
        sourceCompatibility '17'
        targetCompatibility '17'
    }
}

Обновление

Версия 3.0.0 — мажорное обновление с ломающими изменениями в публичном API. Что нужно учесть при обновлении:

  • Новая система логирования. setDebug(boolean) / isDebug() удалены — уровень задаётся через setLogLevel(SdkLogLevel) со значениями NONE, ERROR, WARN, INFO, DEBUG, VERBOSE. По умолчанию NONE: SDK не пишет в логи ничего, в том числе в release (раньше часть логов сыпалась всегда). Дополнительно можно получать записи логов прямо в своём коде через setLogSink(...) (например, прокинуть в свой логгер или крэш-репортер) и снимать одномоментный срез состояния для баг-репортов через getDiagnostics(). Чувствительные данные (токены, e-mail, идентификаторы) маскируются, пока не включён setLogIncludeSensitive(true). Примеры использования — в разделе «Инициализация».
  • Подписки на состояние удалены (addStateObserver / getStateFlow / addAuthStateObserver / getAuthStateFlow / addSessionExpiredObserver / getInitObservable, а также модели CarrotState / CarrotAuthState). Восстановление сессии теперь автоматическое: результат операций берите из их Callback, а факт инициализации — из Carrot.isInit().
  • Отписка через Cancellable. Методы подписки (например, setUnreadConversationsCallback) возвращают Cancellable — для отписки вызывайте .cancel().
  • UserProperty / Operation консолидированы. Operation — единый enum io.carrotquest_sdk.android.models.Operation со значениями в UPPER_CASE (set_onceSET_ONCE, update_or_createUPDATE_OR_CREATE и т.д.). Поле UserProperty.operation больше не публичное мутабельное — читается через getOperation(), класс стал неизменяемым.
  • Тип колбэка CarrotSDK.Callback убран → top-level io.carrotquest_sdk.android.Callback<T>; брендовые Carrot.Callback / Dashly.Callback сохранены как взаимозаменяемые подтипы.
  • Push-хелперы — только Map<String, String>. RemoteMessage-перегрузки и sendFcmToken(...) удалены — используйте sendPushToken(token) и Map-варианты (см. раздел «Уведомления»).

Если в вашем приложении есть авторизация пользователей, вызывайте её при старте приложения — наилучшее место — onResponse колбэка setup. Это предотвратит лишнее возникновение анонимных пользователей:

Carrot.setup(this, yourApiKey, object : Carrot.Callback<Boolean> {
    override fun onResponse(result: Boolean) {
        if (result) {
            Carrot.auth(userId, userAuthKey, object : Carrot.Callback<String> {
                override fun onResponse(result: String?) { }
                override fun onFailure(t: Throwable) { }
            })
        }
    }

    override fun onFailure(t: Throwable) { }
})

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

Для работы с Carrot quest для Android вам понадобится API Key и User Auth Key. Вы можете найти эти ключи на вкладке Настройки > Разработчикам: Api keys

Для инициализации Carrot quest вам нужно выполнить следующий код в методе onCreate() вашего приложения:

Carrot.setup(this, apiKey, callback)

Для вывода подробных логов SDK в logcat во время отладки задайте уровень логирования (по умолчанию SdkLogLevel.NONE — SDK не пишет в логи ничего):

Carrot.setLogLevel(SdkLogLevel.DEBUG)   // выключить: Carrot.setLogLevel(SdkLogLevel.NONE)

Опционально можно получать записи логов в своём коде (например, прокинуть в свой логгер/крэш-репортер) и снять одномоментный срез состояния SDK для баг-репортов:

Carrot.setLogSink { entry -> myLogger.log(entry.category.toString() + " " + entry.message) }
// чувствительные значения (токены/e-mail/идентификаторы) маскируются по умолчанию;
// показать полностью (только для локальной отладки):
Carrot.setLogIncludeSensitive(true)

val report = Carrot.getDiagnostics().toFormattedString()

Авторизация пользователей

Если в вашем приложении присутствует авторизация пользователей, вы можете передать id пользователя в Carrot quest. Существует два способа авторизации: напрямую передать userAuthKey, передать hash генерируемый у вас на бэке. В callback при успешном входе вернется значение свойства carrot_id.

  1. Вход через user auth key:
Carrot.auth(userId, userAuthKey, callback)
  1. Вход через hash:
Carrot.hashedAuth(userId, hash, callback)

Чтобы сменить пользователя, нужно сначала вызвать метод деинициализации, а после завново вызвать методы ининциализации и (опционально) авторизации:

Carrot.deInit(object : Carrot.Callback<Boolean> {
    override fun onResponse(result: Boolean) {
        Carrot.setup(this, yourApiKey, callbackSetup)
    }

    override fun onFailure(t: Throwable) {

    }
})

Свойства пользователей и события

Вы можете установить необходимые свойства пользователя с помощью

Carrot.setUserProperty(userProperty)
Carrot.setUserProperty(userPropertyList)

Для описания свойств пользователя используйте класс UserProperty (io.carrotquest_sdk.android.models.UserProperty):

public UserProperty(String key, String value)
public UserProperty(Operation operation, String key, String value)

Operation — это enum io.carrotquest_sdk.android.models.Operation со значениями в UPPER_CASE (UPDATE_OR_CREATE, SET_ONCE, ADD, DELETE, APPEND, UNION, EXCLUDE). Более подробно про операции можно прочитать в разделе «Cвойства пользователя».

Внимание!

Поле key не может начинаться с символа $.

Для установки системных свойств реализовано 2 класса CarrotUserProperty и EcommerceUserProperty (пакет io.carrotquest_sdk.android.models).

Для отслеживания событий используйте

Carrot.trackEvent(eventName)

Вы можете указать дополнительные параметры для события. Соберите их типобезопасным билдером EventParams — SDK сам сериализует значения в JSON (передавать JSON-строку вручную больше не нужно):

Carrot.trackEvent("purchase", EventParams.builder()
    .put("item", "book")
    .put("price", 9.99)
    .put("gift", true)
    .build())

put(...) перегружен для String/Int/Long/Double/Boolean. В SDK есть возможность трекинга навигации внутри приложения для того, чтобы при необходимости запускать различные триггерные сообщения на определенных экранах. Для этого используйте метод

Carrot.trackScreen(screenName)

Для передачи UTM-меток из ссылки используйте

Carrot.trackUtm(url)

Метод извлекает UTM-параметры из строки запроса переданного URL, фиксирует их как события и устанавливает соответствующие свойства пользователя. Типичный сценарий использования — вызов метода при открытии приложения по диплинку:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    intent?.data?.toString()?.let { Carrot.trackUtm(it) }
}

Вы можете получить список идентификаторов непрочитанных на данный момент диалогов. Это единственный метод SDK, который бросает исключение (CarrotException), — вызывайте его в try/catch:

 try {
     val unread = Carrot.getUnreadConversations()
 } catch (e: CarrotException) {
     // SDK не инициализирован или пользователь недоступен
 }

Также можно подписаться на изменения в списке идентификаторов непрочитанных диалогов

 Carrot.setUnreadConversationsCallback(callback)

Чат с оператором

Вы можете дать пользователю мобильного приложения возможность перейти в чат с оператором из любого места. Это можно реализовать двумя разными путями - через плавающую кнопку, либо напрямую вызвав метод открытия чата в любое нужное время.

Плавающая кнопка (Floating Button)

По своей сути - это элемент интерфейса, наследующийся от ConstraintLayout. Вы можете встроить его в свою разметку:

<io.carrotquest_sdk.android.ui.fab.FloatingButton
        android:id="@+id/cq_sdk_float_button"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:cq_location_fab="BOTTOM_RIGHT"
        app:cq_visibility_background="false"
        app:cq_icon_fab="@drawable/ic_send"
        app:cq_margin_fab="8dp"
        app:cq_show_social_labels="false"
        app:cq_auto_hide_fab="true"
/>

У этого элемента есть свои атрибуты: * app:cq_location_fab отвечает за расположение плавающей кнопки относительно её родительского контейнера. Возможны 4 варианта - TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT. По умолчанию BOTTOM_RIGHT. * app:cq_visibility_background отвечает за видимость эффекта затемнения при нажатии на плавающую кнопку. По умолчанию true. * app:cq_icon_fab задаёт иконку плавающей кнопки. По умолчанию @id/ic_cq_message. * app:cq_margin_fab задаёт отступы плавающей кнопки относительно своего родительского контейнера. По умолчанию 16dp. * app:cq_show_social_labels отвечает за видимость надписей рядом с иконками социальных сетей. По умолчанию true * app:cq_auto_hide_fab отвечает за автоматическое скрытие кнопки чата когда интернет не доступен. По умолчанию false

Интерфейс плавающей кнопки

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

/**
 * Показать плавающую кнопку
 */
public void showFab()
/**
 * Скрыть плавающую кнопку
 */
 public void hideFab()
/**
 * Показать кнопки интеграции
 */
public void expandMenu()
/**
 * Скрыть кнопки интеграции
 */
public void collapseMenu()
/**
 * Установить иконку чата
 * @param iconFAB Иконка
 */
public void setIconFAB(Drawable iconFAB)
/**
 * Установить отступы кнопки от краев экрана
 * @param margin Значение отступа
 */
public void setMarginFAB(int margin)
/**
 * Установить расположение кнопки
 * @param location Расположение кнопки
 */
public void setLocationFAB(LocationFAB location)

Открытие чата из произвольного места

Открыть чат можно также, вызвав из произвольного места (после инициализации) следующий код:

Carrot.openChat(context)

Уведомления

SDK поддерживает два провайдера push-уведомлений - Firebase Cloud Messaging и HUAWEI Push Kit.

Настройка Firebase Cloud Messaging

В первую очередь необходимо получить ключ и отправить его в Carrot. Вы можете найти поле для ввода ключа на вкладке Настройки > Разработчикам > Push-уведомления для SDK. Процесс настройки сервиса Firebase Cloud Messaging описан здесь

Если вы уже используете сервис Firebase Cloud Messaging для своих push-уведомлений, то для корректной работы push-уведомлений в SDK необходимо отредактировать вашу службу FirebaseMessagingService. Это необходимо для "прокидывания" токена и наших сообщений внутрь SDK. Пример:

class MyFirebaseMessagingService : FirebaseMessagingService () {
    override fun onMessageReceived (message: RemoteMessage) {
        val pushData: Map<String, String> = message. data

        if (Carrot.isCarrotPush(pushData)) {
            Carrot.sendPushNotification(pushData, this)
        } else {
            //Your code
        }
    }

    override fun onNewToken (token: String) {
        Carrot.sendPushToken(token)
        super .onNewToken(token)
    }
}

Настройка Huawei Push Kit

На устройствах Huawei без Google-сервисов (большинство моделей, выпущенных после 2019 года) FCM не работает. Чтобы доставлять пуши и на них, в дополнение к FCM используется Huawei Push Kit (HPK). SDK сам определит, что устройство Huawei, и подменит канал доставки — со стороны интеграции достаточно пробросить HPK-токен и входящие сообщения теми же методами Carrot.sendPushToken / Carrot.isCarrotPush / Carrot.sendPushNotification.

HPK настраивается в дополнение к FCM, а не вместо него. Сначала настройте FCM по шагам выше — он остаётся каналом доставки для всех остальных Android-устройств. Оба сервиса (FirebaseMessagingService и HmsMessageService) спокойно живут в одном приложении.

Настройка состоит из четырёх частей: консоль Huawei → ключи в личном кабинете Carrot quest → подключение HMS в проект → код приложения.

Шаг 1. Создайте проект в консоли Huawei

  1. Зарегистрируйте аккаунт разработчика на developer.huawei.com и пройдите верификацию (подтверждение личности или организации). Без верификации Push Kit включить нельзя; проверка документов может занять несколько дней.
  2. В консоли AppGallery Connect создайте проект и добавьте в него Android-приложение. Имя пакета (package name) должно совпадать с applicationId вашего приложения.
  3. В настройках приложения укажите SHA-256 отпечаток сертификата подписи — без него HMS не выдаст пуш-токен. Как получить отпечаток: инструкция Huawei.
  4. Включите Push Kit: в меню проекта слева откройте Рост (Grow) > Push Kit и нажмите «Включить».

Шаг 2. Скопируйте Client ID и Client Secret

В AppGallery Connect откройте Настройки проекта > Данные приложения (App information) и найдите блок «ID клиента OAuth 2.0». Скопируйте оба значения — Client ID и Client Secret. Они понадобятся на шаге 4.

Шаг 3. Настройте уведомление о получении сообщений (вебхук)

Этот шаг обязателен. В отличие от FCM, Huawei сообщает о статусе доставки пуша не в ответе на отправку, а асинхронно — вебхуком. Без настроенного вебхука Carrot quest не сможет отслеживать доставку пушей на Huawei-устройства.

  1. В AppGallery Connect откройте Рост (Grow) > Push Kit > Настройки.
  2. Включите «Уведомление о получении сообщений» на уровне проекта и нажмите «Создать» в появившемся окне.
  3. Заполните поля:

    Поле Значение
    Имя carrotquest
    Адрес подтверждения получения (callback URL) https://api.carrotquest.io/messages/webhooks/huawei/status?app=APP_ID
    Имя пользователя подтверждения получения строго carrotquest
    Ключ подтверждения получения нажмите «Сгенерировать» и сохраните значение — это ваш Webhook Secret для шага 4
    Версия v2

    APP_ID в адресе замените на идентификатор вашего аппа в Carrot quest. Он лежит там же, где ключи для SDK: Настройки > Разработчикам.

  4. Нажмите «Тест» — Huawei отправит проверочный запрос на указанный адрес. Если проверка прошла успешно, нажмите «Отправить».

Шаг 4. Загрузите ключи в Carrot quest

В личном кабинете Carrot quest откройте Настройки > Разработчикам > Push-уведомления для SDK и заполните три поля:

  • Client ID и Client Secret — из шага 2;
  • Webhook Secret — ключ подтверждения получения, сгенерированный на шаге 3.

Подключение Huawei Push Kit

Не забудьте нажать «Сохранить».

Шаг 5. Подключите HMS в проект

  1. В AppGallery Connect на странице Настройки проекта > Данные приложения скачайте файл agconnect-services.json и положите его в каталог модуля приложения (рядом с build.gradle модуля app).
  2. Добавьте репозиторий Huawei и плагин AppGallery Connect. В build.gradle уровня проекта:

    groovy buildscript { repositories { google() mavenCentral() maven { url 'https://developer.huawei.com/repo/' } } dependencies { classpath 'com.huawei.agconnect:agcp:latestVersion' } }

    Репозиторий https://developer.huawei.com/repo/ также нужно добавить туда, где ваш проект объявляет репозитории зависимостей: в allprojects { repositories { ... } } или, для новых проектов, в dependencyResolutionManagement { repositories { ... } } файла settings.gradle[.kts].

  3. В build.gradle модуля приложения примените плагин и добавьте зависимость Push Kit:

    ```groovy apply plugin: 'com.huawei.agconnect'

    dependencies { implementation 'com.huawei.hms:push:latestVersion' } ```

Вместо latestVersion подставьте актуальные версии плагина и Push Kit — их можно посмотреть в официальной инструкции по интеграции HMS.

Шаг 6. Передача токена и обработка push

Создайте сервис, унаследованный от HmsMessageService, и пробросьте в SDK токен и входящие сообщения:

class MyHuaweiPushKitService : HmsMessageService() {
    override fun onMessageReceived(message: RemoteMessage?) {
        val pushData = message?.dataOfMap.orEmpty()
        if (Carrot.isCarrotPush(pushData)) {
            Carrot.sendPushNotification(pushData, this)
        } else {
            // Логика показа собственных push-уведомлений
        }
    }

    override fun onNewToken(token: String?) {
        super.onNewToken(token)
        Carrot.sendPushToken(token)
    }

    override fun onNewToken(token: String?, bundle: Bundle?) {
        super.onNewToken(token, bundle)
        Carrot.sendPushToken(token)
    }
}

Зарегистрируйте сервис в AndroidManifest.xml внутри тега <application>:

<service
    android:name=".MyHuaweiPushKitService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.huawei.push.action.MESSAGING_EVENT" />
    </intent-filter>
</service>

Как проверить

  1. Соберите приложение и запустите его на реальном Huawei-устройстве (на нём должен быть установлен HMS Core — на устройствах без Google-сервисов он есть из коробки).
  2. Убедитесь, что в onNewToken вашего HmsMessageService пришёл токен и он передан в Carrot.sendPushToken (например, добавьте лог).
  3. Сверните приложение и отправьте пользователю ручное сообщение из кабинета Carrot quest с включённым чекбоксом «Отправить push-уведомление» — на устройство должен прийти пуш.

Общие настройки уведомлений

Иконку и цвет уведомлений о новых сообщениях можно изменить. Для установки иконки на уведомления вызовете следующий метод после инициализации SDK:

Carrot.setNotificationIcon(R.drawable.ic_notificatrion_icon);

Либо добавьте иконку с названием ic_cq_notification.xml в директорию res/drawable Для установки цвета уведомлений в файл ресурсов пропишите цвет с названием colorCqNotify и нужным вам значением:

<color name="colorCqNotify">#EF7F28</color>

Если вы хотите из любого места вашего приложения получать информацию о новых сообщениях в SDK, то вы можете реализовать BroadcastReceiver. Пример реализации:

public class MyNewMessageBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.hasExtra(NotificationsConstants.CQ_SDK_NEW_MESSAGE_ARG)) {
            IncomingMessage incomingMessage = (IncomingMessage) intent.getSerializableExtra(NotificationsConstants.CQ_SDK_NEW_MESSAGE_ARG);
            if (incomingMessage != null) {
                Toast.makeText(context, incomingMessage.getText(), Toast.LENGTH_SHORT).show();
            }
        }
    }
}

IncomingMessage - класс, который описывает входящее сообщение.

Далее нужно зарегистрировать его:

MyNewMessageBroadcastReceiver messageReceiver = new MyNewMessageBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(NotificationsConstants.CQ_SDK_NEW_MESSAGE_ACTION);
registerReceiver(messageReceiver, filter);

Важно! Если приложение закрыто и пользователь откроет чат по нажатию на пуш, то ваша стартовая активность не запустится. Приложение закроется вместе с закрытием чата. Чтобы исправить это, вы можете передать полное имя активности, которая должна запуститься при закрытии чата:

Carrot.setParentActivityClassName("io.test.MainActivity");

Метод отписки от пушей

Существуют методы отписать конкретного пользователя от пушей и от всех рассылок в принципе.

Метод для отписки от пушей:

Carrot.pushNotificationsUnsubscribe()

Метод для отписки от всех рассылок:

Carrot.pushCampaignsUnsubscribe()