Android
Библиотека Kavchat для Android добавляет в приложение бота поддержки, который работает по сценарию. В ней есть компоненты Jetpack Compose и Activity для приложений на Views. Ответы предсказуемы и доступны даже без сети на основе последней опубликованной версии. Требуется Android 6.0 (API 23) или новее.
Библиотека состоит из двух модулей: kavchat-engine, версии движка диалогов на Kotlin/JVM без зависимостей от Android и сторонних библиотек, и kavchat, который включает сетевое взаимодействие (HttpURLConnection), кеш на устройстве (SharedPreferences), компоненты Compose KavchatChat и KavchatLauncher, а также KavchatActivity.
Установка
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven("https://jitpack.io")
}
}
// app/build.gradle.kts
dependencies {
implementation("com.kavchat:kavchat-android:0.0.11")
}Библиотека распространяется через JitPack, поэтому один раз добавьте его репозиторий рядом с google() и mavenCentral(). Исходный код SDK открыт по лицензии MIT: bitbucket.org/maxsave/kavchat-android.
Библиотека сама объявляет разрешение INTERNET и KavchatActivity в своём манифесте. Вручную ничего добавлять не нужно.
Настройка
Вызовите configure один раз в Application.onCreate:
class App : Application() {
override fun onCreate() {
super.onCreate()
Kavchat.configure(this, publicKey = "pk_live_...")
// Optional: Kavchat.configure(this, "pk_live_...", apiBase = "https://api.kavchat.com", locale = "he")
}
}Публичный ключ можно включать в приложение. Секретный ключ (sk_live_...) нельзя включать в него ни при каких обстоятельствах.
Compose
Плавающая кнопка в углу, выбранном в панели управления, открывает чат на весь экран:
KavchatOverlay(Modifier.fillMaxSize()) {
AppContent()
}Можно также разместить кнопку самостоятельно или встроить чат в свой экран:
KavchatLauncher() // com.kavchat.ui.KavchatLauncher
KavchatChat(Modifier.fillMaxSize()) // full chat, no close button
KavchatChat(Modifier.fillMaxSize(), onClose = { navController.popBackStack() })Открывайте и закрывайте чат плавающей кнопки из кода с помощью Kavchat.controller.setPresented(true) и setPresented(false).
Views (без Compose в приложении)
Kavchat.open(context) // starts KavchatActivityИз Java: Kavchat.open(context);. Внутри Activity используется Compose, но вашему приложению использовать его необязательно.
Токен идентификации
Для идентификации вошедшего пользователя используйте JWT, подписанный вашим сервером с помощью секретного ключа (см. Идентификация пользователей). Токен передаётся в заголовке Authorization: Bearer <token>. Идентифицированный пользователь может видеть версии, доступные только тестовым пользователям, и отправлять форму обращения без электронной почты или телефона.
Kavchat.setUser(token = identityToken, name = "Dana") // after login
Kavchat.setUser(token = null) // after logoutПри смене пользователя версия загружается заново и начинается новый диалог, чтобы переписка одного пользователя не отображалась у другого.
Экраны приложения: onScreen
Кнопка типа screen в сценарии запрашивает у приложения открытие одного из его экранов. Сначала чат закрывается (диалоговое окно KavchatLauncher или KavchatActivity), чтобы экран был виден:
Kavchat.onScreen = { screen, targetId ->
navController.navigate("$screen/${targetId.orEmpty()}") // e.g. "orders", "42"
}Без обработчика такие кнопки ничего не делают. Кнопки link открывают только ссылки https (в браузере) и tel (в приложении для звонков). Для аналитики Kavchat.onEvent сообщает о событиях Ready, Unavailable, Open, Close, Effect и Ticket.
Список экранов в редакторе
Один раз объявите экраны, которые может открывать приложение, в Kavchat.configure(..., screens = ...) (тип KavchatAppScreen). SDK самостоятельно отправляет список в Kavchat, а редактор сценариев предлагает эти экраны в выпадающем списке с названиями вместо поля для свободного ввода. Редактор также запрашивает идентификатор элемента, если он нужен экрану, и предупреждает о кнопках, ведущих на необъявленный экран. Вводить список экранов вручную в панели управления не нужно.
Kavchat.configure(
this, publicKey = "pk_live_...",
screens = listOf(
KavchatAppScreen("orders", "My orders"),
KavchatAppScreen("product", "Product page", needsTarget = true), // needs a targetId
),
)
// or later: Kavchat.registerScreens(listOf(...))idсодержит значение, которое получаетonScreen: латинские буквы, цифры,_,.и-, до 40 символов.labelсодержит название, которое видит администратор, до 60 символов. Можно добавить до 100 экранов. Некорректные записи и повторяющиеся идентификаторы пропускаются.needsTarget: кнопка также передаёт идентификатор элемента (например, товара), который поступает вonScreenкакtargetId.- Список отправляется в фоновом режиме после загрузки версии, только при изменении или раз в неделю. При сбое уведомления не показываются, а отправка повторяется при следующем запуске. Пользователь ничего не видит.
- Зарегистрированные экраны отображаются в панели управления в разделе «Бот», «Настройки», «Экраны приложения» вместе с платформами, сообщившими о каждом экране. Экран, удалённый из приложения, можно удалить и там.
Цвета
Цвета задаются в панели управления (primaryColor). Текст на фоне фирменного цвета отображается белым или почти чёрным в зависимости от контрастности по WCAG. Если цвет слишком светлый для текста на белом фоне, в ссылках и кнопках он заменяется на почти чёрный. Имя бота, подзаголовок, изображение и сторона размещения плавающей кнопки (start или end) также задаются в панели управления, поэтому меняются без обновления приложения. Оформление поверхностей и типографика берутся из вашей MaterialTheme.
Надпись «Работает на Kavchat by maxsave» со ссылкой на kavchat.com отображается на всех тарифах. На тарифе Premium её можно скрыть в настройках бота.
Языки и RTL
- Язык интерфейса определяется значением
locale, переданным вconfigure. Если оно не передано, используется язык устройства при наличии перевода (he, en, ar, ru, es, fr, de, pt, it, tr), затем язык сценария и, наконец, английский. - Сопоставление со сценарием всегда выполняется на языке сценария с учётом пропускаемых частых слов и приставок в иврите и арабском.
- Для иврита и арабского
LocalLayoutDirectionвсего чата устанавливается в RTL. Ничего не отражается вручную: если вы оборачиваете компоненты, используйтеstartиend. Оставьтеandroid:supportsRtl="true"в манифесте приложения.
Ответы ИИ (Premium)
В приложении ничего настраивать не нужно. Когда в панели управления включены ответы ИИ (с вашим собственным ключом провайдера ИИ), вопрос, на который не отвечает ни один сценарий, отправляется в Kavchat. Во время ожидания, до 20 секунд, чат показывает, что бот печатает. Ответ отображается обычным текстом с небольшой меткой «Ответ ИИ» на языке интерфейса. Под ним появляются кнопка связанной темы, если она есть, и кнопка «Обратиться в поддержку».
Если ответа нет, запрос завершился ошибкой, занял слишком много времени или превысил лимит (10 ответов на диалог за каждые 15 минут), чат показывает обычное сообщение «Не удалось найти ответ». Вопрос по-прежнему попадает в отчёт о вопросах без ответа, а ответы ИИ сохраняются в диалоге, как и любые другие сообщения.
Чат с оператором
В приложении ничего настраивать не нужно. Когда в панели управления включён чат с операторами, чат в приложении работает точно так же, как виджет на сайте.
- Эта возможность отображается только тогда, когда чат с операторами включён в опубликованной версии. Когда бот показывает кнопку «Обратиться в поддержку», SDK проверяет, есть ли свободный оператор. Результат сохраняется на 30 секунд. Если оператор свободен, перед ней появляется кнопка «Чат с оператором». Если нет, отображается только форма обращения. Над ней кратко поясняется причина: нерабочее время (с указанием времени возобновления работы) или все операторы заняты.
- Перед началом чата нужно заполнить короткую форму: имя, электронная почта или телефон, отдел (только если доступно больше одного отдела) и первое сообщение (необязательно). Гость должен оставить электронную почту или телефон. Пользователю, идентифицированному с помощью токена, не нужно указывать ни то ни другое. Если к моменту отправки свободных операторов уже нет, открывается форма обращения с ранее введёнными данными.
- Во время ожидания отображаются время до преобразования чата в обращение и кнопка «Оставить сообщение вместо чата». Время ожидания задаётся в панели управления, по умолчанию это 2 минуты. Во время ожидания тоже можно писать, оператор увидит сообщения. Если никто не освободится вовремя, чат сохраняется как обычное обращение и отображается его номер.
- Во время чата отображаются имя оператора, уведомление о его подключении (в том числе после перевода на другого оператора), индикатор набора текста и кнопка завершения чата. Сообщения содержат только обычный текст, до 2000 символов, без ссылок. Сообщение, которое ещё не дошло до сервера, помечается как «Отправляется...». Если отправка несколько раз завершилась ошибкой, можно нажать на сообщение, чтобы повторить попытку. Повторная попытка не создаёт дубликат.
- После каждого разрыва соединения SDK немного ждёт, получает пропущенные данные и подключается заново. Время ожидания постепенно увеличивается. Сообщения всегда отображаются по порядку и без дубликатов. Если постоянное соединение установить не удаётся (например, за корпоративным прокси), SDK временно переходит на периодические запросы к серверу.
- Когда приложение переходит в фоновый режим, соединение закрывается. При возвращении в приложение SDK получает пропущенные данные и подключается заново. Открытый чат продолжается даже после закрытия и повторного запуска приложения, если не прошло 12 часов.
- В этой версии нет push-уведомлений. Сообщения поступают только при открытом приложении. Ответ, отправленный, пока приложение было в фоновом режиме, появляется сразу после возвращения в него.
- Данные доступа к чату хранятся в памяти. На устройстве они сохраняются только в зашифрованном виде с использованием ключа Android Keystore. Они не записываются в URL или журнал. Данные удаляются, когда чат завершается, преобразуется в обращение или срок его действия истекает, а также при смене пользователя через
setUser.
С помощью Kavchat.controller.livePage можно указать оператору, с какого экрана пришёл пользователь.
Вопросы, условия и лиды
Настройка в приложении не требуется. Сценарий может запрашивать данные (имя, телефон, электронную почту, число или произвольный текст), выбирать дальнейшие действия на основе известной информации и отправлять лид.
- Подходящая клавиатура: когда бот ждёт ответа, для текстового поля открывается клавиатура для ввода телефона, электронной почты или чисел. При запросе имени клавиатура переключается на заглавную букву в начале каждого слова. Если ответ некорректен, бот выводит короткое сообщение на языке чата, а поле выделяется. Для необязательного вопроса отображается кнопка «Пропустить». Ввод «Отмена» на любом поддерживаемом языке позволяет выйти из вопроса.
- Телефон: для номера без
+используется страна по умолчанию, заданная для рабочего пространства в настройках панели управления. - Лид: шаг отправки лида показывает текст согласия с кнопками «Отправить» и «Нет, спасибо», а затем сообщение с подтверждением. Лид добавляется в очередь на устройстве и отправляется на сервер. Если нет сети или сервер недоступен, отправка повторяется, в том числе при следующем запуске и после
reload(). Сервер игнорирует дубликаты. - Предзаполнение: форма обращения и форма запроса чата с оператором заполняются собранными именем, электронной почтой и телефоном. Все собранные значения прикрепляются к обращению или запросу чата с оператором. Вопросы перед чатом с оператором (Premium) задаются до подключения.
- Токен идентификации: при использовании
setUserполяname,emailиphoneиз токена заполняют ответы на соответствующие вопросы, и бот их пропускает. - Текущий экран: условия могут проверять текущий экран. Задайте
Kavchat.controller.livePage(например,"checkout").
Собранные значения являются персональными данными. Они остаются в диалоге, сохранённом на устройстве, и передаются только с лидами, обращениями и чатами с оператором, но никогда не попадают в отчёты.
Работа без сети и кеширование
Последняя версия сохраняется в SharedPreferences вместе с её ETag и проверяется при каждом запуске с помощью If-None-Match (304). Без сети используется сохранённая копия и отображается соответствующее уведомление. Когда бот выключен, доступен только тестовым пользователям или квота исчерпана, ничего не отображается. Открытый диалог сохраняется до 30 минут бездействия, поэтому выход из чата или приложения не начинает его заново. Данные о ходе диалога отправляются через две секунды после последнего действия и сразу при переходе приложения в фоновый режим.