Разное

Android studio чат пример: Как создать чат приложение для Android с помощью Firebase

Содержание

Чат на Java — создание программы для Андроид, разработка онлайн-чата на itProger

Представляем вам курс по созданию программ для Андроид при помощи программы Android Studio. В ходе курса вы научитесь создавать Android программы с использованием дополнительных библиотек и базы данных. Вами будет создана чат программа, что будет синхронизироваться с базой данных Firebase.

Полезные ссылки:

  1. Курс по языку Java;
  2. Вступительный курс по Андроид разработке;
  3. Официальный сайт Java;
  4. Скачать Java JDK;
  5. Скачать Android Studio с официального сайта.

Разработка на Android

Создание программ для Андроида максимально актуальна на сегодняшний день. Платформа Android является одной из лидирующих мировых платформ. Сотни тысяч разработчиков по всему миру работают над созданием программ Андроид, создавая красивые и полноценные игры и приложения под устройства на базе ОС Android.

ОС Андроид стоит на самых разнообразных гаджетах, но чаще всего она встречается на смартфонах. Согласно разным статистическим данным, в 2017 году порядка 85% всех смартфонов построено на Android. Количество проданных копий мобильных телефонов на Андроид переваливает за 1,5 млрд.

Как создавать программы на Андроид?

Для создании программы на Андроид применяется язык программирования Java, а также программа Android Studio. Внутри программы вы можете использовать текстовый, а также графический редактор.

Текстовый редактор позволяет прописать весь функционал для игры/приложения, а графический редактор отвечает за дизайн и внешний вид приложения.

База данных Firebase

При разработке Android программ вы можете использовать практически любую базу данных. В вашем распоряжение такие БД, как:

  • SQLite;
  • MySQL;
  • MongoDB;
  • Firebase;
  • и множество других.

В ходе курса мы будем использовать БД Firebase, так как она одна из наиболее простых для интеграции в Android и обладает широким спектром возможностей.

Благодаря тому, что Firebase была куплена компанией Google в 2014 году, то интеграция этой БД и Android стала легким и быстрым процессом. Напомним что ОС Android также принадлежит компании Google.

У нас на сайте есть курс по Firebase и Андроид разработке, если вам интересно, то вы можете посмотреть его здесь.

План курса

В ходе курса вы создадите чат на Java для Андроид, которая будет синхронизироваться с базой данных Firebase. Вы создадите интерфейс, добавите все необходимые библиотеки, а также создадите множество крутых эффектов: от эмоджи и до красивых «Bubble» блоков с сообщениями.

По итогу получится полноценный чат на Андроид. Это будет простой чат на Java, что ознакомит вас с созданием программ под Андроид. Сама программа будет являться онлайн чатом для Андроид. То есть выполнение всех действий будет связано с базой данных и синхронизация данных будет происходить в автоматическом режиме.

Пишем чат под Android на Websocket’ах / Хабр

Привет Хабр!

Во время локдауна я решил поупражняться в разработке под Android. Начать решил с простой гиперказуальной игры с элементами дуэли. Взаимодействие игроков решил реализовать через отдельный сервер и websocket’ы, но пока читал про все это дело, понял, что простого туториала на русско-язычных ресурсах почему-то нет. Поэтому, решил восполнить этот пробел.

В этой статье я постараюсь описать как настроить WebSocket’ы на примере чата с сервером на SpringBoot и клиенте под Android.

Что такое WebSocket

В клиент-серверной архитектуре все взаимодействие происходит как правило через запросы от клиента к серверу в синхронном режиме. Но что делать, если запрашиваемое действие необходимо выполнить асинхронно? Или пользователь должен получить оповещение об обновлении данных, которые зависят от других пользователей или быстро теряют актуальность? Примеры таких приложений: мессенджеры, многопользовательские игры и т.д. В этом случае возникает потребность в отправке данных от сервера клиенту. Такое взаимодействие можно реализовать через polling или long-polling, что подразумевает периодический опрос сервера «не появилось ли для меня чего-то нового». Или же воспользоваться WebSocket’ами, которые позволяют реализовать двустороннюю связь в режиме реального времени.

На чем пишем?

Все будет написано на Kotlin. Сервер поднимать буду на SpringBoot. Клиент будет под Android, основные зависимости: Hilt, converter-gson, okhttp3, StompProtocolAndroid (библиотека для поддержки STOMP-клиента через websocket)

Сервер

Итак, начнем с написания сервера. Я пропущу этап инициализации SpringBoot приложения и перейдем сразу к описанию ресурсов и конфигурации сокетов. Для обмена сообщениями заведем ресурс, описывающий структуру сообщения и добавим jackson аннотаций для корректной сериализации/десериализации LocalDateTime:

@JsonInclude(JsonInclude.Include.NON_NULL)
data class ChatSocketMessage(
        val text: String,
        var author: String,
        @JsonDeserialize(using = LocalDateTimeDeserializer::class)
        @JsonSerialize(using = LocalDateTimeSerializer::class)
        var datetime: LocalDateTime,
        var receiver: String? = null
)

Создадим REST-контроллер для обработки сообщений

@RestController
@RequestMapping(LINK_CHAT)
class ChatController(
        private val simpleMessageTemplate: SimpMessagingTemplate
) {
    @MessageMapping("/sock")
    fun chatSocket(res: ChatSocketMessage) {
        sendMessageToUsers(res) //отправим сообщения другим пользователям
    }
    
    private fun sendMessageToUsers(message: ChatSocketMessage) {
        if(message.
receiver != null) { //если сообщение отправляется в приватный чат simpleMessageTemplate.convertAndSendToUser(message.receiver!!, CHAT_TOPIC, message) } else { //если сообщение отправляется в общий чат simpleMessageTemplate.convertAndSend(CHAT_TOPIC, message) } } }

Ну и в конце настроим WebSocket’ы на сервере

@Configuration
@EnableWebSocketMessageBroker
open class WebSocketConfig: WebSocketMessageBrokerConfigurer {
    override fun configureMessageBroker(config: MessageBrokerRegistry) {
      /*
      запускаем simple broker с перечислением топиков, на которые будем подписываться 
      При необходимости можно настраивать сторонние брокеры, 
      такой как RabbitMQ
      */  
      	config.enableSimpleBroker(TOPIC) 
        /*
        задаем префиксы для приложения и пользователя
        */
        config.setApplicationDestinationPrefixes(LINK_CHAT)
        config.setUserDestinationPrefix("/user")
    }
    override fun registerStompEndpoints(registry: StompEndpointRegistry) {
      /*
      указываем endpoint, который будет использоваться для подключения сокетов.
Не забываем включить SockJS. При этом надо будет при подключении добавить к адресу /websocket */ registry.addEndpoint(LINK_CHAT) .setAllowedOrigins("*") .withSockJS() } }

Клиент

Помечаем наш MainActivity анотацией AndroidEntryPoint и инджектим ViewModel, которая будет отвечать за взаимодействие с сервером.

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    @Inject
    lateinit var mainViewModel: MainViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
  			//описываем инициализацию
    }
		//...............
}

Переходим к описанию MainViewModel:

class MainViewModel @Inject constructor(
    var db: AppDb // имплементация RoomDatabase
) : ViewModel() {
    companion object{
      //указываем endpoint, на который регистрировали сокет, не забываем добавить /websocket
        const val SOCKET_URL = "ws://10.0.2.2:8080/api/v1/chat/websocket"
      // заводим название топика
      const val CHAT_TOPIC = "/topic/chat"
      //указываем endpoint метода, на который будем слать сообщения
        const val CHAT_LINK_SOCKET = "/api/v1/chat/sock"
    }
    /*
    	инициализируем Gson для сериализации/десериализации 
    	и регистрируем дополнительный TypeAdapter для LocalDateTime
    */
    private val gson: Gson = GsonBuilder(). registerTypeAdapter(LocalDateTime::class.java,
        GsonLocalDateTimeAdapter()
    ).create()
    private var mStompClient: StompClient? = null
    private var compositeDisposable: CompositeDisposable = CompositeDisposable()
    private val _chatState = MutableLiveData<Message?>()
    val liveChatState: LiveData<Message?> = _chatState
    init {
      //инициализация WebSocket клиента
        mStompClient = Stomp.over(Stomp.ConnectionProvider.OKHTTP, SOCKET_URL)
            .withServerHeartbeat(30000)
        initChat() //инициализация подписок
    }
		
    private fun initChat() {
    //опишем ниже
    }
    /*
    отправляем сообщение в общий чат
    */
    fun sendMessage(text: String) {
        val chatSocketMessage = ChatSocketMessage(text = text, author = "Me")
        sendCompletable(mStompClient!!.send(CHAT_LINK_SOCKET, gson.toJson(chatSocketMessage)))
    }
    private fun sendCompletable(request: Completable) {
        compositeDisposable?.add(
            request.
subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { Log.d(TAG, "Stomp sended") }, { Log.e(TAG, "Stomp error", it) } ) ) } override fun onCleared() { super.onCleared() mStompClient?.disconnect() compositeDisposable?.dispose() } }

В конце настраиваем подписки на наш топик и состояние соединения

private fun initChat() {
        if (mStompClient != null) {
          //настраиваем подписку на топик
            val topicSubscribe = mStompClient!!.topic(CHAT_TOPIC)
                .subscribeOn(Schedulers.io(), false)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ topicMessage: StompMessage ->
                    Log.d(TAG, topicMessage.payload)
                    //десериализуем сообщение
                    val message: ChatSocketMessage =
                        gson.
fromJson(topicMessage.payload, ChatSocketMessage::class.java) addMessage(message) //пишем сообщение в БД и в LiveData }, { Log.e(TAG, "Error!", it) //обработка ошибок } ) //подписываемся на состояние WebSocket'a val lifecycleSubscribe = mStompClient!!.lifecycle() .subscribeOn(Schedulers.io(), false) .observeOn(AndroidSchedulers.mainThread()) .subscribe { lifecycleEvent: LifecycleEvent -> when (lifecycleEvent.type!!) { LifecycleEvent.Type.OPENED -> Log.d(TAG, "Stomp connection opened") LifecycleEvent.Type.ERROR -> Log.e(TAG, "Error", lifecycleEvent.exception) LifecycleEvent.Type.FAILED_SERVER_HEARTBEAT, LifecycleEvent.Type.CLOSED -> { Log.
d(TAG, "Stomp connection closed") } } } compositeDisposable!!.add(lifecycleSubscribe) compositeDisposable!!.add(topicSubscribe) //открываем соединение if (!mStompClient!!.isConnected) { mStompClient!!.connect() } } else { Log.e(TAG, "mStompClient is null!") } }

На этом все, полный код работающего чата можно найти на GitHub. Надеюсь это будет полезно тем, кто сталкивается с настройкой WebSocket’ов впервые, как и я.

Как создать пользовательский интерфейс обмена сообщениями для приложения чата Android

Введение

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

Это руководство является попыткой восполнить этот пробел.

Мы все видели красочные пузыри чата, заполненные текстом, изображениями и даже играбельными медиафайлами — как они их создают? Ответ на удивление прост: RecyclerViews в сочетании с шаблоном ViewHolder.

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

В этом руководстве рассматривается создание:

  1. Пользовательского интерфейса обмена сообщениями
  2. Адаптера для RecyclerView
  3. Активности канала

Для этого руководства требуется:

  1. Android Studio 2 версии 9:0015 API Android 9:01.2 9:01.2
  2. Android Studio 9:01.2
  3. Основной SDK Sendbird: 3.0.148

Обратите внимание, что в этом руководстве предполагается базовое знакомство с разработкой для Android.

Шаг 1. Создание пользовательского интерфейса обмена сообщениями

Создание пользовательского интерфейса действия

В этом руководстве мы создадим специальное действие для размещения наших сообщений. Для этого действия нам понадобится XML. Итак, первое, что мы сделаем, это создадим файл activity_channel.xml.

Основным компонентом в этом упражнении является RecyclerView, который будет занимать большую часть экрана. Вы заметите, что существует также AppBarLayout с панелью инструментов. Мы не будем много делать с этим прямо сейчас, но, как правило, вы можете добавить кнопку «Назад», кнопку «О программе» или информацию о канале здесь. Последнее, что мы добавим, — это RelativeLayout, который будет содержать кнопки «EditText» и «Send». Соответственно, пользователи будут вводить текст и отправлять его. В этом RelativeLayout вы также можете добавить значки для поддержки добавления видео/изображений .

Создание элемента списка для каждого сообщения

Используйте отдельный файл XML для определения макета каждого элемента (т. е. сообщения) для RecyclerView. Обычно каждое сообщение содержит что-то вроде приведенного выше (т. е. имя отправителя, изображение его профиля и отметку времени). Поскольку выравнивание облачка чата обычно указывает на владельца сообщения, отображение изображения и имени профиля отправителя для каждого сообщения было бы излишним. Например, на изображении выше выровненный по правому краю пузырь чата указывает на то, что он принадлежит отправителю, поэтому нам не нужно включать изображение или имя.

Нам нужно создать два разных XML-файла. Первый .xml будет для сообщений с точки зрения «Я» или сообщений, отправленных текущим пользователем. Для этого мы решили иметь TextView для фактического сообщения, обернутого в Cardview. Вокруг этого TextView находятся другие TextView для таких вещей, как Date.

Второй .xml будет для сообщений с точки зрения «Другое» — это означает любое сообщение, которое текущий пользователь не отправляет. Этот пользовательский интерфейс будет похож на пользовательский интерфейс «Я». Однако он выровнен по левому краю и содержит информацию о «Другом» пользователе, такую ​​как ImageView для изображения профиля и TextField для имени пользователя. В остальном взгляды относительно схожи.

Шаг 2. Создание адаптера для recyclerview

Теперь, когда мы создали пользовательский интерфейс для чата, нам нужно связать сообщения с пользовательским интерфейсом. Мы сделаем это с помощью RecyclerView.Adapter.

Этот адаптер выполняет три функции. Он будет:

  • Сохранять список сообщений
  • Определять, отправлено или получено сообщение
  • Раздувать соответствующий макет в RecyclerView

Но прежде чем рисковать дальше, нам нужен список сообщений!

Разработка серверной части для обмена сообщениями в реальном времени выходит за рамки этого руководства. Поэтому мы продолжим работу с моделями в SDK чата Sendbird. Он примерно имеет следующую структуру:

Общее сообщение и пользовательские модели

 class Message {
  Строковое сообщение;
  Отправитель пользователя;
  давно создано;
}
класс Пользователь {
  Строковый никнейм;
  Строка profileUrl;
}
 

Так как реализация обмена сообщениями обычно разрабатывается таким образом, мы надеемся, что вы сможете следовать этому руководству с минимальными изменениями в вашем коде.

Теперь давайте создадим адаптер и назовем его MessageListAdapter. Это будет содержать список сообщений, которые будут отображаться в RecyclerView.

По умолчанию для адаптера требуется как минимум один Viewholder. Это макет, который можно раздувать и связывать объектами, которые он содержит. В нашем случае мы начнем только с двух: SendMessageHolder и ReceivedMessageHolder. По мере того, как вы добавляете больше типов сообщений, вы можете добавить больше держателей. В этом руководстве основное внимание уделяется пользовательским сообщениям или текстовым сообщениям.

Для этого у нас будет два закрытых внутренних класса внутри нашего MessageListAdapter.

Каждый ViewHolder содержит представления-члены, которые могут быть привязаны к определенной информации, содержащейся в сообщении. Например, TextView messageText привязывается к содержимому сообщения, а nameText привязывается к имени отправителя сообщения.

Антонио Лейва предлагает реализовать метод bind(object) в классе ViewHolder. Это обеспечивает привязку представления к классу ViewHolder, а не к onBindViewHolder. Таким образом, он создает более чистый код среди нескольких ViewHolder и ViewTypes. Это также позволяет нам легко добавлять OnClickListeners, если это необходимо.

После завершения ViewHolder вернитесь к адаптеру и переопределите необходимые методы, чтобы:

  1. Получить сообщение из MessageList
  2. Определить, является ли оно отправленным или полученным сообщением
  3. Раздуть соответствующий макет для ViewHolder
  4. Передать сообщение ViewHolder для привязки

Реализация этого процесса стандартна для большинства адаптеров и относительно не требует пояснений; поэтому мы покажем код для полного адаптера без дополнительных пояснений.

Мы только что закончили адаптер. Теперь мы можем отображать список как отправленных, так и полученных сообщений в пузырьках чата, которые мы определили ранее.

Шаг 3. Создание активности канала

Мы создали все компоненты, и теперь нам нужно инициализировать их внутри нашей активности. Создайте действие с именем MessageListActivity. В onCreate создайте RecyclerView и MessageListAdapter со списком сообщений, и вуаля! Вы только что создали свой собственный интерфейс обмена сообщениями.

Заключение

Вы можете создавать расширенные функции, такие как предварительный просмотр изображений, анимированные GIF-файлы в облачках чата и многое другое. Посмотрите примеры расширенного пользовательского интерфейса чата в примере приложения пользовательского интерфейса с открытым исходным кодом Sendbird! Это основано на использовании RecyclerViews и адаптеров, которые мы рассмотрели в этом руководстве, и поможет вам создать приложение чата производственного уровня с различными функциями.

Удачного создания чата!

Создание приложений для обмена сообщениями для Android Auto

Оставаться на связи с помощью сообщений важно для многих водителей. Чат-приложения могут позволить пользователям знать, нужно ли забрать ребенка или изменилось ли место ужина. Платформа Android позволяет приложениям для обмена сообщениями расширять свои возможности. услуг в опыт вождения с помощью стандартного пользовательского интерфейса, который позволяет водителям сохранять глаза на дороге.

Приложения, поддерживающие обмен сообщениями, могут расширить свои уведомления об обмене сообщениями, чтобы позволить Android Auto потреблять их, когда Auto работает. Эти уведомления отображаются в режиме «Авто» и позволяют пользователям читайте и отвечайте на сообщения в согласованном интерфейсе с низким уровнем отвлекающих факторов. И когда вы используете в MessagingStyle API, вы получаете оптимизированные уведомления о сообщениях для всех Android устройств, включая Android Auto. Оптимизация включает в себя пользовательский интерфейс, специализированный для уведомления о сообщениях, улучшенная анимация и поддержка встроенных изображений.

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

Важно: Новые и существующие приложения для обмена сообщениями нельзя установить напрямую как оптимизированное для драйверов приложение на Android Automotive OS. Они могут быть только распространяется через Android Auto. Для получения дополнительной информации см. Поддерживаемые категории приложений.

Начало работы

Чтобы предоставить службу обмена сообщениями для устройств Auto, ваше приложение должно объявить поддержку Android Auto в манифесте и иметь возможность делать следующее:

  • Создание и отправка NotificationCompat.MessagingStyle объекты, которые содержат ответ и пометить как прочитанное Объекты действия .
  • Обработка ответа и пометки разговора как прочитанного с помощью службы .

Концепции и объекты

Прежде чем приступить к разработке приложения, полезно понять, как Android Auto обрабатывает сообщения.

Отдельный фрагмент сообщения называется сообщением и представляется класс Стиль сообщения.Сообщение . Сообщение содержит отправителя, сообщение содержание и время отправки сообщения.

Связь между пользователями называется разговором и представлена Объект MessagingStyle . Разговор или MessagingStyle содержит заголовок, сообщения, и находится ли разговор среди группы пользователей.

