Мобильные приложения: чат в WebView
Встраивание reactive.chat в iOS и Android: страница /embed/SITE_KEY в WKWebView или WebView, идентификация через JavaScript, загрузка файлов, кнопка «Назад» и push через вебхуки.
Для приложений нет нативного SDK. Вместо этого приложение загружает страницу, специально созданную для WebView:
https://reactive.chat/embed/SITE_KEY
У страницы нет обрамления, навигации и кнопки чата: виджет заполняет экран и сразу открыт. Это тот же чат, что на сайте: тот же проект, дизайн и входящие. Ключ сайта находится в аккаунте в Проект → Установка.
Свойства страницы:
- только для активных проектов; иначе 404;
viewport-fit=coverи безопасная область: поле ввода расположено над полосой у нижнего края;- фон фирменного цвета, пока виджет не готов;
X-Robots-Tag: noindexиframe-ancestors 'none': страница предназначена для WebView, а не<iframe>на другом сайте;- язык по языку устройства.
iOS (WKWebView)
import WebKit
let konf = WKWebViewConfiguration()
konf.allowsInlineMediaPlayback = true // otherwise the full-screen player pulls the chat away
let web = WKWebView(frame: .zero, configuration: konf)
web.scrollView.bounces = false
web.scrollView.contentInsetAdjustmentBehavior = .never
web.load(URLRequest(url: URL(string: "https://reactive.chat/embed/SITE_KEY")!))
Размещайте WebView на всей области, а не внутри safe area layout guide: страница сама учитывает отступы.
Android (WebView)
val web = findViewById<WebView>(R.id.chat)
web.settings.javaScriptEnabled = true
web.settings.domStorageEnabled = true // required: no session without it
web.settings.mediaPlaybackRequiresUserGesture = false
web.webViewClient = WebViewClient() // otherwise the system browser opens
web.loadUrl("https://reactive.chat/embed/SITE_KEY")
domStorageEnabled обязателен: виджет хранит ID в хранилище WebView. Без него каждый запуск начинает новый разговор.
Передача вошедшего пользователя
Никогда через адрес. Хеш в URL попадает в историю, журналы и заголовки Referer. Передавайте идентификационные данные через JavaScript после загрузки. userHash вычисляет ваш сервер (Идентификация посетителей); секрету не место в пакете приложения, потому что приложения можно разобрать. При входе приложение должно получить три значения с вашего сервера.
// Android, in onPageFinished
web.evaluateJavascript(
"""ReactiveChat("identify",{userId:"$id",name:"$name",userHash:"$hash",exp:$exp});""",
null)
// iOS, in webView(_:didFinish:)
web.evaluateJavaScript(
"ReactiveChat(\"identify\",{userId:\"\(id)\",name:\"\(name)\",userHash:\"\(hash)\",exp:\(exp)});")
Корректно экранируйте значения для JavaScript (проще всего сериализовать их в JSON в приложении). Вызов до загрузки тоже работает: очередь ReactiveChat.q принимает его до загрузки виджета.
Что отличается в WebView
- Push-уведомления не приходят из чата. Если приложение должно связаться с пользователем при закрытом чате, настройте вебхук на
message.createdи отправляйте push самостоятельно. - Загрузка файлов работает на Android, только когда приложение передаёт выбор файла (
WebChromeClient.onShowFileChooser); iOS делает это сам. - Кнопка «Назад» (Android): у страницы нет собственной истории. Рассматривайте чат как экран приложения и закрывайте его вместо вызова
web.goBack(). - Фон: не уничтожайте WebView при переходе приложения в фон. Виджет сам переподключается после перерывов и затем отправляет сообщения из буфера (Транспорт).
- Согласие: на странице встраивания нет платформы согласия; поэтому виджет запускается без согласия и сначала хранит ID только на время жизни WebView (Интеграция конфиденциальности). Проверьте в приложении, сохраняется ли разговор после перезапуска приложения.
Передача событий в приложение
События виджета можно передавать приложению через JavaScript-мост, например для значка непрочитанных сообщений:
// Android: register web.addJavascriptInterface(Bruecke(), "App") beforehand
web.evaluateJavascript(
"ReactiveChat('on','unread',function(e){ App.ungelesen(e.count); });", null)
Далее: Smart Answer
Обновлено: