Introduction
Unfortunately, even now, in the modern world, it is not always possible to take advantage of all the benefits
of push technology and sometimes you have to implement workarounds, for example, in the form of Long Poll, which allows you to emulate a push-notification mechanism. In particular, such a need arose in the implementation of the
client VKontakte for Sailfish OS .
This article will not discuss the principles of interaction with the Long Poll VKontakte server - it has very detailed
documentation , and the basic examples have already been published
earlier . Instead, practical implementation for a specific platform will be considered.
It is understood that the reader is familiar with the development under Sailfish OS not only in
QML , but also in
C ++ .
Long poll client
The main client class is the
LongPoll
class, which queries the Long Poll server and parses its responses.
The
getLongPollServer
method, whose task is to obtain information for opening a connection to the server, is called during application initialization, which allows you to immediately receive custom updates:
void LongPoll::getLongPollServer() { QUrl url("https://api.vk.com/method/messages.getLongPollServer");
In case of successful execution of the request, the connection information with the Long Poll server is saved and the connection is opened using the
doLongPollRequest
method:
void LongPoll::finished(QNetworkReply* reply) { QJsonDocument jDoc = QJsonDocument::fromJson(reply->readAll());
In the
doLongPollRequest
Long Poll method, the server passes the necessary connection parameters:
void LongPoll::doLongPollRequest() { QUrl url("https://" + _server);
It is worth noting that the value of the
mode
field, equal to 10, was obtained by adding the option of receiving attachments (2) and returning the extended set of events (8).
In response to opening a connection, the server returns JSON containing the latest events. The answer is processed in the method
finished
:
void LongPoll::finished(QNetworkReply* reply) { QJsonDocument jDoc = QJsonDocument::fromJson(reply->readAll());
The
failed
field in the response can take four values, but only one of them, equal to one, does not require re-requesting information to connect to the Long Poll server. For this reason, the condition was added to the code
jObj.value("failed").toInt() == 1
The
parseLongPollUpdates
method is a simple loop for all incoming events with a check of their type:
enum LONGPOLL_EVENTS { NEW_MESSAGE = 4,
From the code, it is clear that for each Long Poll event a
signal is sent by the client, which must be processed by another part of the application. The signal argument is not the entire event object, but only the necessary parts of it. For example, the
gotNewMessage
signal transmits only the identifier of a new message for which its full content is
requested :
void VkSDK::_gotNewMessage(int id) { _messages->getById(id); }
As a result of the execution of this one-line function
, a request is sent to the VKontakte server to obtain complete information about the message by its identifier with the further
creation of the object of this message. Finally, a signal is sent that is associated with the user interface, transmitting data about the new message, which is
displayed in the notification panel:
import QtQuick 2.0
Dialog Interface
Now, based on the principles of client interaction with the Long Poll server and the principles of transferring the received information to the user interface, we can consider an example of updating the open
dialog .
The first thing that catches your eye is the
Connections
component:
Connections {
The
onUserTyping
slot handles the dialing event of the message by displaying the corresponding notification to the user. Here, in the first step, a room identifier is received (a room is a generic term for conversations and chats), and in the second, a notification is displayed if the received identifier and the identifier of the current room match.
It is worth noting that the notification of a set of messages is displayed for ten seconds, if during this time a new event did not arrive, a newly activated notification. This is provided by the
Timer
component:
Label {
The
onSavedPhoto
slot
onSavedPhoto
responsible for handling the end of image loading in messages, which is beyond the scope of the current article.
The second thing that causes interest is the list of messages:
SilicaListView {
Here, the
MessageItem
component is responsible for displaying a single message. His consideration is beyond the scope of this article.
The messages themselves are taken from the model
vksdk.messagesModel
. This model is a list of
Message
objects that can be updated in real time using the
add
,
prepend
,
addProfile
,
readMessages
and
clear
methods:
void MessagesModel::clear() { beginRemoveRows(QModelIndex(), 0, _messages.size());
A common
dataChanged
all five methods is the use of the
dataChanged
signal, which indicates that the model has been updated. Emitting this signal updates the
SilicaListView
elements to display the current status of the messages. Adding messages to the
SilicaListView
accomplished by calling the
beginInsertRows
and
endInsertRows
that send the
rowsAboutToBeInserted
and
rowsInserted
respectively. As a result, the user will see in the dialogue new messages and their status in real time.
Conclusion
This article examined the interaction with the Long Poll server when developing for Sailfish OS using the example of the VKontakte application. Some features of the client implementation and how to update the user interface in real time were considered. The code for the application described in this article is
available on GitHub.