Below are the partial source extracted from aTalk project i.e.:
atalk-android
You may refer to the project starting with ChatPanel#mamQuery() method to see how to request for the relevant mam for a specific chatroom/contact/user.
In short you must defined the MamQueryArgs, then use it to request the MAM from the server.
MamManager.MamQueryArgs mamQueryArgs = MamManager.MamQueryArgs.builder()
.limitResultsToJid(jid)
.limitResultsSince(mamDate)
.setResultPageSizeTo(MAM_PAGE_SIZE)
.build();
MamManager.MamQuery query = mamManager.queryArchive(mamQueryArgs);
/**
* Fetch the server mam message and merged into the history database if new;
* This method is accessed only after the user has registered with the network,
*
* @param descriptor can either be metaContact or chatRoomWrapper=>ChatRoom, from whom the mam are to be loaded
*/
private boolean mamQuery(Object descriptor) {
if (!getProtocolProvider().isRegistered()) {
aTalkApp.showToastMessage(R.string.service_gui_HISTORY_WARNING);
return false;
}
MamManager mamManager;
XMPPConnection connection = getProtocolProvider().getConnection();
Jid jid;
if (descriptor instanceof ChatRoom) {
jid = ((ChatRoom) descriptor).getIdentifier();
mamManager = MamManager.getInstanceFor(((ChatRoom) descriptor).getMultiUserChat());
}
else {
jid = ((MetaContact) descriptor).getDefaultContact().getJid().asBareJid();
mamManager = MamManager.getInstanceFor(connection, null);
}
// Retrieve the mamData from the last message sent/received in this chatSession
MessageHistoryServiceImpl mMHS = MessageHistoryActivator.getMessageHistoryService();
Date mamDate = mMHS.getLastMessageDateForSessionUuid(mChatId);
try {
if (mamManager.isSupported()) {
// Prevent omemoManager from automatically decrypting MAM messages.
OmemoManager omemoManager = OmemoManager.getInstanceFor(connection);
omemoManager.stopStanzaAndPEPListeners();
// Must always use a valid mamDate in memQuery
mamDate = mMHS.getMamDate(mChatId);
if (mamDate == null) {
Calendar c = Calendar.getInstance(TimeZone.getDefault());
c.set(Calendar.DAY_OF_MONTH, -30);
mamDate = c.getTime();
}
MamManager.MamQueryArgs mamQueryArgs = MamManager.MamQueryArgs.builder()
.limitResultsToJid(jid)
.limitResultsSince(mamDate)
.setResultPageSizeTo(MAM_PAGE_SIZE)
.build();
MamManager.MamQuery query = mamManager.queryArchive(mamQueryArgs);
List<Forwarded<Message>> forwardedList = query.getPage().getForwarded();
if (!forwardedList.isEmpty()) {
mMHS.saveMamIfNotExit(omemoManager, this, forwardedList);
}
omemoManager.resumeStanzaAndPEPListeners();
} else {
mMHS.setMamDate(mChatId, mamDate);
}
} catch (SmackException.NoResponseException | XMPPException.XMPPErrorException // | IOException
| SmackException.NotConnectedException | InterruptedException | SmackException.NotLoggedInException e) {
Timber.e("MAM query: %s", e.getMessage());
}
return true;
}
/**
* Update the last mam retrieval message timeStamp for the specified sessionUuid.
* Always advance timeStamp by 10ms to avoid last message being included in future mam fetching.
*
* @param sessionUuid the chat sessions record id to which to save the timestamp
* @param date last mam message timestamp
*/
public void setMamDate(String sessionUuid, Date date) {
contentValues.clear();
contentValues.put(ChatSession.MAM_DATE, Long.toString(date.getTime() + 10));
String[] args = {sessionUuid};
mDB.update(ChatSession.TABLE_NAME, contentValues, ChatSession.SESSION_UUID + "=?", args);
}
public void saveMamIfNotExit(OmemoManager omemoManager, ChatPanel chatPanel,
List<Forwarded<Message>> forwardedList) {
EntityFullJid userJid = chatPanel.getProtocolProvider().getConnection().getUser();
String chatId = chatPanel.getChatSession().getChatId();
Date timeStamp = new Date();
for (Forwarded<Message> forwarded : forwardedList) {
Message msg = forwarded.getForwardedStanza();
// Skip all messages that are being sent by own self
Jid sender = msg.getFrom();
// Timber.d("userJid = %s; sender = %s", userJid, sender);
if (userJid.equals(sender)) {
continue;
}
// Some received/DomainBareJid message does not have msgId. So use stanzaId from StanzaIdElement if found.
String msgId = msg.getStanzaId();
if (TextUtils.isEmpty(msgId)) {
ExtensionElement stanzaIdElement = msg.getExtension(StanzaIdElement.QNAME);
if (stanzaIdElement instanceof StanzaIdElement) {
msgId = ((StanzaIdElement) stanzaIdElement).getId();
}
}
if (TextUtils.isEmpty(msgId)) {
continue;
}
timeStamp = forwarded.getDelayInformation().getStamp();
String[] args = {msgId, chatId};
Cursor cursor = mDB.query(ChatMessage.TABLE_NAME, null, ChatMessage.UUID
+ "=? AND " + ChatMessage.SESSION_UUID + "=?", args, null, null, null);
int msgCount = cursor.getCount();
cursor.close();
if (msgCount == 0) {
IMessage iMessage = null;
if (msg.hasExtension(OmemoElement.NAME_ENCRYPTED, OmemoConstants.OMEMO_NAMESPACE_V_AXOLOTL)) {
OmemoElement omemoElement =
(OmemoElement) msg.getExtensionElement(OmemoElement.NAME_ENCRYPTED, OmemoConstants.OMEMO_NAMESPACE_V_AXOLOTL);
try {
OmemoMessage.Received oReceive = omemoManager.decrypt(sender.asBareJid(), omemoElement);
iMessage = new MessageJabberImpl(oReceive.getBody(), iMessage.ENCRYPTION_OMEMO, null, msgId);
} catch (SmackException.NotLoggedInException | CorruptedOmemoKeyException | NoRawSessionException
| CryptoFailedException | IOException e) {
Timber.e("Omemo decrypt message (%s): %s", msgId, e.getMessage());
}
}
else {
iMessage = new MessageJabberImpl(msg.getBody(), iMessage.ENCRYPTION_NONE, null, msgId);
}
if (iMessage != null) {
String direction = userJid.asBareJid().isParentOf(sender) ? ChatMessage.DIR_OUT : ChatMessage.DIR_IN;
int msgType = (Message.Type.groupchat == msg.getType()) ? ChatMessage.MESSAGE_ACTION : ChatMessage.MESSAGE_IN;
if (isHistoryLoggingEnabled()) {
writeMessage(chatId, direction, sender, iMessage, timeStamp, msgType);
}
else {
String fromJid = sender.toString();
chatPanel.cacheNextMsg(new ChatMessageImpl(fromJid, fromJid, timeStamp,
msgType, iMessage, null, direction));
}
// Timber.d("Message body# %s: (%s) %s => %s", sender, msgId, timeStamp, iMessage.getContent());
}
}
}
// Save the last mam retrieval timeStamp
setMamDate(chatId, timeStamp);
}