Чтобы уведомлять пользователей об обновлениях беседы, таких как новое сообщение, публикация приложений Уведомление в систему Android. Это уведомление использует объект MessagingStyle для отображения конкретных сообщений. Пользовательский интерфейс в тени уведомлений. Платформа Android также передает это уведомление . в Android Auto, а MessagingStyle извлекается и используется для публикации уведомление через дисплей автомобиля.

Android Auto также требует, чтобы приложения добавляли объекты Action в уведомление в позволить пользователю быстро ответить на сообщение или пометить его как прочитанное прямо из оттенок уведомления.

Таким образом, один разговор представлен Уведомлением объект, стилизованный под объект MessagingStyle . Стиль сообщений содержит все сообщения в этом разговоре в одном или нескольких MessagingStyle.Message объектов. И, чтобы быть совместимым с Android Auto, приложение должен прикрепить ответ и пометить как прочитанное объекты Action к уведомлению .

Обмен сообщениями

В этом разделе описывается типичный обмен сообщениями между вашим приложением и Android Auto.

  1. Ваше приложение получает сообщение.
  2. Ваше приложение создает уведомление MessagingStyle с ответом и пометить как прочитанное Действие объектов.
  3. Android Auto получает событие «новое уведомление» от системы Android и находит MessagingStyle , ответ Действие и пометить как прочитанное Действие .
  4. Android Auto создает и отображает уведомление в автомобиле.
  5. Если пользователь коснется уведомления на дисплее автомобиля, Android Auto запускает пометку как прочитанное Действие .
    • В фоновом режиме ваше приложение должно обрабатывать это событие пометки как прочитанное.
  6. Если пользователь отвечает на уведомление голосом, Android Auto помещает транскрипцию ответа пользователя в ответ Действие , а затем запускает его.
    • В фоновом режиме ваше приложение должно обрабатывать это событие ответа.

Предварительные предположения

Эта страница не поможет вам создать приложение для обмена сообщениями целиком. следующий пример кода включает в себя некоторые вещи, которые нужны вашему приложению прежде чем вы начнете поддерживать обмен сообщениями с Android Auto:

 класс данных YourAppConversation(
        действительный идентификатор: Int,
        val title: Строка,
        val получатели: MutableList,
        значок val: растровое изображение) {
    сопутствующий объект {
        /** Выбирает [YourAppConversation] по его [id]. */
        fun getById(id: Int): YourAppConversation = // . ..
    }
    /** Ответы на этот диалог с заданным [сообщением]. */
    забавный ответ (сообщение: строка) {}
    /** Помечает этот разговор как прочитанный. */
    весело пометить как прочитано() {}
    /** Получает все непрочитанные сообщения из этой беседы. */
    fun getUnreadMessages(): List { return /* ... */ }
}
класс данных YourAppUser (идентификатор допустимого значения: Int, имя допустимого значения: строка, значок допустимого значения: Uri)
класс данных YourAppMessage(
    действительный идентификатор: Int,
    val отправитель: YourAppUser,
    тело val: Строка,
    val timeReceived: Long)
 

Заявить о поддержке Android Auto

Когда Android Auto получает уведомление от приложения для обмена сообщениями, оно проверяет, в приложении заявлена ​​поддержка Android Auto. Чтобы включить эту поддержку, включите следующую запись в манифесте вашего приложения:

 
    . ..
    <метаданные
        android:name="com.google.android.gms.car.application"
        android:resource="@xml/automotive_app_desc"/>
    ...

 

Эта запись манифеста ссылается на другой файл XML, который необходимо создать с помощью следующий путь: YourAppProject/app/src/main/res/xml/automotive_app_desc.xml . В файле Automobile_app_desc.xml укажите возможности Android Auto для вашего приложения. поддерживает. Например, чтобы объявить о поддержке уведомлений, включите следующее:

 
    <использует имя="уведомление" />

 

Если ваше приложение может быть установлено в качестве обработчика SMS по умолчанию, обязательно включите следующий элемент . Если вы этого не сделаете, по умолчанию обработчик, встроенный в Android Auto, будет использоваться для обработки входящих SMS/MMS-сообщений. когда ваше приложение установлено в качестве обработчика SMS по умолчанию, что может привести к дублированию уведомления.

 <автомобильное приложение>
    ...
    <использует имя="смс" />

 

Импорт базовой библиотеки AndroidX

Для создания уведомлений для использования с устройствами Auto требуется Основная библиотека AndroidX. Импортируйте библиотеку в свой проекта следующим образом:

  1. В файл build.gradle верхнего уровня включите зависимость от Google Maven репозиторий, как показано в следующем примере:

Groovy

все проекты {
    репозитории {
        Google()
    }
}
 

Котлин

все проекты {
    репозитории {
        Google()
    }
}
 
  1. В файл build. gradle вашего модуля приложения включите AndroidX Core зависимость библиотеки, как показано в следующем примере:

Groovy

