hi, i’m not true if i find the solution.
I check the source code, decompile the smack.jar(with spark 2.5.8). I find that:
org.jivesoftware.smack.PacketReader has a field: listerners
protected final Map<PacketListener, ListenerWrapper> listeners = new ConcurrentHashMap<PacketListener, ListenerWrapper>();
the listerners is used to notify all packetListener.
for example:
1,org.jivesoftware.spark.filetransfer.SparkTransferManager{
…
private void addPresenceListener() {
SparkManager.getConnection().addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
Presence presence = (Presence)packet;
if (presence.isAvailable()) {
…
}
…
2,org.jivesoftware.smack.Roster
…
PacketFilter rosterFilter = new PacketTypeFilter(RosterPacket.class);
connection.addPacketListener(new RosterPacketListener(), rosterFilter);
PacketFilter presenceFilter = new PacketTypeFilter(Presence.class);
presencePacketListener = new PresencePacketListener();
connection.addPacketListener(presencePacketListener, presenceFilter);
…
Because listerners use Map, not List, so it’s unordered. when spark starts up, 1 may been notified before 2. but next time, 2 may before 1.
if 1 before 2, the offline file transfer will get the message:The user is offline. Will auto-send “xxx” when user comes back online
So i change org.jivesoftware.smack.PacketReader,use a ordered Map (ConcurrentSkipListMap)
protected final Map<PacketListener, ListenerWrapper> listeners =
new java.util.concurrent.ConcurrentSkipListMap<PacketListener, ListenerWrapper>(new java.util.Comparator(){
public int compare(Object o1, Object o2){
return 1;
}
public boolean equals(Object obj) {
return super.equals(obj);
}
});
compile, then put into smack.jar
I test this , it seem ok.
hehe, i’m not sure if this is the solution. I just want this to be helpful.
PacketReader.java.zip (7882 Bytes)