Контекст — это всё. Нет ничего более раздражающего, чем использовать мобильное приложение и получать уведомление о необходимости переключиться на другое приложение для общения с другими пользователями или связи со службой поддержки.
Это часто случается при использовании приложения с кнопкой чата или «Связаться с нами», нажатие на которую перенаправляет вас далеко от самого приложения. Сколько раз вам приходилось обращаться в службу поддержки и обнаруживать, что при нажатии кнопки поддержки вы попадаете на веб-страницу, где вам нужно снова войти в систему, или, что еще хуже, на вашу стандартную программу набора номера?
Чаще всего страница даже не адаптирована для мобильных устройств. Это если вас не перенаправят напрямую в ваше почтовое приложение или на их страницу в Facebook. И всего лишь один звонок или текстовое сообщение в середине этого процесса, и вы уже не помните, что делали.
Хорошие новости! Оказывается, с новым Programmable Chat от Twilio вы можете сохранять коммуникации в приложении в контексте. Это не только позволяет предоставлять пользователям контекстную информацию, но и гарантирует вам полный контроль над взаимодействием, удерживая пользователя в вашем приложении как можно дольше.
Всё, что вам нужно, — это учетная запись Twilio и бэкэнд для генерации токенов доступа. Вы можете следовать руководству Twilio Programmable Chat QuickStart, которое покажет, как создать бэкэнд для генерации токена доступа. Или, если вы просто хотите скачать и запустить бэкэнд, вы можете клонировать любой из наших quickstarts:
Вы можете использовать ссылки, приведенные в каждом из quickstarts, чтобы помочь вам сгенерировать необходимые ключи аутентификации. В этом посте я буду использовать .NET quickstart, поэтому я сгенерировал ключи в соответствии со ссылками здесь.
Чтобы сделать наш бэкэнд доступным извне нашей локальной среды, мы будем использовать ngrok. После того, как ваш бэкэнд будет запущен локально, выполните следующую команду в новом окне терминала:
Как только это будет запущено, скопируйте сгенерированный для вас URL и откройте его в браузере по вашему выбору.
Независимо от используемого языка, вы попадете в пример приложения чата, где вся аутентификация и генерация токенов обрабатываются за вас.
С этого момента вы можете следовать инструкциям для существующего Android-приложения, которое у вас уже есть, или работать с примером приложения, о котором я расскажу дальше.
Альтернативно, если вы хотите запустить приложение напрямую, не следуя всем шагам ниже, вы можете просто скачать его из репозитория GitHub здесь и запустить.
Вместо того, чтобы пошагово описывать, как создать Android-приложение, я решил показать, как добавить Programmable Chat в существующее приложение.
Мы будем использовать пример Android Displaying Bitmaps Sample. Я выбрал это приложение, так как оно часто используется для обучения, и я думаю, было бы здорово иметь возможность обсуждать некоторые из удивительных изображений в нем с другими энтузиастами фотографии.
Если фотография вам неинтересна, у Google есть множество других примеров кода, которые вы можете использовать в качестве отправной точки для интеграции Programmable Chat.
Теперь, когда мы определились с приложением, которое будем использовать, давайте клонируем его, чтобы начать вносить изменения. Из вашего терминала клонируйте репозиторий GitHub туда, где вы хотите хранить свое приложение. Обычно я храню свои приложения в *~/Projects/Java*.
После завершения откройте его в Android Studio. Если у вас еще не установлена Android Studio, вы можете найти ссылку для скачивания для вашей любимой операционной системы здесь. Обычно я люблю запускать свои приложения напрямую на своем телефоне, но вы можете найти информацию о том, как запускать их на эмуляторах, здесь.
Если вы решите пойти этим путем, убедитесь, что вы используете эмулятор с архитектурой armeabi-v7a, чтобы приложение работало.
Теперь мы изменим это приложение, чтобы пользователи могли присоединяться к каналу разговора и обсуждать каждое изображение с другими пользователями приложения.
В Android Studio убедитесь, что вы используете представление «Проект» (Project view) и откройте файл *src/main/**res/menu/main_menu.xml* и добавьте новый элемент в меню.
Теперь откройте *src/main/java/com/example/android/displayingbitmaps/ui/ImageDetailActivity.java* и в методе *onOptionsItemSelected* создайте новое объявление case под названием *discuss* следующим образом:
Мы создали новую запись в меню, которая при нажатии приведет пользователя на страницу чата. Оставаясь в том же файле, измените его переменные члена, чтобы получить доступ к идентификатору изображения. Вы можете сделать это, добавив новую переменную в верхнюю часть класса под названием *extraCurrentItem*.
Теперь нам нужно присвоить его, поэтому удалите ключевые слова *final* и *int* из:
Страница чата будет новым Activity, которое мы создадим чуть позже.
Прежде чем приступить к Activity чата, нам нужно убедиться, что мы импортировали Twilio Android SDK. Вы можете скачать его здесь.
После скачивания и распаковки обоих у вас должна появиться папка *libs*. Из каталога *twilio-rtc-common* переместите *armeabi-v7a* в новую папку в *Application/src/main/* под названием *jniLibs*. Теперь ваша структура в Android Studio должна выглядеть так:
Все еще из каталога *twilio-rtc-common* переместите twilio-common-android.jar в новую папку в вашем проекте под названием Libs в *Application/.* Из каталога *twilio-ip-messaging-android* скопируйте libs/twilio-ip-messaging-android.jar в папку Libs, которую вы только что создали.
Теперь нам нужно сообщить Android Studio, где найти наши библиотеки. Вы можете сделать это, открыв файл *build.gradle*, который находится внутри каталога Application, и добавив в него пару строк, чтобы он синхронизировался и разрешил зависимости.
Теперь, когда мы импортировали библиотеки в проект, нам нужно изменить *AndroidManifest.xml*, чтобы добавить в него тег *service*. Мы добавляем это, чтобы часть обмена сообщениями нашего приложения всегда работала в фоновом режиме. Таким образом, вам не нужно иметь открытое приложение, чтобы получать новые сообщения.
Откройте *AndroidManifest.xml* и добавьте следующее после последнего activity в нем.
Также воспользуемся этой возможностью, чтобы создать несколько каталогов, которые мы будем использовать позже. Таким образом, все новые файлы, которые мы создаем, будут создаваться в новом пакете. Вы можете сделать это вручную или через терминал. Из каталога *src* выполните:
Android-приложения по умолчанию не поддерживают состояние, что означает, что вы не можете сохранять глобальные переменные на протяжении всего жизненного цикла приложения. Поскольку мы скоро инициализируем SDK, наше приложение придется изменить, чтобы оно могло работать таким образом. Мы создадим новый класс под названием *TwilioApplication* в *src/main/java/com/twilio/ipmessaging/application* и поместим в него следующий код.
Теперь откройте *AndroidManifest.xml* и добавьте новый запрос разрешения для состояния Wi-Fi, а также измените тег *Application*, добавив новый атрибут *android:name*. Установите его значение *com.twilio.ipmessaging.application.TwilioApplication*.
Вы могли заметить, что при создании класса *TwilioApplication* одна из зависимостей не была удовлетворена. Это потому, что мы еще не создали наш клиент — *BasicIPMessagingClient*. Мы скоро к нему приступим.
Чтобы начать отправлять и получать сообщения, сначала нам нужно убедиться, что мы аутентифицированы на серверах Twilio. Мы будем использовать бэкэнд, который мы создали ранее, для генерации токенов доступа, которые наше приложение затем сможет использовать для аутентификации.
В *src/main/java/com/twilio/ipmessaging/util* создайте новый Java-класс, назовите его *ILoginListener* и выберите его *kind* как *Interface*. Замените его содержимое следующим определением класса:
Мы реализуем этот интерфейс позже, когда будем работать над входом в чат. Вход осуществляется через HTTP, поэтому нам понадобится способ делать HTTP-запросы. Существует несколько библиотек, которые помогут вам с этим, но инженеры Twilio создали очень простой HTTP-обертку для этого.
Скопируйте код из этого gist и вставьте его в новый файл под названием *HttpHelper.java* в *src/main/java/com/twilio/ipmessaging/util/*.
Последний кусочек головоломки, прежде чем мы сможем работать над нашим Activity чата, — это реализация *BasicIPMessagingClient.java*. Здесь произойдет инициализация SDK, и мы уже ранее изменили наше приложение, чтобы поддерживать состояние этого класса.
Создайте новый класс под названием *BasicIPMessagingClient.java* в *src/main/java/com/twilio/ipmessaging/util/* и заставьте его реализовывать *IPMessagingClientListener* и *TwilioAccessManagerListener*.
Теперь добавьте следующие импорты и переменные члена в начало этого файла, которые мы будем использовать дальше.
Мы только что создали конструктор для нашего класса, который будет принимать *Context* в качестве аргумента, и методы доступа, которые будут хранить токен возможностей, который мы сгенерируем дальше.
Создайте новый метод под названием *doLogin*. Мы будем вызывать этот метод всякий раз, когда новый пользователь присоединяется к чату.
В приведенном выше коде мы проверяем, инициализирован ли SDK. Если нет, мы создаем новый экземпляр клиента и новый менеджер доступа. Поэтому создайте новый метод под названием *createClientWithAccessManager* внизу класса.
Получение токена осуществляется путем выполнения HTTP-запроса к конечной точке, которую мы создали во время quickstart. Мы сделаем это, создав новый класс внизу этого класса под названием *GetCapabilityTokenAsyncTask*.
Если SDK уже инициализирован, мы можем просто вызвать *createClientWithToken* и повторно использовать уже имеющийся токен.
Если вы хотите просто скопировать код для всего этого класса, вы можете получить полный исходный код здесь.
Создайте новое пустое Android Activity под названием *ChatActivity* в *src/main/java/com/twilio/ipmessaging/ui*.
Теперь вернемся в *ChatActivity*, измените основной класс, чтобы он реализовывал *ChannelListener, ILoginListener* и *IPMessagingClientListener*. Android Studio попросит вас реализовать методы интерфейса, так что вы можете позволить ей сгенерировать методы для вас.
В верхнюю часть класса добавьте следующие переменные члена и импорты, чтобы ваш класс выглядел так:
Убедитесь, что вы обновили выделенный URL, чтобы он соответствовал тому, который вы использовали для своего бэкэнда.
Замените содержимое очень простого метода *onCreate* логикой, которая попытается аутентифицироваться.
Приведенный выше код аутентифицирует пользователя при загрузке Activity и проверяет, была ли нажата кнопка отправки. В случае, если она была нажата, он попытается опубликовать сообщение.
Создайте новый метод внизу класса под названием *authenticateUser* и добавьте следующее:
Теперь создайте класс в том же Activity под названием *GetCapabilityTokenAsyncTask* и добавьте следующее:
Обратите внимание, как мы делаем HTTP-запрос, используя URL, который мы определили в *authenticateUser*, а затем устанавливаем токен возможностей для нашего клиента в качестве результата. Мы также получаем информацию о пользователе из quickstart, чтобы установить имя пользователя для каждого из пользователей. Если у вас уже есть концепция имен пользователей в вашем приложении, вы можете использовать их вместо этого.
Вы также могли заметить, что в методе *onPostExecute* мы делаем запрос к *basicClient.doLogin()*. *basicClient* — это экземпляр *BasicIPMessagingClient*, и ранее мы реализовали вызов *onLoginFinished* в нем, который мы сейчас будем использовать. Замените содержимое *onloginFinished* следующим:
Мы проверяем, существует ли уже канал для этого изображения, и если нет, мы просто создаем его. Когда канал загружается, мы также загружаем все сообщения, а затем присоединяемся к нему.
После присоединения к каналу мы вызываем *setupListView*, чтобы все сообщения в этом канале отображались на экране. Создайте новый метод под названием *setupListview* в основном классе и добавьте следующее:
Теперь все загруженные в этом канале сообщения будут добавлены в список. Однако эти сообщения не всегда упорядочены, поэтому чуть выше нового метода создайте новый класс компаратора. Это поможет нам упорядочить сообщения перед добавлением их в представление.
Еще одна из обязанностей метода *setupListView* — убедиться, что наш ListView правильно связан с адаптером для отображения сообщений. Мы создадим представление для этого адаптера сейчас, перейдя в *src/main/res/layout/* и создав новый файл под названием *message_item_layout.xml* со следующим кодом:
Это новое представление будет использовать несколько 9-патч изображений для отображения пузырька вокруг текста. Вы можете скачать эти изображения здесь и поместить их в *src/main/res/drawable-xhdpi*.
Нам просто нужен держатель представления, чтобы правильно отображать сообщения в listview. Создайте новый класс под названием *MessageViewHolder.java* в *src/main/java/com/twilio/ipmessaging/ui/* и добавьте следующий код:
Пришло время запустить приложение. После его загрузки выберите одну из картинок и в правом верхнем углу нажмите на меню и выберите «Обсудить».
Вы увидите, что появится экран чата и загрузится ваша клавиатура. Напишите любое сообщение и нажмите «Отправить». Сейчас также самое время отправить приложение некоторым вашим друзьям, чтобы они могли пообщаться с вами.
Мы начали с приложения, которое позволяло просто просматривать удивительные картинки, но не предлагало никакого способа взаимодействия с другими пользователями, смотрящими на них.
Затем мы изменили его так, чтобы пользователям никогда не приходилось покидать приложение, и все общение было сосредоточено вокруг единого элемента контента внутри приложения. Контекст — ключ к тому, чтобы удержать пользователей в вашем приложении как можно дольше.
Как бы вы изменили свое приложение, чтобы пользователи могли общаться друг с другом? Возможно, у вас будет канал поддержки, где пользователи смогут напрямую общаться с вами, когда у них возникнут вопросы или они захотят сообщить об ошибках? Или, возможно, вы могли бы отображать сообщения, отправленные вашим приложением, на большой доске сообщений.
Мне хотелось бы увидеть, что вы придумаете, и как вы модифицируете свои приложения, чтобы сохранять беседы в контексте. Свяжитесь со мной в Twitter @marcos_placona или по электронной почте marcos@twilio.com, чтобы рассказать об этом.