зависимости {
    // Если ваше приложение написано на Java
    реализация 'androidx.core:core:1.9.0'
    // Если ваше приложение написано на Kotlin
    реализация «androidx.core: core-ktx: 1.9.0»
}
 

Котлин

зависимости {
    // Если ваше приложение написано на Java
    реализация ("androidx.core: ядро: 1.9.0")
    // Если ваше приложение написано на Kotlin
    реализация ("androidx.core: core-ktx: 1.9.0")
}
 

Обработка действий пользователя

Вашему приложению для обмена сообщениями нужен способ обработки обновления разговора через Действие . Для Android Auto существует два типа объектов Action вашего приложения. необходимо обрабатывать: ответить и отметить как прочитанное. Мы рекомендуем обрабатывать их с помощью IntentService , который обеспечивает гибкость для обработки потенциально дорогостоящих вызывает в фоновом режиме , освобождая основной поток вашего приложения.

Предупреждение: Не используйте действие или фрагмент для обработки действия . Они не только работают на переднем плане, но и, как известно, вызывают проблемы с пользовательским интерфейсом, которые может привести к тому, что ваше приложение будет заблокировано в Android Auto.

Определить действия намерения

Действия намерения — это простые строки, определяющие, что Намерение для. Поскольку одна служба может обрабатывать несколько типов намерений, проще определить несколько строк действий вместо определения нескольких Компоненты IntentService .

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

 частная константа VAL ACTION_REPLY = "com.example.REPLY"
частная константа val ACTION_MARK_AS_READ = "com.example.MARK_AS_READ"
 

Создать службу

Чтобы создать службу, которая обрабатывает эти объекты Action , вам нужен идентификатор разговора, которая представляет собой произвольную структуру данных, определенную вашим приложением, которое идентифицирует разговор. Вам также понадобится клавиша удаленного ввода, которая обсуждается в подробности далее в этом разделе. В следующем примере кода создается служба для обработки необходимых действий:

 private const val EXTRA_CONVERSATION_ID_KEY = "conversation_id"
закрытое константное значение REMOTE_INPUT_RESULT_KEY = "reply_input"
/**
 * Служба [IntentService], обрабатывающая действия ответа и пометки как прочитанного для
 * [Разговор о вашем приложении]. 
 */
класс MessagingService : IntentService("MessagingService") {
    переопределить удовольствие onHandleIntent (намерение: намерение?) {
        // Извлекает внутренние данные.
        val разговорId = намерение!!.getIntExtra(EXTRA_CONVERSATION_ID_KEY, -1)
        // Ищет в базе данных этот разговор.
        val разговор = YourAppConversation.getById (идентификатор разговора)
        // Обрабатывает действие, запрошенное в намерении. TODO
        // рассматриваются в следующем разделе.
        когда (намерение.действие) {
            ACTION_REPLY -> ЗАДАЧА()
            ACTION_MARK_AS_READ -> ЗАДАЧА()
        }
    }
}
 

Чтобы связать эту службу с вашим приложением, вам также необходимо зарегистрировать службу в манифесте вашего приложения, как показано в следующем примере:

 
    
    ...

 

Создание и обработка намерений

Другие приложения, включая Android Auto, не могут получить намерение который запускает MessagingService , потому что Intent передаются другим приложениям через Ожидание намерения . Из-за это ограничение, вам нужно создать RemoteInput объект, чтобы другие приложения могли предоставить текст ответа вашему приложению, как показано в следующем примере:

 /**
 * Создает [RemoteInput], который позволяет удаленным приложениям предоставлять строку ответа
 * к базовому [Intent] внутри [PendingIntent].
 */
весело createReplyRemoteInput (контекст: контекст): RemoteInput {
    // RemoteInput.Builder принимает единственный параметр: ключ для сохранения
    // ответ в.
    вернуть RemoteInput.Builder(REMOTE_INPUT_RESULT_KEY).build()
    // Обратите внимание, что RemoteInput ничего не знает о диалоге. Это
    // потому что данные для RemoteInput привязаны к намерению ответа с помощью
    // статические методы в классе RemoteInput.
}
/** Создает [Intent], который обрабатывает ответ на данный [appConversation]. */
весело создатьReplyIntent(
        контекст: Контекст, appConversation: YourAppConversation): Intent {
    // Создает намерение, поддерживаемое MessagingService. 
    val намерение = намерение (контекст, MessagingService::class.java)
    // Сообщаем MessagingService, что это ответный запрос.
    намерение.действие = ACTION_REPLY
    // Предоставляет идентификатор диалога, к которому относится ответ.
    намерение.putExtra (EXTRA_CONVERSATION_ID_KEY, appConversation.id)
    вернуть намерение
}
 

В предложении ACTION_REPLY switch в MessagingService , извлеките информацию, которая входит в ответ Intent , как показано на следующий пример:

 ACTION_REPLY -> {
    // Извлекает ответный ответ из намерения, используя тот же ключ, что и
    // RemoteInput использует.
    результаты val: Bundle = RemoteInput.getResultsFromIntent (намерение)
    val сообщение = results.getString(REMOTE_INPUT_RESULT_KEY)
    // Этот объект беседы поступает из службы обмена сообщениями.
    разговор.ответ(сообщение)
}
 

