这对我来说很奇怪:在我的项目中(顺便说一句,它是从Yaxim派生的,所以它是一个android聊天应用程序),我试图通过messageeventlistener实现写通知。我确实收到了通知事件。为了让它出现在listview(在另一个类中)中,我在数据库中添加了一行,就好像它是一条消息一样(只有文本是"…")。我添加了一个计数器,该行被正确地插入到数据库中(随后,当实际消息到来时,该行会从数据库中删除)。notifychanges也被正确调用。奇怪的是,尽管如此,该行并没有出现在列表视图中。如果我把这个过程移到下面几行,在常规消息的packetlistener上,它就会被插入。然而,我不能这样做,因为packetlistener并没有正确地接收到所有组成通知,所以它并不能一直用于此目的。此外,当写入通知正确插入数据库时,如果我将过程保留在messageEventNotificationListener()中,则当实际消息到达时,写入通知消息不会被删除(并且iCount不断增加);如果我把过程放在packetListener中,它会这样做(因此,在消息被推送到数据库后,iCount等于0)
这是messageeventlistener:
private void messageEventNotificationListener(){
// Create a MessageEventManager
if (mMessageEventManager == null)
mMessageEventManager = new MessageEventManager(mXMPPConnection);
// Add the listener that will react to the event notifications
mMessageEventManager.addMessageEventNotificationListener(new MessageEventNotificationListener() {
public void deliveredNotification(String from, String packetID) {
Log.d(TAG, "The message has been delivered (" + from + ", " + packetID + ")");
}
public void displayedNotification(String from, String packetID) {
Log.d(TAG, "The message has been displayed (" + from + ", " + packetID + ")");
}
public void composingNotification(String from, String packetID) {
Log.d(TAG, "The message's receiver is composing a reply (" + from + ", " + packetID + ")");
//controlla se l'utente non sta già scrivendo
String selection = ChatConstants.JID + " = '" + from + "' AND " +
ChatConstants.DELIVERY_STATUS + " = " + ChatConstants.DS_WRITING;
Cursor cursor = mContentResolver.query(ChatProvider.CONTENT_URI,
new String[] { "count(" + ChatConstants._ID + ")" },
selection, null, null);
cursor.moveToFirst();
int iCount = cursor.getInt(0);
//if (iCount == 0)
//{
addChatMessageToDB(ChatConstants.INCOMING, from, "...", ChatConstants.DS_WRITING, System.currentTimeMillis(), packetID);
//}
}
public void offlineNotification(String from, String packetID) {
Log.d(TAG, "The message's receiver is offline (" + from + ", " + packetID + ")");
}
public void cancelledNotification(String from, String packetID) {
Log.d(TAG, "The message's receiver cancelled composing a reply (" + from + ", " + packetID + ")");
}
});
}
这是数据包记录器:
private void registerMessageListener() {
// do not register multiple packet listeners
if (mPacketListener != null)
mXMPPConnection.removePacketListener(mPacketListener);
PacketTypeFilter filter = new PacketTypeFilter(Message.class);
mPacketListener = new PacketListener() {
public void processPacket(Packet packet) {
try {
if (packet instanceof Message) {
Message msg = (Message) packet;
String chatMessage = msg.getBody();
DeliveryReceipt dr = (DeliveryReceipt)msg.getExtension("received", DeliveryReceipt.NAMESPACE);
if (dr != null) {
Log.d(TAG, "got delivery receipt for " + dr.getId());
changeMessageDeliveryStatus(dr.getId(), ChatConstants.DS_DELIVERED);
}
if (chatMessage == null)
return;
if (msg.getType() == Message.Type.error) {
chatMessage = "<Error> " + chatMessage;
}
long ts;
DelayInfo timestamp = (DelayInfo)msg.getExtension("delay", "urn:xmpp:delay");
if (timestamp == null)
timestamp = (DelayInfo)msg.getExtension("x", "jabber:x:delay");
if (timestamp != null)
ts = timestamp.getStamp().getTime();
else
ts = System.currentTimeMillis();
String fromJID = getJabberID(msg.getFrom());
//elimina il messaggio "writing" se esiste
deleteWritingChatMessageFromDB(fromJID);
if (msg.getExtension("request", DeliveryReceipt.NAMESPACE) != null) {
// got XEP-0184 request, send receipt
sendReceipt(msg.getFrom(), msg.getPacketID());
}
addChatMessageToDB(ChatConstants.INCOMING, fromJID, chatMessage, ChatConstants.DS_NEW, ts, msg.getPacketID());
mServiceCallBack.newMessage(fromJID, chatMessage);
}
}
} catch (Exception e) {
// SMACK silently discards exceptions dropped from processPacket :(
Log.e(TAG, "failed to process packet:");
e.printStackTrace();
}
};
mXMPPConnection.addPacketListener(mPacketListener, filter);
}
最后是插入和删除方法
private void addChatMessageToDB(int direction, String JID,
String message, int delivery_status, long ts, String packetID) {
ContentValues values = new ContentValues();
values.put(ChatConstants.DIRECTION, direction);
values.put(ChatConstants.JID, JID);
values.put(ChatConstants.MESSAGE, message);
values.put(ChatConstants.DELIVERY_STATUS, delivery_status);
values.put(ChatConstants.DATE, ts);
values.put(ChatConstants.PACKET_ID, packetID);
Uri noteUri = mContentResolver.insert(ChatProvider.CONTENT_URI, values);
//mContentResolver.notifyChange(noteUri, null);
}
private void deleteWritingChatMessageFromDB(String JID) {
int count = mContentResolver.delete(ChatProvider.CONTENT_URI,
ChatConstants.JID + " = ? AND " + ChatConstants.MESSAGE + " = ? AND " + ChatConstants.DELIVERY_STATUS + " = ?", new String[] { JID, "...", "3" });
debugLog("deleteWritingChatMessageEntryFromDB: Deleted " + count + " entries");
}
这两个方法都被调用到ChatProvider类中,并以getContext().getContentResolver().notifyChange(url,null);
发现问题不同:我发布这篇文章只是为了防止其他人遇到同样的问题。消息实际上是插入到数据库中的,但虽然packetlistener只返回jid,但messageeventlistener也返回jid和末尾的资源,这些资源需要在插入之前删除。完成后,消息出现在列表中。此外:我发布的代码不完全正确,无法处理messageEvent。需要直接从packetListener内部调用侦听器。