Создание пользовательского прослушивателя строфы с помощью XMPP, Smack для Android

Перейти к профилю Кенана Бегича

Кенан БегичЗаблокированоUnblockFollowFollowing

25 марта

XMPP, Смак, Android

В этом руководстве объясняется, как создать собственный прослушиватель строфы для нашего клиентского приложения чата для Android. Если вы не знакомы с XMPP и его терминологией, вам следует посетить вики-страница и получить некоторое представление о том, что такое XMPP. XMPP — это стандартизированный протокол для потоковой передачи XML. Когда клиент хочет начать сеанс с сервером XMPP, клиент открывает TCP-соединение, а затем устанавливает поток XML на сервер. После того, как клиент установил поток XML с сервером XMPP, клиент и сервер XMPP могут обмениваться специальными фрагментами XML через поток. Существует три основных фрагмента XML: <сообщение />, <присутствие /> а также . Вот пример одной из этих строф XML.

<сообщение от = «test@testdomain.com» к = «anothertest@testdomain.com»>

Это тест.

Эти фрагменты, также называемые строфами XML, являются основными единицами смысла в XMPP, и после согласования потока XML вы можете отправлять неограниченное количество строф по потоку. В этом руководстве объясняются основы создания одноэлементного класса Smack и способы создания настраиваемого поставщика строф для обмена пользовательскими форматами строф XML.

1. Создание класса модели для местоположения пользователя

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

public class UserLocation implements ExtensionElement{ //XML Tags public static final String NAMESPACE = "jabber:client"; public static final String ELEMENT_NAME = "location"; public static final String TAG_NAME_LATITUDE = "lat"; public static final String TAG_NAME_LONGITUDE = "lon"; public static final String TAG_NAME_NAME = "name"; public static final String TAG_NAME_ADDRESS = "addr";

//Fields private double latitude; private double longitude; private String name; private String address;

public UserLocation(Place place) { name = place.getName().toString(); address = place.getAddress().toString(); latitude = place.getLatLng().latitude; longitude = place.getLatLng().longitude; }

@Override public String getElementName() { return ELEMENT_NAME; }

@Override public String getNamespace() { return NAMESPACE; }

@SuppressLint("DefaultLocale") @Override public CharSequence toXML(String enclosingNamespace) { return String.format(" <location xmlns="jabber:client"> <type>%d</type> <lat>%f</lat> <lon>%f</lon> <name>%s</name> <addr>%s</addr> </location>", ChatMessageTableHelper.TYPE_OUTGOING_LOCATION, latitude, longitude, name, address); }}

Вот как мы можем попросить нашего пользователя поделиться местоположением или отправить указанное местоположение:

private void sendLocation() { // Construct an intent for the place picker try { PlacePicker.IntentBuilder intentBuilder = new PlacePicker.IntentBuilder(); Intent intent = intentBuilder.build(this); startActivityForResult(intent, REQUEST_PLACE_PICKER); } catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException e) { Log.e(LOG_TAG, e.toString(), e); }}

Позже в нашем onActivityResult метод, когда мы получаем результат, мы создаем наш Местоположение пользователя class и отправьте его в наш синглтон Smack, который мы создадим в следующей главе.

protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK) { switch (requestCode) { case REQUEST_PLACE_PICKER: // The user has selected a place. // Extract the name and address. Place place = PlacePicker.getPlace(this, data); UserLocation location = new UserLocation(place);
              //Send Custom stanza to our Smack singleton class
              SmackSingelton.getInstance(context)
              .sendChatMessage("buddy@domain.com", "Location msg",
                               location)
              break; } }}

Теперь давайте немного подробнее объясним класс UserLocation. Как мы видим наш Местоположение пользователя расширение класса РасширениеЭлемент интерфейс. Поскольку это говорит само за себя, это означает, что этот класс будет расширением нашей стандартной строфы сообщений XML, которая будет содержать пользовательский XML и будет анализироваться с помощью специального поставщика, который мы создадим позже. Это означает, что наше сообщение будет содержать пользовательский дочерний элемент, в нашем примере это местоположение пользователя с его собственными дочерними элементами, которые представляют основы местоположения. Дополнительные пояснения к элементам расширения можно найти здесь

Далее мы видим, что мы должны реализовать три метода этого интерфейса. Эти методы: getElementName(), getNamespace(), toXML(). Как видим первый способ получитьимяэлемента(), возвращает наше статическое поле ЭЛЕМЕНТ_ИМЯ который представляет имя нашего корневого элемента нашего расширения. Второй способ получитьимяпространство()возвращает наше статическое поле ПРОСТРАНСТВО ИМЕН что представляет пространство имен корневого элемента XML. И, наконец, третий способ вXML(), возвращает наше расширение строфы в XML-представлении.

2. Создайте провайдера местоположения пользователя

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