Вы обрабатываете пометку как прочитанную Intent аналогичным образом. Однако это не требуется RemoteInput , как показано в следующем примере:

 /** Создает [Intent], который обрабатывает пометку [appConversation] как прочитанной. */
весело создатьMarkAsReadIntent(
        контекст: Контекст, appConversation: YourAppConversation): Intent {
    val намерение = намерение (контекст, MessagingService::class.java)
    намерение.действие = ACTION_MARK_AS_READ
    намерение.putExtra (EXTRA_CONVERSATION_ID_KEY, appConversation.id)
    вернуть намерение
}
 

Предложение переключателя ACTION_MARK_AS_READ в службе обмена сообщениями не требует дополнительной логики, как показано в следующем примере:

 // Пометка как прочитанная не имеет другой логики.
ACTION_MARK_AS_READ -> беседа.markAsRead()
 

Уведомление пользователей о сообщениях

После завершения обработки диалога следующим шагом будет генерировать уведомления, совместимые с Android Auto.

Создание действий

Действие Объекты могут быть переданы другим приложениям с помощью Уведомление для триггерные методы в исходном приложении. Вот как Android Auto может отметить разговор как прочитанный или ответ на него.

Чтобы создать Действие , начните с Намерения . Следующий пример показывает как создать «ответ» Intent :

 весело createReplyAction(
        контекст: Контекст, appConversation: YourAppConversation): Действие {
    val responseIntent: Intent = createReplyIntent (контекст, разговор о приложении)
    // ...
 

Затем заверните эти Intent в PendingIntent , который подготавливает его к внешнему использование приложения. PendingIntent блокирует весь доступ к упакованному намерению с помощью раскрывая только выбранный набор методов, которые позволяют принимающему приложению запускать Intent или получить имя пакета исходного приложения. Внешнее приложение никогда не может получить доступ к базовому Intent или данным внутри него.

 // ...
    val responsePendingIntent = PendingIntent.getService(
        контекст,
        createReplyId(appConversation), // Метод поясняется позже.
        ответНамерение,
        PendingIntent.FLAG_UPDATE_CURRENT или PendingIntent.FLAG_MUTABLE)
    // ...
 

Прежде чем настраивать ответ Действие , имейте в виду, что Android Auto имеет три требования к ответу Действие :

  • Семантическое действие должно быть установлено на Action. SEMANTIC_ACTION_REPLY .
  • Действие должно указывать, что при запуске оно не будет отображать пользовательский интерфейс.
  • Действие должно содержать один RemoteInput .

Следующий пример кода настраивает ответ Действие , касающееся перечисленные выше требования:

 // ...
    val responseAction = Action.Builder (R.drawable.reply, «Ответить», replyPendingIntent)
        // Обеспечивает контекст того, что делает действие.
        .setSemanticAction(Action.SEMANTIC_ACTION_REPLY)
        // Действие не отображает пользовательский интерфейс, как того требует Android Auto.
        .setShowsUserInterface (ложь)
        // Не забудьте ответ RemoteInput. Android Auto будет использовать это, чтобы
        // сделать системный вызов, который добавит строку ответа в
        // намерение ответа, чтобы оно могло быть извлечено приложением для обмена сообщениями. 
        .addRemoteInput (создатьReplyRemoteInput (контекст))
        .строить()
    ответный ответДействие
}
 

Обработка действия пометки как прочитанного аналогична, за исключением того, что нет RemoteInput . Поэтому Android Auto предъявляет два требования к пометке как прочитанное Action :

  • Семантическое действие имеет значение Action.SEMANTIC_ACTION_MARK_AS_READ .
  • Действие указывает, что при запуске не будет отображаться пользовательский интерфейс.

В следующем примере кода устанавливается действие пометки как прочитанное , которое устраняет эти требования:

 весело createMarkAsReadAction(
        контекст: Контекст, appConversation: YourAppConversation): Действие {
    val markAsReadIntent = createMarkAsReadIntent (контекст, разговор о приложении)
    val markAsReadPendingIntent = PendingIntent. getService(
            контекст,
            createMarkAsReadId(appConversation), // Метод описан ниже.
            пометить как прочитанное намерение,
            PendingIntent.FLAG_UPDATE_CURRENT или PendingIntent.FLAG_IMMUTABLE)
    val markAsReadAction = Action.Builder(
            R.drawable.mark_as_read, "Пометить как прочитанное", markAsReadPendingIntent)
        .setSemanticAction (Действие.SEMANTIC_ACTION_MARK_AS_READ)
        .setShowsUserInterface (ложь)
        .строить()
    возврат markAsReadAction
}
 

