xmpp连接黑莓java
Posted
技术标签:
【中文标题】xmpp连接黑莓java【英文标题】:xmpp connection blackberry java 【发布时间】:2014-07-01 12:45:10 【问题描述】:我能够连接 xmpp 服务器并完成登录身份验证,但是当我发送名册时,输入流 is.read() 给了我 -1 并抛出了一个异常,我现在不知道该怎么办。请帮帮我。
我的 XMppCONnection 类:
package mypackage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Vector;
import javax.microedition.io.ConnectionNotFoundException
import javax.microedition.io.SecureConnection;
import javax.microedition.io.StreamConnection;
import net.rim.device.api.io.File;
import net.rim.device.api.io.FileInputStream;
import net.rim.device.api.io.FileOutputStream;
public class XMPPConnection extends XMPPThread
private XmlReader reader;
private XmlWriter writer;
private InputStream is;
private OutputStream os;
FileInputStream fis;
FileOutputStream fos;
File file;
/**
* If you create this object all variables will be saved and the
* method @link #run() is started to log in on jabber server and
* listen to parse incomming xml stanzas. Use
* @link #addListener(XmppListener xl) to listen to events of this object.
*/
// jid must in the form "username@host"
// to login Google Talk, set port to 5223 (NOT 5222 in their offical guide)
public XMPPConnection(Connection connection)
super(connection);
this.host = connection.getHost();
this.port = connection.getPort();
this.username = connection.getUsername();
this.password = connection.getPassword();
this.resource = "mobile";
this.myjid = this.username + "@" + this.host;
if (connection.getServer() == null)
this.server = host;
else
this.server = connection.getServer();
this.use_ssl = connection.isSSL();
this.connectionMaskIndex = connection.getNetworkType();
/**
* The <code>run</code> method is called when @link XMPPConnection object is
* created. It sets up the reader and writer, calls @link #login()
* methode and listens on the reader to parse incomming xml stanzas.
*/
public void run()
try
this.connect();
catch (final IOException e)
e.printStackTrace();
this.connectionFailed(e.getMessage());
return;
catch (Exception e)
e.printStackTrace();
this.connectionFailed(e.getMessage());
return;
// connected
try
boolean loginSuccess = this.login();
if (loginSuccess)
this.parse();
catch (final Exception e)
// hier entsteht der connection failed bug (Network Down)
java.lang.System.out.println(e);
this.connectionFailed(e.toString());
protected void connect() throws IOException, Exception
if (!use_ssl)
//final StreamConnection connection = (StreamConnection) Connector.open("http://" + this.server + ":" + this.port+this.connectionMask, Connector.READ_WRITE);
ConnectionFactory connectionFactory = new ConnectionFactory("socket://" + this.server + ":" + this.port, this.connectionMaskIndex);
StreamConnection connection = null;
try
connection = (StreamConnection) connectionFactory.getNextConnection();
catch (NoMoreTransportsException e)
throw new Exception("Connection failed. No transport available.");
catch (ConnectionNotFoundException e)
throw new Exception("ConnectionNotFoundException:" + e.getMessage());
catch (IllegalArgumentException e)
throw new Exception("IllegalArgumentException: " + e.getMessage());
catch (IOException e)
throw new Exception("IOException: " + e.getMessage());
is = connection.openInputStream();
os = connection.openOutputStream();
this.reader = new XmlReader(is);
this.writer = new XmlWriter(os);
else
//final SecureConnection sc = (SecureConnection) Connector.open("ssl://" + this.server + ":" + this.port+this.connectionMask, Connector.READ_WRITE);
ConnectionFactory connectionFactory = new ConnectionFactory("ssl://" + this.server + ":" + this.port, this.connectionMaskIndex);
SecureConnection sc = null;
try
sc = (SecureConnection) connectionFactory.getNextConnection();
catch (NoMoreTransportsException e)
throw new Exception("Connection failed. No transport available.");
catch (ConnectionNotFoundException e)
throw new Exception("ConnectionNotFoundException: " + e.getMessage());
catch (IllegalArgumentException e)
throw new Exception("IllegalArgumentException: " + e.getMessage());
catch (IOException e)
throw new Exception("IOException: " + e.getMessage());
if (sc != null)
//sc.setSocketOption(SocketConnection.DELAY, 1);
//sc.setSocketOption(SocketConnection.LINGER, 0);
is = sc.openInputStream();
os = sc.openOutputStream();
this.reader = new XmlReader(is);
this.writer = new XmlWriter(os);
/**
* Opens the connection with a stream-tag, queries authentication type and
* sends authentication data, which is username, password and resource.
* @return
* @throws Exception
*/
protected boolean login() throws Exception
String msg = "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='" + this.host + "' version='1.0'>";
os.write(msg.getBytes());
os.flush();
do
reader.next();
if (reader.getType() == XmlReader.START_TAG && reader.getName().equals("stream:features"))
this.packetParser.parseFeatures(reader);
while (!(reader.getType() == XmlReader.END_TAG && reader.getName().equals("stream:features")));
boolean loginSuccess = this.doAuthentication();
msg = "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='" + this.host + "' version='1.0'>";
os.write(msg.getBytes());
os.flush();
reader.next();
while (true)
if ((reader.getType() == XmlReader.END_TAG) && reader.getName().equals("stream:features"))
break;
reader.next();
if (resource == null)
msg = "<iq type='set' id='res_binding'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></iq>";
else
msg = "<iq type='set' id='res_binding'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>" + resource + "</resource></bind></iq>";
os.write(msg.getBytes());
os.flush();
return loginSuccess;
protected void parse() throws IOException
while (true)
int nextTag = this.reader.next();
switch (nextTag)
case XmlReader.START_TAG:
final String tmp = this.reader.getName();
if (tmp.equals("message"))
this.packetParser.parseMessage(this.reader);
else if (tmp.equals("presence"))
this.packetParser.parsePresence(this.reader);
else if (tmp.equals("iq"))
this.packetParser.parseIq(this.reader, this.writer);
else
this.packetParser.parseIgnore(this.reader);
break;
case XmlReader.END_TAG:
this.reader.close();
throw new IOException("Unexpected END_TAG "+this.reader.getName());
default:
this.reader.close();
throw new IOException("Bad XML tag");
protected boolean doAuthentication() throws Exception
boolean loginSuccess = false;
Vector mechanismList = this.packetParser.getMechanism();
System.out.println(mechanismList.toString());
if (mechanismList.contains("X-GOOGLE-TOKEN"))
// X-GOOGLE-TOKEN authorization doing. User can disable
// google features using by deselecting corresponding
// checkbox in profile
String resp = this.packetParser.getGoogleToken(this.myjid, this.password);
String msg = "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"X-GOOGLE-TOKEN\">" + resp + "</auth>";
os.write(msg.getBytes());
//os.flush();
reader.next();
if (reader.getName().equals("success"))
loginSuccess = true;
while (true)
if ((reader.getType() == XmlReader.END_TAG) && reader.getName().equals("success"))
break;
reader.next();
if (mechanismList.contains("PLAIN") && loginSuccess == false)
String msg = "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>";
byte[] auth_msg = (username + "@" + host + "\0" + username + "\0" + password).getBytes();
msg = msg + MD5.toBase64(auth_msg) + "</auth>";
os.write(msg.getBytes());
os.flush();
reader.next();
if (reader.getName().equals("success"))
loginSuccess = true;
while (true)
if ((reader.getType() == XmlReader.END_TAG) && reader.getName().equals("success"))
break;
reader.next();
if (loginSuccess == false)
for (Enumeration e = listeners.elements(); e.hasMoreElements();)
XmppListener xl = (XmppListener) e.nextElement();
xl.onAuthFailed(reader.getName() + ", failed authentication");
return false;
return loginSuccess;
public void getRosterVCard(String tojid) throws IOException
this.writer.startTag("iq");
this.writer.attribute("id", "vc2");
this.writer.attribute("to", tojid);
this.writer.attribute("type", "get");
this.writer.startTag("vCard");
this.writer.attribute("xmlns", "vcard-temp");
this.writer.endTag(); // vCard
this.writer.endTag(); // iq
this.writer.flush();
/**
* Sends a roster query.
*
* @throws java.io.IOException is thrown if @link XmlReader or @link XmlWriter
* throw an IOException.
*/
public void getRoster() throws IOException
this.writer.startTag("iq");
// this.writer.attribute("id", "roster");
this.writer.attribute("type", "get");
this.writer.startTag("query");
this.writer.attribute("xmlns", "jabber:iq:roster");
this.writer.endTag(); // query
this.writer.endTag(); // iq
this.writer.flush();
//<iq id="qxmpp7" from="919700424402@213.204.83.20/QXmpp" type="get"><query xmlns="jabber:iq:roster"/></iq>
/**
* Sends a message text to a known jid.
*
* @param to the JID of the recipient
* @param msg the message itself
*/
public void sendMessage(final String to, final String msg, final String id)
try
this.writer.startTag("message");
this.writer.attribute("type", "chat");
this.writer.attribute("to", to);
this.writer.startTag("body");
this.writer.text(msg);
this.writer.endTag();
this.writer.endTag();
this.writer.flush();
catch (final IOException e)
java.lang.System.out.println(e);
this.connectionFailed();
/**
* Requesting a subscription.
*
* @param to the jid you want to subscribe
*/
public void subscribe(final String to)
this.sendPresence(to, "subscribe", null, null, 0);
/**
* Remove a subscription.
*
* @param to the jid you want to remove your subscription
*/
public void unsubscribe(final String to)
this.sendPresence(to, "unsubscribe", null, null, 0);
/**
* Approve a subscription request.
*
* @param to the jid that sent you a subscription request
*/
public void subscribed(final String to)
this.sendPresence(to, "subscribed", null, null, 0);
/**
* Refuse/Reject a subscription request.
*
* @param to the jid that sent you a subscription request
*/
public void unsubscribed(final String to)
this.sendPresence(to, "unsubscribed", null, null, 0);
/**
* Sets your Jabber Status.
*
* @param show is one of the following: <code>null</code>, chat, away,
* dnd, xa, invisible
* @param status an extended text describing the actual status
* @param priority the priority number (5 should be default)
*/
public void setStatus(String show, String status, final int priority)
if (show.equals(""))
show = null;
if (status.equals(""))
status = null;
if (show.equals("invisible"))
this.sendPresence(null, "invisible", null, null, priority);
else
this.sendPresence(null, null, show, status, priority);
/**
* Sends a presence stanza to a jid. This method can do various task but
* it's private, please use setStatus to set your status or explicit
* subscription methods subscribe, unsubscribe, subscribed and
* unsubscribed to change subscriptions.
*/
public void sendPresence(final String to, final String type, final String show, final String status, final int priority)
try
this.writer.startTag("presence");
if (type != null)
this.writer.attribute("type", type);
if (to != null)
this.writer.attribute("to", to);
if (show != null)
this.writer.startTag("show");
this.writer.text(show);
this.writer.endTag();
if (status != null)
this.writer.startTag("status");
this.writer.text(status);
this.writer.endTag();
if (priority != 0)
this.writer.startTag("priority");
this.writer.text(Integer.toString(priority));
this.writer.endTag();
this.writer.endTag(); // presence
this.writer.flush();
catch (final IOException e)
java.lang.System.out.println(e);
this.connectionFailed();
/**
* Closes the stream-tag and the @link XmlWriter.
*/
public void logoff()
try
this.writer.endTag();
this.writer.flush();
this.writer.close();
catch (final IOException e)
java.lang.System.out.println(e);
this.connectionFailed();
/**
* Save a contact to roster. This means, a message is send to jabber
* server (which hosts your roster) to update the roster.
*
* @param jid the jid of the contact
* @param name the nickname of the contact
* @param group the group of the contact
* @param subscription the subscription of the contact
*/
public void saveContact(final String jid, final String name, final Enumeration group, final String subscription)
try
this.writer.startTag("iq");
this.writer.attribute("type", "set");
this.writer.startTag("query");
this.writer.attribute("xmlns", "jabber:iq:roster");
this.writer.startTag("item");
this.writer.attribute("jid", jid);
if (name != null)
this.writer.attribute("name", name);
if (subscription != null)
this.writer.attribute("subscription", subscription);
if (group != null)
while (group.hasMoreElements())
this.writer.startTag("group");
this.writer.text((String) group.nextElement());
this.writer.endTag(); // group
this.writer.endTag(); // item
this.writer.endTag(); // query
this.writer.endTag(); // iq
this.writer.flush();
catch (final IOException e)
java.lang.System.out.println(e);
this.connectionFailed();
/**
* This method is used to be called on a parser or a connection error.
* It tries to close the XML-Reader and XML-Writer one last time.
*
*/
private void connectionFailed()
if (this.writer != null)
this.writer.close();
if (this.reader != null)
this.reader.close();
for (Enumeration e = listeners.elements(); e.hasMoreElements();)
XmppListener xl = (XmppListener) e.nextElement();
xl.onConnFailed("");
private void connectionFailed(final String msg)
if (this.writer != null)
this.writer.close();
if (this.reader != null)
this.reader.close();
for (Enumeration e = listeners.elements(); e.hasMoreElements();)
XmppListener xl = (XmppListener) e.nextElement();
xl.onConnFailed(msg);
;
xml 阅读器如下所示:
public class XmlReader
private InputStream is;
public final static int START_DOCUMENT = 0;
public final static int END_DOCUMENT = 1;
public final static int START_TAG = 2;
public final static int END_TAG = 3;
public final static int TEXT = 4;
//private Stack tags;
private boolean inside_tag;
private boolean left_angle;
private String tagName;
private String text;
private final Hashtable attributes = new Hashtable();
private int c;
private int type = START_DOCUMENT;
//public XmlReader(final InputStream in) throws IOException, UnsupportedEncodingException
public XmlReader(final InputStream in) throws IOException
//reader = new InputStreamReader(in, "UTF-8");
this.is = in;
//this.tags = new Stack();
this.inside_tag = false;
this.left_angle = false;
//http://discussion.forum.nokia.com/forum/showthread.php?t=76814
//by abirr
private int getNextCharacter() throws IOException
int a = is.read();
int t=a;
if((t|0xC0)==t)
int b = is.read();
if( b == 0xFF ) // Check if legal
t=-1;
else if( b < 0x80 ) // Check for UTF8 compliancy
throw new IOException("Bad UTF-8 Encoding encountered");
else if((t|0xE0)==t)
int c = is.read();
if( c == 0xFF ) // Check if legal
t=-1;
else if( c < 0x80 ) // Check for UTF8 compliancy
throw new IOException("Bad UTF-8 Encoding encountered");
else
t=((a & 0x0F)<<12) | ((b & 0x3F)<<6) | (c & 0x3F);
else
t=((a & 0x1F)<<6)|(b&0x3F);
return a;
public void close()
if (is != null)
try
is.close();
is = null;
catch (IOException e)
e.printStackTrace();
/*try
reader.close();
catch (IOException e) */
public int next() throws IOException
/* while (!this.ready())
try
java.lang.Thread.sleep(100);
catch (InterruptedException e) */
this.c = getNextCharacter();
if (this.c <= ' ')
while (((this.c = getNextCharacter()) <= ' ') && (this.c != -1))
;
if (this.c == -1)
this.type = END_DOCUMENT;
return this.type;
if (this.left_angle || (this.c == '<'))
this.inside_tag = true;
// reset all
this.tagName = null;
this.text = null;
this.attributes.clear();
if (this.c == '<')
this.left_angle = true;
this.c = getNextCharacter();
if (this.left_angle && this.c == '/')
this.left_angle = false;
this.type = END_TAG;
this.c = getNextCharacter();
this.tagName = this.readName('>');
else if (this.left_angle && ((this.c == '?') || (this.c == '!'))) // ignore xml heading & // comments
this.left_angle = false;
while ((this.c = getNextCharacter()) != '>')
;
this.next();
else
this.left_angle = false;
this.type = START_TAG;
this.tagName = this.readName(' ');
String attribute = "";
String value = "";
while (this.c == ' ')
/*this.c = getNextCharacter();
attribute = this.readName('=');
int quote = getNextCharacter();//this.c = this.read(); // '''
BTalk.debugConsole.addDebugMsg("quote: " + quote);
this.c = getNextCharacter();
value = this.readText(quote); //change from value = this.readText(''');
this.c = getNextCharacter();
this.attributes.put(attribute, value);
BTalk.debugConsole.addDebugMsg("attributes: " + attributes);*/
this.c = getNextCharacter();
attribute = this.readName('=').trim();
int quote = getNextCharacter();//this.c = this.read(); // '''
if (quote == 32)
while (quote == 32)
quote = getNextCharacter();//this.c = this.read(); // '''
this.c = getNextCharacter();
value = this.readText(quote); //change from value = this.readText(''');
this.c = getNextCharacter();
this.attributes.put(attribute, value);
else
this.c = getNextCharacter();
value = this.readText(quote); //change from value = this.readText(''');
this.c = getNextCharacter();
this.attributes.put(attribute, value);
if (this.c != '/')
this.inside_tag = false;
else if ((this.c == '>') && this.inside_tag) // last tag ended
this.type = END_TAG;
this.inside_tag = false;
else
this.tagName = null;
this.attributes.clear();
this.type = TEXT;
this.text = this.readText('<');
// fix the < dismatching problem
this.left_angle = true;
return this.type;
// NOTICE: this is only for debug use
public void parsehtml() throws IOException
while (true)
char c;
c = (char) this.getNextCharacter();
System.out.print(c);
public int getType()
return this.type;
public String getName()
return this.tagName;
public String getAttribute(final String name)
return (String) this.attributes.get(name);
public Enumeration getAttributes()
return this.attributes.keys();
public String getText()
return this.text;
private String readText(final int end) throws IOException
final StringBuffer output = new StringBuffer("");
while (this.c != end)
if (this.c == '&')
this.c = getNextCharacter();
switch (this.c)
case 'l':
output.append('<');
break;
case 'g':
output.append('>');
break;
case 'a':
if (getNextCharacter() == 'm')
output.append('&');
else
output.append('\'');
break;
case 'q':
output.append('"');
break;
case 'n':
output.append(' ');
break;
default:
output.append('?');
while ((this.c = getNextCharacter()) != ';')
;
// NOTICE: Comment out these mystical codes
// else if (this.c == '\\')
// // NOTICE: What this means?
// if ((this.c = getNextCharacter()) == '<')
// output.append('\\');
// break;
// else
// output.append((char) this.c);
//
else
output.append((char) this.c);
this.c = getNextCharacter();
// while((c = read()) != end);
System.out.println(output.toString()+"");
return output.toString();
private String readName(final int end) throws IOException
final StringBuffer output = new StringBuffer("");
do
output.append((char) this.c);
while (((this.c = getNextCharacter()) != end) && (this.c != '>') && (this.c != '/'));
return output.toString();
;
【问题讨论】:
谁能帮帮我 【参考方案1】:问题在于会话我们需要在名册之前创建会话
String msg = "<iq type=\"set\" id=\"session_1\"><session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/></iq>";
try
os.write(msg.getBytes());
os.flush();
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
try
reader.next();
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
if (reader.getName().equals("iq"))
while (true)
if((reader.getType() == XmlReader.END_TAG) && reader.getName().equals("iq"))
session=true;
break;
try
reader.next();
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
//
now the problem is solved.thank you
【讨论】:
问题已解决。以上是我错过的代码。这在库中不可用。以上是关于xmpp连接黑莓java的主要内容,如果未能解决你的问题,请参考以下文章