public class LocationMessageProvider extends ExtensionElementProvider { @Override public Element parse(XmlPullParser parser, int initialDepth) throws Exception { UserLocation location = new UserLocation(); boolean done = false; String tag = null; while (!done) { int eventType = parser.next(); switch (eventType) { case XmlPullParser.START_TAG: tag = parser.getName(); break; case XmlPullParser.TEXT: if (UserLocation.TAG_NAME_LATITUDE.equals(tag)) { try { location.setLatitude( Double.parseDouble(parser.getText())); } catch (NumberFormatException ignored) {} } else if (UserLocation.TAG_NAME_LONGITUDE.equals(tag)) { try { location.setLongitude( Double.parseDouble(parser.getText())); } catch (NumberFormatException ignored) {} } else if (UserLocation.TAG_NAME_NAME.equals(tag)) { location.setName(parser.getText()); } else if(UserLocation.TAG_NAME_ADDRESS.equals(tag)) { location.setAddress(parser.getText()); } break; case XmlPullParser.END_TAG: // Stop parsing when we hit </addr> done = UserLocation.TAG_NAME_ADDRESS.equals( parser.getName()); break; } } return location; }}

Как мы видим, наш LocationMessageProvider продлевать ExtensionElementProvider абстрактный класс, и он должен реализовать разобрать() метод, который будет анализировать нашу пользовательскую строфу, если наша строфа сообщения содержит ExtensionElements. Таким образом мы десериализуем необработанный XML в наш Местоположение пользователя учебный класс. Далее нам нужно зарегистрировать нашего провайдера, чтобы он мог анализировать нашу пользовательскую строфу, которую мы отправим. Для этого мы создадим наш одноэлементный класс Smack.

3. Создание одноэлементного класса Smack

Класс Smack singleton инкапсулирует все функции, необходимые нашему клиенту для установления соединения XMPP с сервером. Это означает, что пользователь должен быть зарегистрирован и авторизован. Мы не будем рассматривать эти функции, поскольку они не являются предметом этой статьи. Наш упрощенный одноэлементный класс Smack будет выглядеть так.

public class SmackSingleton { private static final String LOG_TAG = "SmackSingleton"; private MessagePacketListener messagePacketListener; private static SmackSingleton instance; private XMPPTCPConnection con;

private SmackSingleton(Context context) { this.context = context; messagePacketListener = new MessagePacketListener(context); ProviderManager.addExtensionProvider( UserLocation.ELEMENT_NAME, UserLocation.NAMESPACE, new LocationMessageProvider() ); }

public static synchronized SmackSingleton getInstance( Context context) { if (instance == null) { instance = new SmackSingleton( context.getApplicationContext()); } return instance; }

//....Login and connection functionalities..// public void sendChatMessage(String to, String body, ExtensionElement extension) throws SmackInvocationException { try { jid = JidCreate.entityBareFrom(to); Message msg = new Message(); //For our message body can be empty msg.setBody(body); //Add our extension to message that will be sent to user msg.addExtension(extension); //Add delivery request if needed to msg //which is again another extension to //message stanza as our location extension as it extend //ExtensionElement interface DeliveryReceiptRequest.addTo(msg); //Send chat message ChatManager.getInstanceFor(connection) .chatWith(jid).send(msg); } catch (NotConnectedException e) { throw new SmackInvocationException(e); } catch (InterruptedException | XmppStringprepException | SmackException.NoResponseException e) { e.printStackTrace(); } }}

Если мы посмотрим на наш класс, у нас есть три важные вещи. Во-первых, когда мы создаем наш одноэлементный класс, мы добавляем наш LocationMessageProvider к ProviderManager. Это означает, что мы регистрируем нашего настраиваемого провайдера у провайдера, который будет отвечать за синтаксический анализ пользовательских разделов XML. Во-вторых, это MessagePacketListener. Это расширение слушателя StanzaListener интерфейс, который прослушивает пакеты, отправленные нашему клиенту. В нашем случае мы слушаем только определенный пакет, который необходимо обработать. Эта концепция также известна как программирование в стиле событий. Наконец, в-третьих, мы должны отправить наше сообщение. За это отвечает наш sendChatMessage (строка для, тело строки, расширение ExtensionElement) метод. Этот метод отправляет сообщение нашему приятелю с телом, которое представляет собой текст, который получит пользователь, и пользовательское расширение. Это расширение будет UserLocation.

4. Создание MessagePacketListener

Когда мы отправляем сообщение нашему приятелю, должен быть способ получить это сообщение. Мы упоминали в предыдущей главе, что MessagePacketListener отвечает за такие функции. Итак, это наш класс слушателя, который мы регистрируем в нашем SmackSingleton учебный класс.

public class MessagePacketListener implements StanzaListener{ private Context context;

MessagePacketListener(Context context) { this.context = context; }

private void processPacketExtension(Intent intent, Message msg) { Collection<ExtensionElement> extensions = msg.getExtensions(); if (extensions != null) { Iterator<ExtensionElement> iterator = extensions.iterator(); if (iterator.hasNext()) { ExtensionElement extension = iterator.next(); if (extension instanceof UserLocation) { //...We have received UserLcoation...// UserLocation loc = (UserLocation)extension; } if(extension instanceof DeliveryReceipt){ //...Our buddy has set request for...// //...DeliveryReceipt extension...// //...so we will send DeliveryReceipt...// //...extension to our buddy...// DeliveryReceipt delivery = (DeliveryReceipt) extension; } } } }

@Override public void processStanza(Stanza packet) { Message msg = (Message)packet; processPacketExtension(intent, msg); //...Do the sth with message...// }}

Наш прослушиватель строфы должен расширять метод интерфейса процессСтанса. Этот метод обрабатывает наше сообщение, которое было отправлено нашим другом. Дополнительно мы называем ProcessPacketExtension метод, который обрабатывает наше сообщение и перебирает все расширения, которые у него есть. Если мы находим какие-либо важные для нас расширения, такие как наше местоположение пользователя или уведомление о доставке, мы десериализуем необработанный XML в класс, который нам нужен, чтобы его можно было использовать в нашем приложении.

Вот оно, наше пользовательское расширение, полученное нашим приятелем.

Виола.

5. Ссылки

xmpp.org

Расширяемый протокол обмена сообщениями и присутствия (XMPP): ядро

Смак документы

6. Контакт

Свяжитесь со мной по адресу:

begic_kenan@hotmail.com

info@redundantcoding.com

LinkedIn

Похожие записи

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

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