Guida a XMPP Smack Client

1. Introduzione

XMPP è un protocollo di messaggistica istantanea ricco e complesso.

Invece di scrivere il nostro client da zero, in questo tutorial daremo un'occhiata a Smack, un client XMPP open source modulare e portatile scritto in Java che ha svolto gran parte del lavoro pesante per noi.

2. Dipendenze

Smack è organizzato in diversi moduli per fornire maggiore flessibilità , quindi possiamo facilmente includere le funzionalità di cui abbiamo bisogno.

Alcuni di questi includono:

  • Modulo XMPP su TCP
  • Un modulo per supportare molte delle estensioni definite dalla XMPP Standards Foundation
  • Supporto per estensioni legacy
  • Un modulo per eseguire il debug

Possiamo trovare tutti i moduli supportati nella documentazione di XMPP.

Tuttavia, in questo tutorial, utilizzeremo solo i moduli tcp , im , extensions e java7 :

 org.igniterealtime.smack smack-tcp   org.igniterealtime.smack smack-im   org.igniterealtime.smack smack-extensions   org.igniterealtime.smack smack-java7 

Le versioni più recenti possono essere trovate su Maven Central.

3. Configurazione

Per testare il client, avremo bisogno di un server XMPP. Per farlo, creeremo un account su jabber.hot-chilli.net, un servizio Jabber / XMPP gratuito per tutti.

Successivamente, possiamo configurare Smack utilizzando la classe XMPPTCPConnectionConfiguration che fornisce un builder per impostare i parametri della connessione:

XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() .setUsernameAndPassword("baeldung","baeldung") .setXmppDomain("jabb3r.org") .setHost("jabb3r.org") .build();

Il builder ci permette di impostare le informazioni di base necessarie per eseguire una connessione . Se necessario, possiamo anche impostare altri parametri come porta, protocolli SSL e timeout.

4. Connessione

La creazione di una connessione si ottiene semplicemente utilizzando la classe XMPPTCPConnection :

AbstractXMPPConnection connection = new XMPPTCPConnection(config); connection.connect(); //Establishes a connection to the server connection.login(); //Logs in 

La classe contiene un costruttore che accetta la configurazione precedentemente costruita. Fornisce inoltre metodi per connettersi al server e accedere.

Una volta stabilita una connessione, possiamo utilizzare le funzionalità di Smack , come la chat , che descriveremo nella sezione successiva.

Nel caso in cui la connessione fosse improvvisamente interrotta, per impostazione predefinita, Smack proverà a riconnettersi.

Il ReconnectionManager tenterà di ricollegare immediatamente al server e aumentare il ritardo tra i tentativi come reconnections successive non consentiti.

5. Chat

Una delle caratteristiche principali della libreria è il supporto tramite chat.

L'utilizzo della classe Chat rende possibile creare un nuovo thread di messaggi tra due utenti:

ChatManager chatManager = ChatManager.getInstanceFor(connection); EntityBareJid jid = JidCreate.entityBareFrom("[email protected]"); Chat chat = chatManager.chatWith(jid);

Nota che, per costruire una chat abbiamo utilizzato un ChatManager e, ovviamente, abbiamo specificato con chi chattare. Abbiamo ottenuto quest'ultimo utilizzando l' oggetto EntityBareJid , cheracchiude un indirizzo XMPP —aka un JID— composto da una parte locale ( baeldung2 ) e una parte di dominio ( jabb3r.org ).

Dopodiché, possiamo inviare un messaggio utilizzando il metodo send () :

chat.send("Hello!");

E ricevi messaggi impostando un ascoltatore:

chatManager.addIncomingListener(new IncomingChatMessageListener() { @Override public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) { System.out.println("New message from " + from + ": " + message.getBody()); } });

5.1. Camere

Oltre alla chat utente end-to-end, Smack fornisce supporto per le chat di gruppo attraverso l'uso delle stanze .

Esistono due tipi di stanze, stanze istantanee e stanze riservate.

Le stanze istantanee sono disponibili per l'accesso immediato e vengono create automaticamente in base a una configurazione predefinita. D'altra parte, le stanze riservate vengono configurate manualmente dal proprietario della stanza prima che chiunque possa entrare.

Diamo un'occhiata a come creare una stanza istantanea utilizzando MultiUserChatManager :

MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection); MultiUserChat muc = manager.getMultiUserChat(jid); Resourcepart room = Resourcepart.from("baeldung_room"); muc.create(room).makeInstant();

In modo simile possiamo creare una stanza riservata:

