使用 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 级别是多少?

找不到提供程序类 SMACK 4.1.1 Android

在 MainActivity android 中使用 smack API 与服务器连接

Stanza for Smack 4.1.4 中的自定义扩展元素

使用 Android 上的 Smack API 获取在服务器上注册并具有在线/离线状态的所有用户的列表