使用 Smack Api for Android 发送和接收消息
Posted
技术标签:
【中文标题】使用 Smack Api for Android 发送和接收消息【英文标题】:Sending and Receiving messages using Smack Api for Android 【发布时间】:2016-02-06 16:21:16 【问题描述】:自过去四天以来,我一直在尝试使用自己的 XMPP 和 Smack+OpenFire 发送和接收聊天消息。根据 Smack 的“readme.txt”,我建立了连接并登录了用户。连接和登录的代码是这样的
public static String TAG = "Test connection";
private static XMPPTCPConnection connection;
private static String userName = "demo";
private static String Password = "demo";
static
// Create the configuration for this new connection
XMPPTCPConnectionConfiguration.Builder configBuilder = XMPPTCPConnectionConfiguration.builder();
configBuilder.setSecurityMode(XMPPTCPConnectionConfiguration.SecurityMode.disabled);
configBuilder.setResource("");
configBuilder.setUsernameAndPassword(userName, Password);
configBuilder.setServiceName("192.168.2.10");
configBuilder.setHost("192.168.2.10");
configBuilder.setPort(5222);
configBuilder.setCompressionEnabled(false);
connection = new XMPPTCPConnection(configBuilder.build());
这样我配置了连接构建器。 在这里,我正在连接并登录用户。
public class ConnectAndLogin extends AsyncTask<Void, Void, Void>
@Override
protected Void doInBackground(Void... params)
try
connection.connect();
Log.i(TAG, "Connected to " + connection.getHost());
catch (SmackException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
catch (XMPPException e)
Log.e(TAG, "Failed to connect to " + connection.getHost());
Log.e(TAG, e.toString());
e.printStackTrace();
try
connection.login(userName, Password);
Log.i(TAG, "Login as a : " + connection.getUser());
setConnection(connection);
setListner();
catch (XMPPException e)
e.printStackTrace();
Log.i(TAG, "Login error " + e.toString());
catch (SmackException e)
e.printStackTrace();
Log.i(TAG, "Login error " + e.toString());
catch (IOException e)
e.printStackTrace();
Log.i(TAG, "Login error " + e.toString());
return null;
在某些教程中,必须在登录后设置addPacketListner
。我在setConnection()
中完成了这项工作,一些帖子通过addAsyncStanzaListner
完成。
用于发送消息
send.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
Message msg = new Message("demo2", Message.Type.chat);
msg.setBody("Hi how are you");
if (connection != null)
try
connection.sendPacket(msg);
Log.d("Send to room : Name : ", "demo2");
Log.d("store", "store data to db");
//DBAdapter.addUserData(new UserData(text, "", "1" ,beam_id));
catch (Exception e)
Log.d("ooo", "msg exception" + e.getMessage());
);
对于接收消息此代码
public void setListner()
connection.addAsyncStanzaListener(new StanzaListener()
@Override
public void processPacket(Stanza packet) throws SmackException.NotConnectedException
Message message = (Message) packet;
Log.i(TAG, "REC : " + message.getBody());
Log.i(TAG, "REC: " + message.getFrom());
, new StanzaFilter()
@Override
public boolean accept(Stanza stanza)
return false;
);
这是我的依赖项
compile 'org.igniterealtime.smack:smack-android:4.1.0'
compile 'org.igniterealtime.smack:smack-tcp:4.1.0'
compile 'org.igniterealtime.smack:smack-core:4.1.0'
compile 'org.igniterealtime.smack:smack-im:4.1.0'
compile 'org.igniterealtime.smack:smack-resolver-minidns:4.1.0'
compile 'org.igniterealtime.smack:smack-sasl-provided:4.1.0'
但我仍然无法向 demo2 用户发送消息。 我在哪里做错了。请指导和帮助我。 谢谢
【问题讨论】:
您是否遇到任何错误 如果您在 smack 中一次收到 100 条消息。当它们从服务器发送时,你能按顺序得到它们吗? 没试过这种方式。 【参考方案1】:很长一段时间后,我现在可以发送短信甚至图像。这是我处理 XmppConnection 的完整代码。
public class SmackConnection implements ConnectionListener, ChatManagerListener, RosterListener, ChatMessageListener, PingFailedListener
private Gson gson;
private AsyncTask<Void, Void, Void> mRegisterTask;
private FileTransferManager manager;
private static final String TAG = "SMACK";
public static Context mApplicationContext;
public static SmackConnection instance = null;
private final String mServiceName = "192.168.2.3";
private static XMPPTCPConnection mConnection;
private static final byte[] dataToSend = StringUtils.randomString(1024 * 4 * 3).getBytes();
private static byte[] dataReceived;
private XMPPTCPConnectionConfiguration.Builder config;
public void init(String mUsername, String mPassword)
Log.i(TAG, "connect()");
config = XMPPTCPConnectionConfiguration.builder();
config.setServiceName(mServiceName);
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
config.setHost(mServiceName);
config.setPort(5222);
config.setDebuggerEnabled(true);
config.setResource("sender");
config.setCompressionEnabled(true);
config.setUsernameAndPassword(mUsername, mPassword);
XMPPTCPConnection.setUseStreamManagementResumptiodDefault(true);
XMPPTCPConnection.setUseStreamManagementDefault(true);
config.setCompressionEnabled(true);
try
TLSUtils.acceptAllCertificates(config);
catch (NoSuchAlgorithmException e)
e.printStackTrace();
catch (KeyManagementException e)
e.printStackTrace();
mConnection = new XMPPTCPConnection(config.build());
mConnection.addConnectionListener(this);
PingManager pingManager = PingManager.getInstanceFor(mConnection);
pingManager.registerPingFailedListener(this);
ChatManager.getInstanceFor(mConnection).addChatListener(this);
manager = FileTransferManager.getInstanceFor(mConnection);
manager.addFileTransferListener(new FileTransferIMPL());
FileTransferNegotiator.getInstanceFor(mConnection);
gson = new Gson();
connectAndLoginAnonymously();
public void connectAndLoginAnonymously()
mRegisterTask = new AsyncTask<Void, Void, Void>()
@Override
protected Void doInBackground(Void... params)
try
mConnection.connect();
mConnection.login();
catch (SmackException | XMPPException | IOException e)
e.printStackTrace();
return null;
@Override
protected void onPostExecute(Void res)
;
// execute AsyncTask
mRegisterTask.execute(null, null, null);
public void login(final String username, final String password)
mRegisterTask = new AsyncTask<Void, Void, Void>()
@Override
protected Void doInBackground(Void... params)
try
disconnect();
config.setUsernameAndPassword(username, password);
mConnection.connect();
mConnection.login();
catch (SmackException | XMPPException | IOException e)
e.printStackTrace();
return null;
@Override
protected void onPostExecute(Void res)
;
// execute AsyncTask
mRegisterTask.execute(null, null, null);
public void disconnect()
Log.i(TAG, "disconnect()");
if (mConnection != null)
mConnection.disconnect();
public void sendMessage(ChatMessage chatMessage)
gson = new Gson();
Log.i(TAG, "sendMessage()");
Chat chat = ChatManager.getInstanceFor(mConnection).createChat(chatMessage.receiver + "@santosh-pc", this);
Gson gson = new Gson();
String body = gson.toJson(chatMessage);
final Message message = new Message();
message.setBody(body);
message.setStanzaId(chatMessage.msgid);
message.setType(Message.Type.chat);
try
chat.sendMessage(message);
catch (SmackException.NotConnectedException e)
e.printStackTrace();
@Override
public void chatCreated(Chat chat, boolean createdLocally)
Log.i(TAG, "chatCreated()");
chat.addMessageListener(this);
//MessageListener
@Override
public void processMessage(Chat chat, Message message)
gson = new Gson();
Log.i(TAG, "processMessage()");
if (message.getType().equals(Message.Type.chat) || message.getType().equals(Message.Type.normal))
Log.i("MyXMPP_MESSAGE_LISTENER", "Xmpp message received: '"
+ message);
if (message.getType() == Message.Type.chat
&& message.getBody() != null)
String sender1 = message.getFrom();
final Random random = new Random();
final String delimiter = "\\@";
String[] temp = sender1.split(delimiter);
final String sender = temp[0];
final ChatMessage chatMessage = gson.fromJson(message.getBody(), ChatMessage.class);
chatMessage.msgid = " " + random.nextInt(1000);
processMessage(sender, chatMessage);
public void processMessage(final String sender, ChatMessage chatMessage)
chatMessage.sender = sender;
chatMessage.receiver = LoginSignupPage.self;
chatMessage.type = "TEXT";
chatMessage.isMine = false;
Log.i("MSG RECE", chatMessage.getBody());
ChatActivity.chatlist.add(chatMessage);
CommonMethods commonMethods = new CommonMethods(mApplicationContext);
commonMethods.createTable(sender);
commonMethods.insertIntoTable(sender, sender, LoginSignupPage.self, "fdfd", "r", "TEXT");
Log.i("MSG RECE", "Added");
new Handler(Looper.getMainLooper()).post(new Runnable()
@Override
public void run()
Log.i("MSG RECE", "LOOPER");
ChatActivity.chatAdapter.notifyDataSetChanged();
);
private void processMessage(final FileTransferRequest request)
new Handler(Looper.getMainLooper()).post(new Runnable()
@Override
public void run()
Log.i("MSG RECE", "LOOPER");
Random random = new Random();
CommonMethods commonMethods = new CommonMethods(mApplicationContext);
int iend = request.getRequestor().lastIndexOf("@");
String requester = request.getRequestor().substring(0, 10);
commonMethods.createTable(requester);
Log.i("MSG RECE", requester);
commonMethods.insertIntoTable(requester, requester, LoginSignupPage.self, request.getFileName(), "r", "IMG");
final ChatMessage chatMessage = new ChatMessage(LoginSignupPage.self, requester,
request.getFileName(), "" + random.nextInt(1000), false, "IMG");
chatMessage.setMsgID();
chatMessage.body = request.getFileName();
chatMessage.Date = CommonMethods.getCurrentDate();
chatMessage.Time = CommonMethods.getCurrentTime();
chatMessage.type = "IMG";
ChatActivity.chatlist.add(chatMessage);
ChatActivity.chatAdapter.notifyDataSetChanged();
Log.i("MSG RECE", request.getRequestor());
);
//ConnectionListener
@Override
public void connected(XMPPConnection connection)
Log.i(TAG, "connected()");
@Override
public void authenticated(XMPPConnection connection, boolean arg0)
Log.i(TAG, "authenticated()");
@Override
public void connectionClosed()
Log.i(TAG, "connectionClosed()");
@Override
public void connectionClosedOnError(Exception e)
Log.i(TAG, "connectionClosedOnError()");
@Override
public void reconnectingIn(int seconds)
Log.i(TAG, "reconnectingIn()");
@Override
public void reconnectionSuccessful()
Log.i(TAG, "reconnectionSuccessful()");
@Override
public void reconnectionFailed(Exception e)
Log.i(TAG, "reconnectionFailed()");
//RosterListener
@Override
public void entriesAdded(Collection<String> addresses)
@Override
public void entriesUpdated(Collection<String> addresses)
Log.i(TAG, "entriesUpdated()");
@Override
public void entriesDeleted(Collection<String> addresses)
Log.i(TAG, "entriesDeleted()");
@Override
public void presenceChanged(Presence presence)
Log.i(TAG, "presenceChanged()");
@Override
public void pingFailed()
Log.i(TAG, "pingFailed()");
public boolean createNewAccount(String username, String newpassword)
boolean status = false;
if (mConnection == null)
try
mConnection.connect();
catch (SmackException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
catch (XMPPException e)
e.printStackTrace();
try
String newusername = username + mConnection.getServiceName();
Log.i("service", mConnection.getServiceName());
AccountManager accountManager = AccountManager.getInstance(mConnection);
accountManager.createAccount(username, newpassword);
status = true;
catch (SmackException.NoResponseException e)
status = false;
e.printStackTrace();
catch (XMPPException.XMPPErrorException e)
e.printStackTrace();
status = false;
catch (SmackException.NotConnectedException e)
e.printStackTrace();
status = false;
mConnection.disconnect();
return status;
public XMPPTCPConnection getConnection()
return mConnection;
public SmackConnection(Context context)
mApplicationContext = context;
public SmackConnection()
public XMPPTCPConnection SmackConnection()
return mConnection;
public static SmackConnection getInstance(Context context)
if (instance == null)
instance = new SmackConnection(context);
mApplicationContext = context;
return instance;
public class FileTransferIMPL implements FileTransferListener
@Override
public void fileTransferRequest(final FileTransferRequest request)
final IncomingFileTransfer transfer = request.accept();
try
InputStream is = transfer.recieveFile();
ByteArrayOutputStream os = new ByteArrayOutputStream();
int nRead;
byte[] buf = new byte[1024];
try
while ((nRead = is.read(buf, 0, buf.length)) != -1)
os.write(buf, 0, nRead);
os.flush();
catch (IOException e)
e.printStackTrace();
dataReceived = os.toByteArray();
createDirectoryAndSaveFile(dataReceived, request.getFileName());
Log.i("File Received", transfer.getFileName());
processMessage(request);
catch (XMPPException ex)
Logger.getLogger(SmackConnection.class.getName()).log(Level.SEVERE, null, ex);
catch (SmackException e)
e.printStackTrace();
public void fileTransfer(String user, Bitmap bitmap, String filename) throws XMPPException
Roster roster = Roster.getInstanceFor(mConnection);
String destination = roster.getPresence(user).getFrom();
// Create the file transfer manager
FileTransferManager manager = FileTransferManager.getInstanceFor(mConnection);
// Create the outgoing file transfer
final OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(destination);
// Send the file
//transfer.sendFile(new File("abc.txt"), "You won't believe this!");
transfer.sendStream(new ByteArrayInputStream(convertFileToByte(bitmap)), filename, convertFileToByte(bitmap).length, "A greeting");
System.out.println("Status :: " + transfer.getStatus() + " Error :: " + transfer.getError() + " Exception :: " + transfer.getException());
System.out.println("Is it done? " + transfer.isDone());
if (transfer.getStatus().equals(FileTransfer.Status.refused))
System.out.println("refused " + transfer.getError());
else if (transfer.getStatus().equals(FileTransfer.Status.error))
System.out.println(" error " + transfer.getError());
else if (transfer.getStatus().equals(FileTransfer.Status.cancelled))
System.out.println(" cancelled " + transfer.getError());
else
System.out.println("Success");
public byte[] convertFileToByte(Bitmap bmp)
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
return stream.toByteArray();
private void createDirectoryAndSaveFile(byte[] imageToSave, String fileName)
File direct = new File(Environment.getExternalStorageDirectory() + "/LocShopie/Received/");
if (!direct.exists())
File wallpaperDirectory = new File("/sdcard/LocShopie/Received/");
wallpaperDirectory.mkdirs();
File file = new File(new File("/sdcard/LocShopie/Received/"), fileName);
if (file.exists())
file.delete();
try
FileOutputStream out = new FileOutputStream(file);
out.write(imageToSave);
out.flush();
out.close();
catch (Exception e)
e.printStackTrace();
/*DeliveryReceiptManager dm = DeliveryReceiptManager
.getInstanceFor(mConnection);
dm.setAutoReceiptMode(DeliveryReceiptManager.AutoReceiptMode.always);
dm.addReceiptReceivedListener(new ReceiptReceivedListener()
@Override
public void onReceiptReceived(final String fromid,
final String toid, final String msgid,
final Stanza packet)
);*/
在这一些行是数据库的,因为我将文本 msg 存储在 sqlite 中。 此方法用于发送消息。
public void sendTextMessage(View v)
String message = msg_edittext.getEditableText().toString();
if (!message.equalsIgnoreCase(""))
final ChatMessage chatMessage = new ChatMessage(LoginSignupPage.self, user2, message, "" + random.nextInt(1000), true, "TEXT");
chatMessage.setMsgID();
chatMessage.body = message;
chatMessage.Date = CommonMethods.getCurrentDate();
chatMessage.Time = CommonMethods.getCurrentTime();
chatMessage.type = "TEXT";
chatMessage.isMine = true;
msg_edittext.setText("");
try
chatAdapter.add(chatMessage);
chatAdapter.notifyDataSetChanged();
chatXmpp.sendMessage(chatMessage);
catch (Exception e)
e.printStackTrace();
CommonMethods commonMethods = new CommonMethods(ChatActivity.this);
commonMethods.createTable(user2);
commonMethods.insertIntoTable(user2, chatMessage.sender, chatMessage.receiver, chatMessage.body, "m", "TEXT");
【讨论】:
可以分享一下chatMessage类吗 谢谢我有几个问题你能帮我吗 如果您有任何单独的错误,请发布另一个问题。否则评论。 您好,您遇到聊天消息慢的问题吗? 您可以在他们的社区页面上查看。 community.igniterealtime.org/thread/57267以上是关于使用 Smack Api for Android 发送和接收消息的主要内容,如果未能解决你的问题,请参考以下文章
android 在 facebook 聊天中使用 smack api
Smack 4.1 所需的最低 Android API 级别是多少?
在 MainActivity android 中使用 smack API 与服务器连接