我在android项目中使用asmack最新版本(asmack-android-8-source-0.8.3),我试图通过发送多个IQ并接收响应来与服务器通信。 我收到响应并且它被正确解析但是包侦听器没有触发。 我有以下代码:
vCard_IQProvider.java
public class vCard_IQProvider implements IQProvider
{
public static final String NAMESPACE = "vcard-temp";
public static final String ELEMENT_NAME = "vCard";
public static final String LAST_STATUS = "LAST_STATUS";
public static final String LAST_STATUS_DESCRIPTION = "LAST_STATUS_DESCRIPTION";
public static final String WORK_TIME_RANGE = "WORK_TIME_RANGE";
public static final String SOUND_SETTINGS = "SOUND_SETTINGS";
public static final String AUTO_LOCATION_MACHINE_DATA = "AUTO_LOCATION_MACHINE_DATA";
public static final String AUTO_LOCATION = "AUTO_LOCATION";
public static final String AUTO_LOCATION_ENABLED = "AUTO_LOCATION_ENABLED";
public static final String AUTO_ONLINE = "AUTO_ONLINE";
public static final String HIDEACTIONNOTIFICATIONS = "HideActionNotifications";
public static final String AUTO_CONNECT = "AUTO_CONNECT";
public static final String AUTO_OFFLINE_WORK_TIME = "AUTO_OFFLINE_WORK_TIME";
public static final String AUTO_RELOGIN = "AUTO_RELOGIN";
public static final String CONNECTED_VIA_INTERNET = "CONNECTED_VIA_INTERNET";
public static final String MINIMIZE_CHAT = "MINIMIZE_CHAT";
public static final String PROMPT_PROJECT_SWITCH = "PROMPT_PROJECT_SWITCH";
public static final String MACHINE_NAME = "MACHINE_NAME";
public static final String MROFFICE_VER = "MROFFICE_VER";
public static final String WORK = "WORK";
public static final String LOCALITY = "LOCALITY";
public static final String TIMESTAMP = "timestamp";
public static final String REGION = "REGION";
public static final String EXT = "EXT";
public static final String LAST_ACTIVITY_TS = "LAST_ACTIVITY_TS";
public static final String FUTURE_STATUS = "FUTURE_STATUS";
public static final String FUTURE_STATUS_DESCRIPTION = "FUTURE_STATUS_DESCRIPTION";
public static final String FUTURE_STATUS_TS = "FUTURE_STATUS_TS";
public static final String CUSTOM = "CUSTOM";
public static final String PREF = "PREF";
private Map<String, String> list = new HashMap<String, String>();
@Override
public IQ parseIQ(XmlPullParser parser) throws Exception
{
String name;
boolean isEmpty;
boolean done = false;
while(parser.next() != XmlPullParser.END_DOCUMENT && false == done)
{
name = parser.getName();
switch (parser.getEventType())
{
case XmlPullParser.START_TAG:
{
isEmpty = parser.isEmptyElementTag();
if(name.equalsIgnoreCase(LAST_STATUS) && false == isEmpty)
{
list.put(LAST_STATUS, parser.nextText());
}
else if(name.equalsIgnoreCase(LAST_STATUS_DESCRIPTION) && false == isEmpty)
{
list.put(LAST_STATUS_DESCRIPTION , parser.nextText());
}
else if(name.equalsIgnoreCase(WORK_TIME_RANGE) && false == isEmpty)
{
list.put(WORK_TIME_RANGE, parser.nextText());
}
else if(name.equalsIgnoreCase(SOUND_SETTINGS) && false == isEmpty)
{
list.put(SOUND_SETTINGS, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_LOCATION_MACHINE_DATA) && false == isEmpty)
{
list.put(AUTO_LOCATION_MACHINE_DATA, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_LOCATION) && false == isEmpty)
{
list.put(AUTO_LOCATION, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_LOCATION_ENABLED) && false == isEmpty)
{
list.put(AUTO_LOCATION_ENABLED, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_ONLINE) && false == isEmpty)
{
list.put(AUTO_ONLINE, parser.nextText());
}
else if(name.equalsIgnoreCase(HIDEACTIONNOTIFICATIONS) && false == isEmpty)
{
list.put(HIDEACTIONNOTIFICATIONS, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_CONNECT) && false == isEmpty)
{
list.put(AUTO_CONNECT, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_OFFLINE_WORK_TIME) && false == isEmpty)
{
list.put(AUTO_OFFLINE_WORK_TIME, parser.nextText());
}
else if(name.equalsIgnoreCase(AUTO_RELOGIN) && false == isEmpty)
{
list.put(AUTO_RELOGIN, parser.nextText());
}
else if(name.equalsIgnoreCase(CONNECTED_VIA_INTERNET) && false == isEmpty)
{
list.put(CONNECTED_VIA_INTERNET, parser.nextText());
}
else if(name.equalsIgnoreCase(MINIMIZE_CHAT) && false == isEmpty)
{
list.put(MINIMIZE_CHAT, parser.nextText());
}
else if(name.equalsIgnoreCase(PROMPT_PROJECT_SWITCH) && false == isEmpty)
{
list.put(PROMPT_PROJECT_SWITCH, parser.nextText());
}
else if(name.equalsIgnoreCase(MACHINE_NAME) && false == isEmpty)
{
list.put(MACHINE_NAME, parser.nextText());
}
else if(name.equalsIgnoreCase(MROFFICE_VER) && false == isEmpty)
{
list.put(MROFFICE_VER, parser.nextText());
}
else if(name.equalsIgnoreCase(WORK) && false == isEmpty)
{
list.put(WORK, parser.nextText());
}
else if(name.equalsIgnoreCase(LOCALITY) && false == isEmpty)
{
list.put(LOCALITY, parser.nextText());
}
else if(name.equalsIgnoreCase(TIMESTAMP) && false == isEmpty)
{
list.put(TIMESTAMP, parser.nextText());
}
else if(name.equalsIgnoreCase(REGION) && false == isEmpty)
{
list.put(REGION, parser.nextText());
}
else if(name.equalsIgnoreCase(EXT) && false == isEmpty)
{
list.put(EXT, parser.nextText());
}
else if(name.equalsIgnoreCase(LAST_ACTIVITY_TS) && false == isEmpty)
{
list.put(LAST_ACTIVITY_TS, parser.nextText());
}
else if(name.equalsIgnoreCase(FUTURE_STATUS) && false == isEmpty)
{
list.put(FUTURE_STATUS, parser.nextText());
}
else if(name.equalsIgnoreCase(FUTURE_STATUS_DESCRIPTION) && false == isEmpty)
{
list.put(FUTURE_STATUS_DESCRIPTION, parser.nextText());
}
else if(name.equalsIgnoreCase(FUTURE_STATUS_TS) && false == isEmpty)
{
list.put(FUTURE_STATUS_TS, parser.nextText());
}
else if(name.equalsIgnoreCase(CUSTOM) && false == isEmpty)
{
list.put(CUSTOM, parser.nextText());
}
else if(name.equalsIgnoreCase(PREF) && false == isEmpty)
{
list.put(PREF, parser.nextText());
}
break;
}
case XmlPullParser.END_TAG:
{
done = ELEMENT_NAME.equalsIgnoreCase(name);
break;
}
}
}
name = null;
return new vCard_IQ(list);
}
}
vCard_IQ.java
public class vCard_IQ extends IQ
{
public static final String ID = "vcard";
private static Map<String, String> list;
private static boolean finishedParsing = false;
public vCard_IQ(Map<String, String> l)
{
if(null == list)
{
list = new HashMap<String, String>();
}
list.clear();
list.putAll(l);
finishedParsing = true;
}
@Override
public String getChildElementXML()
{
return null;
}
public static final Map<String, String> getData()
{
return list;
}
public static void setFinishedParsingToFalse()
{
finishedParsing = false;
}
public static final boolean finishedParsing()
{
return finishedParsing;
}
}
我添加了提供商:
ProviderManager.getInstance().addIQProvider(vCard_IQProvider.ELEMENT_NAME, vCard_IQProvider.NAMESPACE, new vCard_IQProvider());
和包监听器:
connection.addPacketListener(new PacketListener()
{
@Override
public void processPacket(Packet p)
{
if(p.getPacketID().equals(vCard_IQ.ID))
{
vCard_IQ pp = (vCard_IQ)p;
//access the parsed data
//vCard_IQ.getData().get.......
pp = null;
}
}
},
new PacketFilter()
{
@Override
public boolean accept(Packet arg0)
{
return true;
}
});
数据包过滤器设置为接受所有数据包,由于某种原因,列表器不会触发。我可以在调试器中看到服务器正在发送响应。
我甚至尝试通过创建一个异步任务来绕过监听器,在后台线程中等待,直到解析响应并且我访问它。现在它仅适用于第一个发送的iq - 我收到一个响应并且它被正确解析,但是对于其余的我可以在调试器中看到它发送响应的服务器但它从未到达解析器。解析器永远不会被调用。
Asynk<Void, Void, Void> asynk = new Asynk<Void, Void, Void>()
{
Packet iq_vcard;
@Override
protected Void doInBackground(Void... params)
{
for(String s : names_list)
{
final String name = s;
iq_vcard = new Packet()
{
@Override
public String toXML()
{
String str = String.format("<iq from='%s' to='%s' type='get' id='" + vCard_IQ.ID + "'><vCard xmlns='vcard-temp'/></iq>",
sharedPrefs.getString(LogIn.USERNAME, "") + "@" + sharedPrefs.getString(Settings_LogIn.DOMAIN, Settings_LogIn.ERROR) + "/iOffice",
name + "@" + sharedPrefs.getString(Settings_LogIn.DOMAIN, Settings_LogIn.ERROR));
Log.e("iq_vcard", str);
return str;
}
};
connection().sendPacket(iq_vcard);
iq_vcard = null;
while(false == vCard_IQ.finishedParsing())
{
try
{
Thread.sleep(1000);
Log.e("TAG", "waiting to finish parsing...");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
//access the parsed data
//vCard_IQ.getData().get.......
vCard_IQ.setFinishedParsingToFalse();
}
return null;
}
@Override
protected void onPostExecute(Void result)
{
}
};
asynk.execute();
关于什么是错的任何建议?
答案 0 :(得分:1)
这是aSmack中的一个错误,经过多次尝试修复此问题后,尝试自行编译aSmack失败后尝试了tutorial并尝试了一些我能想到的内容,我做了以下内容:我创建了一个新包在我的android项目中并将所有aSmack的java类转储到那里。这样我就让eclipse编译aSmack,我可以更好地控制它的代码。
问题在于每次我从服务器收到自定义iq响应时,在PacketParserUtils.java中,aSmack会返回错误的elementName和名称空间,从而选择错误的iq提供程序来解析响应。
答案 1 :(得分:0)
在方法调用结束时,解析器必须置于其上 子元素的结束标记。
答案 2 :(得分:0)
如果有人试图这样做,我发现问题是什么。
vCard_IQProvider
类的while条件错误,应该是:
while(!done && parser.next() != XmlPullParser.END_DOCUMENT)
否则,当done设置为true时,while将再次检查条件并将解析器移动到下一个元素(通过调用parser.next()
)。