Sending and Receiving messages using Smack Api for Android

10,461

After long time now i can send text message and even images. this is my complete code to that handle the 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) {

    }
});*/
}

In this some lines are of database as i am storing the text msg in sqlite. this method is for send msg.

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");
    }
}
Share:
10,461
Devendra Singh
Author by

Devendra Singh

I am neither especially clever nor especially gifted. I am only very, very curious.

Updated on June 11, 2022

Comments

  • Devendra Singh
    Devendra Singh about 2 years

    I'm trying since last four days to send and receive chat message using own XMPP and with Smack+OpenFire. According to Smack's "readme.txt' i set up the connection and got logged user in. The code of connection and login is this

    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());
    }
    

    This way i configured the connectionbuilder. here i am connecting and signing in the user.

    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;
        }
    }
    

    In some tutorials that the addPacketListner must be set after login. i done that in setConnection() and some posts went through addAsyncStanzaListner. for send message

    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());
                    }
                }
            }
        });
    

    and for receiving messages this code

     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;
            }
        });
    }
    

    here is my dependencies

     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'
    

    But still i'm not able to send messages to demo2 user. Where im doing wrong.Please guide and help me. Thanks