Set owners = JidUtil.jidSetFrom( new String[] { "[email protected]", "[email protected]" }); muc.create(room) .getConfigFormManger() .setRoomOwners(owners) .submitConfigurationForm();

6. Roster

Un'altra funzionalità fornita da Smack è la possibilità di monitorare la presenza di altri utenti.

Con Roster.getInstanceFor (), possiamo ottenere un'istanza di Roster :

Roster roster = Roster.getInstanceFor(connection);

Il Roster è un elenco di contatti che rappresenta gli utenti come oggetti RosterEntry e ci consente di organizzare gli utenti in gruppi.

Possiamo stampare tutte le voci nel Roster usando il metodo getEntries () :

Collection entries = roster.getEntries(); for (RosterEntry entry : entries) { System.out.println(entry); }

Inoltre, ci consente di ascoltare i cambiamenti nelle sue voci e nei dati di presenza con un RosterListener:

roster.addRosterListener(new RosterListener() { public void entriesAdded(Collection addresses) { // handle new entries } public void entriesDeleted(Collection addresses) { // handle deleted entries } public void entriesUpdated(Collection addresses) { // handle updated entries } public void presenceChanged(Presence presence) { // handle presence change } });

Fornisce inoltre un modo per proteggere la privacy dell'utente assicurandosi che solo gli utenti approvati possano iscriversi a un elenco. Per fare ciò, Smack implementa un modello basato sulle autorizzazioni.

Esistono tre modi per gestire le richieste di sottoscrizione di presenza con il metodo Roster.setSubscriptionMode () :

  • Roster.SubscriptionMode.accept_all : accetta tutte le richieste di sottoscrizione
  • Roster.SubscriptionMode.reject_all: rifiuta tutte le richieste di sottoscrizione
  • Roster.SubscriptionMode.manual - Elabora manualmente le richieste di sottoscrizione di presenza

Se scegliamo di gestire manualmente le richieste di sottoscrizione, dovremo registrare una StanzaListener (descritta nella sezione successiva) e gestire i pacchetti con il tipo Presence.Type.subscribe .

7. Stanza

Oltre alla chat, Smack fornisce una struttura flessibile per inviare una stanza e ascoltare quella in arrivo.

Per chiarire, una strofa è un'unità semantica discreta di significato in XMPP. Si tratta di informazioni strutturate che vengono inviate da un'entità a un'altra su un flusso XML.

Possiamo trasmettere una Stanza tramite una connessione utilizzando il metodo send () :

Stanza presence = new Presence(Presence.Type.subscribe); connection.sendStanza(presence);

In the example above, we sent a Presence stanza to subscribe to a roster.

On the other hand, to process the incoming stanzas, the library provides two constructs:

  • StanzaCollector
  • StanzaListener

In particular, StanzaCollector let us wait synchronously for new stanzas:

StanzaCollector collector = connection.createStanzaCollector(StanzaTypeFilter.MESSAGE); Stanza stanza = collector.nextResult();

While StanzaListener is an interface for asynchronously notifying us of incoming stanzas:

connection.addAsyncStanzaListener(new StanzaListener() { public void processStanza(Stanza stanza) throws SmackException.NotConnectedException,InterruptedException, SmackException.NotLoggedInException { // handle stanza } }, StanzaTypeFilter.MESSAGE);

7.1. Filters

Moreover, the library provides a built-in set of filters to process incoming stanzas.

We can filter stanza by type using StanzaTypeFilter or by ID with StanzaIdFilter:

StanzaFilter messageFilter = StanzaTypeFilter.MESSAGE; StanzaFilter idFilter = new StanzaIdFilter("123456");

Or, discerning by particular address:

StanzaFilter fromFilter = FromMatchesFilter.create(JidCreate.from("[email protected]")); StanzaFilter toFilter = ToMatchesFilter.create(JidCreate.from("[email protected]"));

E possiamo usare l'operatore di filtro logico ( AndFilter , OrFilter , NotFilter ) per creare filtri complessi:

StanzaFilter filter = new AndFilter(StanzaTypeFilter.Message, FromMatchesFilter.create("[email protected]"));

8. Conclusione

In questo articolo, abbiamo coperto le classi più utili fornite da Smack.

Abbiamo imparato a configurare la libreria per inviare e ricevere la stanza XMPP.

Successivamente, abbiamo imparato a gestire le chat di gruppo utilizzando le funzionalità ChatManager e Roster .

Come al solito, tutti gli esempi di codice mostrati in questo tutorial sono disponibili su GitHub.