При генерации ожидающих намерений используются два метода: createReplyId() и createMarkAsReadId() . Эти методы служат коды запроса для каждого PendingIntent , которые используются Android для управления существующие ожидающие намерения. Методы create() должны возвращать уникальные идентификаторы для каждого разговора, но повторяющиеся вызовы для одного и того же беседа должна возвращать уже сгенерированный уникальный идентификатор.

Рассмотрим пример с двумя диалогами, A и B: Идентификатор ответа диалога A равен 100, и его идентификатор пометки как прочитанный — 101. Идентификатор ответа диалога B — 102, а его идентификатор пометки как прочитанный — 103. Если беседа А обновлена, идентификаторы ответа и пометки как прочитанные по-прежнему 100 и 101. Дополнительные сведения см. PendingIntent.FLAG_UPDATE_CURRENT .

Создание MessagingStyle

MessagingStyle является носителем информации об обмене сообщениями и тем, что Android Авто используется для чтения вслух каждого сообщения в беседе.

Сначала необходимо указать пользователя устройства в виде Объект Person , как показано на следующий пример:

 fun createMessagingStyle(
        context: Context, appConversation: YourAppConversation): MessagingStyle {
    // Метод, определенный приложением для обмена сообщениями. 
    val appDeviceUser: YourAppUser = getAppDeviceUser()
    val devicePerson = Person.Builder()
        // Отображаемое имя (также имя, которое читается вслух в Android auto).
        .setName(appDeviceUser.name)
        // Значок, который будет отображаться в тени уведомлений в пользовательском интерфейсе системы (вне
        // Android Auto).
        .setIcon(appDeviceUser.icon)
        // Уникальный ключ на случай, если в этом разговоре несколько человек с
        // то же имя.
        .setKey(appDeviceUser.id)
        .строить()
    // ...
 

Затем вы можете создать объект MessagingStyle и указать некоторые детали. о разговоре.

 // ...
    valmessagingStyle = Стиль сообщений (лицо-устройства)
    // Устанавливает заголовок разговора. Если целевая версия приложения ниже
    // чем P, это автоматически пометит разговор как группу (чтобы
    // поддерживать обратную совместимость). Используйте `setGroupConversation` после
    // установка заголовка беседы для явного переопределения этого поведения.  Видеть
    // документация для получения дополнительной информации.
    messageStyle.setConversationTitle(appConversation.title)
    // Групповой разговор означает, что есть более 1 получателя, поэтому установите его соответствующим образом.
    messageStyle.setGroupConversation(appConversation.recipients.size > 1)
    // ...
 

Наконец, добавьте непрочитанные сообщения.

 // ...
    для (appMessage в appConversation.getUnreadMessages()) {
        // Отправитель также представлен с помощью объекта Person.
        val senderPerson = Person.Builder()
            .setName(appMessage.sender.name)
            .setIcon(appMessage.sender.icon)
            .setKey(appMessage.sender.id)
            .строить()
        // Добавляет сообщение. Более сложные сообщения, такие как изображения,
        // можно создать и добавить, создав экземпляр MessagingStyle.Message
        // класс напрямую. Подробности смотрите в документации.
        стиль сообщений.addMessage(
                appMessage. body, appMessage.timeReceived, senderPerson)
    }
    возврат сообщенияСтиль
}
 

Упаковать и отправить уведомление

После создания объектов Action и MessagingStyle можно создать и опубликовать уведомление .

 забавное уведомление (контекст: Context, appConversation: YourAppConversation) {
    // Создает действия и MessagingStyle.
    val responseAction = createReplyAction (контекст, разговор о приложении)
    val markAsReadAction = createMarkAsReadAction(context, appConversation)
    valmessagingStyle = createMessagingStyle(context, appConversation)
    // Создает уведомление.
    val уведомление = NotificationCompat.Builder(контекст, канал)
        // Обязательное поле для пользовательского интерфейса Android.
        .setSmallIcon (R.drawable.notification_icon)
        // Отображается в Android Auto как изображение разговора. 
        .setLargeIcon(appConversation.icon)
        // Добавляет стиль сообщений.
        .setStyle (стиль обмена сообщениями)
        // Добавляет ответное действие.
        .addAction (ответное действие)
        // Делает действие пометить как прочитанное невидимым, чтобы оно не отображалось
        // в пользовательском интерфейсе Android, но приложение удовлетворяет требованиям Android Auto
        // Требование действия пометить как прочитанное. Оба необходимых действия могут быть выполнены
        // видимый или невидимый; это стилистический выбор.
        .addInvisibleAction (отметить как действие чтения)
        .строить()
    // Публикует уведомление для просмотра пользователем.
    valnotificationManagerCompat = NotificationManagerCompat.from(контекст)
    уведомлениеManagerCompat.notify(appConversation.id, уведомление)
}
 

Дополнительные ресурсы

  • Google Design для вождения: приложения для обмена сообщениями
  • Обзор уведомлений

Сообщить о проблеме обмена сообщениями Android Auto

Если вы столкнетесь с проблемой при разработке приложения обмена сообщениями для Android Auto, вы можете сообщить об этом, используя Трекер проблем Google.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *