The Sales Management App includes a comprehensive real-time messaging system powered by Firebase, enabling seamless communication between managers and their sales teams.
Chat System Overview
Personal Chat One-on-one messaging between salesperson and their assigned manager
Chat Room Group chat for team-wide announcements and discussions
Real-Time Updates Messages appear instantly using Firebase Realtime Database listeners
Message History Complete chat history preserved and accessible anytime
Chat Types
Personal Chat (Manager ↔ Salesperson)
Direct messaging between a salesperson and their manager for:
Sales strategy discussions
Individual performance feedback
Customer support questions
Inventory inquiries
Personal goal setting
Chat Room (Team Group Chat)
Group messaging for the entire sales team:
Team announcements
Product updates
Team celebrations
Knowledge sharing
General collaboration
Message Data Model
All messages use the BaseMessage class:
public class BaseMessage {
String message ; // Message content
String senderName ; // Sender's user ID
String msgRole ; // "Manager" or "Salesperson"
String createdAt ; // Unix timestamp
public BaseMessage ( String message , String createdAt , String senderName , String msgRole ) {
this . message = message;
this . senderName = senderName;
this . createdAt = createdAt;
this . msgRole = msgRole;
}
}
Source: Chat/BaseMessage.java:7-58
The senderName field actually stores the user’s Firebase ID, not their display name. The msgRole field determines how the message is displayed.
Personal Chat (Salesperson to Manager)
Accessing Personal Chat
Salespersons can message their manager directly:
Open Navigation Drawer
From the Salesperson dashboard, tap the hamburger menu.
Select Message Manager
Tap “Message Manager” from the menu: else if (id1 == R . id . message_manager ){
databaseReference = FirebaseDatabase . getInstance (). getReference ( "Salesperson" );
databaseReference . addListenerForSingleValueEvent ( new ValueEventListener () {
@ Override
public void onDataChange (@ NonNull DataSnapshot dataSnapshot ) {
for ( DataSnapshot snapshot : dataSnapshot . getChildren ()) {
if ( snapshot . getKey (). equals (id)) {
SalesPerson sp = snapshot . getValue ( SalesPerson . class );
salespersonName = sp . getName ();
managerName = sp . getManagerName ();
Intent intent = new Intent ( SalespersonMain . this ,
PersonalChatActivitySalesperson . class );
intent . putExtra ( "SalespersonName" , salespersonName);
intent . putExtra ( "ManagerName" , managerName);
startActivity (intent);
}
}
}
});
}
Source: SalespersonMain.java:479-505
Chat Interface Loads
The PersonalChatActivitySalesperson activity opens with your chat history.
Chat Interface Components
The personal chat interface includes:
private RecyclerView recyclerView ; // Message list
private MessageListAdapter messageListAdapter ; // Adapter for messages
private Button sendButton ; // Send message button
private EditText chatBox ; // Message input field
private String SalespersonName ; // Your name
private String ManagerName ; // Manager's name
Source: Chat/PersonalChatActivityManager.java:35-42
Sending Messages
Type Your Message
Enter text in the chat box at the bottom of the screen.
Tap Send
Click the send button to submit your message: sendButton . setOnClickListener ( new View. OnClickListener () {
@ Override
public void onClick ( View view) {
String message = chatBox . getText (). toString ();
// Get current timestamp
Long tsLong = System . currentTimeMillis () / 1000 - 19800 ;
String ts = tsLong . toString ();
if ( ! message . equals ( "" )) {
BaseMessage baseMessage = new BaseMessage (
message,
ts,
mp . get ( "id" ), // Your user ID
mp . get ( "role" ) // "Salesperson"
);
databaseReference = FirebaseDatabase . getInstance ()
. getReference ( "ChatsTable" );
String key1 = databaseReference . child (tmp1 + "-" + tmp2). push (). getKey ();
databaseReference . child (tmp1 + "-" + tmp2). child (key1). setValue (baseMessage);
chatBox . setText ( "" ); // Clear input
} else {
Toast . makeText ( getApplicationContext (),
"message is empty!!" ,
Toast . LENGTH_SHORT ). show ();
}
}
});
Source: Chat/PersonalChatActivityManager.java:122-168
Message Appears
Your message is saved to Firebase and appears immediately in the chat.
Empty messages cannot be sent. The send button validates that the chat box contains text before submitting.
Firebase Database Structure
Personal chats are stored with a combined key:
ChatsTable/
├─ {ManagerName}-{SalespersonName}/
│ ├─ {messageId1}/
│ │ ├─ message: "Hello, I have a question about inventory"
│ │ ├─ senderName: "userId123"
│ │ ├─ msgRole: "Salesperson"
│ │ └─ createdAt: "1709501234"
│ ├─ {messageId2}/
│ │ ├─ message: "Sure, what do you need to know?"
│ │ ├─ senderName: "userId456"
│ │ ├─ msgRole: "Manager"
│ │ └─ createdAt: "1709501298"
The chat room key is constructed by:
tmp1 = ManagerName . replaceAll ( " \\ s+" , "" ); // Remove spaces from manager name
tmp2 = SalespersonName . replaceAll ( " \\ s+" , "" ); // Remove spaces from salesperson name
String chatRoomKey = tmp1 + "-" + tmp2;
Source: Chat/PersonalChatActivityManager.java:67-68
Real-Time Message Updates
Messages appear instantly using Firebase ChildEventListener:
databaseReference . child (tmp1 + "-" + tmp2). addChildEventListener ( new ChildEventListener () {
@ Override
public void onChildAdded (@ NonNull DataSnapshot dataSnapshot , @ Nullable String s ) {
databaseReference . child (tmp1 + "-" + tmp2)
. addListenerForSingleValueEvent ( new ValueEventListener () {
@ Override
public void onDataChange (@ NonNull DataSnapshot dataSnapshot ) {
final ArrayList < BaseMessage > mMessages = new ArrayList <>();
for ( DataSnapshot dataSnapshot1 : dataSnapshot . getChildren ()){
BaseMessage bm = dataSnapshot1 . getValue ( BaseMessage . class );
mMessages . add (bm);
}
messageListAdapter = new MessageListAdapter ( getApplicationContext (), mMessages);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager ( getApplicationContext ());
recyclerView . setLayoutManager (linearLayoutManager);
recyclerView . setAdapter (messageListAdapter);
messageListAdapter . notifyDataSetChanged ();
recyclerView . smoothScrollToPosition ( mMessages . size () - 1 ); // Scroll to bottom
}
});
}
// ... other listener methods
});
Source: Chat/PersonalChatActivityManager.java:70-120
The chat automatically scrolls to the newest message when you send or receive a message.
Personal Chat (Manager to Salesperson)
Managers can initiate chats with individual salespersons:
From Chat Room
Managers access personal chats through the Chat Room interface:
Open Chat Room
From the Manager dashboard, navigate to “Chat Room” in the navigation drawer: else if (id == R . id . chat_room ){
SessionManager sessionManager = new SessionManager ( getApplicationContext ());
final String idManager = sessionManager . getUserDetails (). get ( "id" );
databaseRef = FirebaseDatabase . getInstance (). getReference ( "Manager" );
databaseRef . addListenerForSingleValueEvent ( new ValueEventListener () {
@ Override
public void onDataChange (@ NonNull DataSnapshot dataSnapshot ) {
for ( DataSnapshot dataSnapshot1 : dataSnapshot . getChildren ()){
if ( dataSnapshot1 . getKey (). equals (idManager)){
SalesManager salesManager = dataSnapshot1 . getValue ( SalesManager . class );
Intent intent = new Intent ( ManagerMain . this , ChatRoom . class );
intent . putExtra ( "ManagerNumber" , salesManager . getNumber ());
intent . putExtra ( "Name" , salesManager . getName ());
startActivity (intent);
}
}
}
});
}
Source: ManagerMain.java:392-416
Select Salesperson
The Chat Room displays a list of all salespersons under this manager. Tap any salesperson to open a personal chat.
Send Messages
The chat interface is identical to the salesperson view, with messages distinguished by the msgRole field.
Group Chat Room
Both Managers and Salespersons can access the team chat room.
Accessing Chat Room
For Managers:
else if (id == R . id . chat_room ){
Intent intent = new Intent ( ManagerMain . this , ChatRoom . class );
intent . putExtra ( "ManagerNumber" , salesManager . getNumber ());
intent . putExtra ( "Name" , salesManager . getName ());
startActivity (intent);
}
Source: ManagerMain.java:392-416
For Salespersons:
else if (id1 == R . id . chat_room ){
// Get manager details
DatabaseReference databaseReference1 = FirebaseDatabase . getInstance ()
. getReference ( "Manager" );
databaseReference1 . addListenerForSingleValueEvent ( new ValueEventListener () {
@ Override
public void onDataChange (@ NonNull DataSnapshot dataSnapshot ) {
for ( DataSnapshot dataSnapshot1 : dataSnapshot . getChildren ()){
SalesManager salesManager = dataSnapshot1 . getValue ( SalesManager . class );
if ( salesManager . getName (). equals (thisManagerName)){
Intent intent = new Intent ( SalespersonMain . this , ChatRoom . class );
intent . putExtra ( "ManagerNumber" , salesManager . getNumber ());
intent . putExtra ( "Name" , SalesPersonName);
startActivity (intent);
}
}
}
});
}
Source: SalespersonMain.java:506-555
Chat Room Interface
The ChatRoom activity displays:
List of Team Members : All salespersons under the manager
Personal Chat Access : Tap any member to open 1-on-1 chat
Group Chat : Team-wide messaging (if implemented)
The ChatRoom uses a RecyclerView with ChatRoomAdapter:
public class ChatRoom extends AppCompatActivity {
private RecyclerView recyclerView ;
private ChatRoomAdapter chatRoomAdapter ;
// Implementation details
}
Source: Chat/ChatRoom.java:12
Message Display
Messages are displayed differently based on sender:
Message Types
Sent Messages Right-aligned, different background color
Received Messages Left-aligned, distinct styling
Message Adapter
The MessageListAdapter handles message rendering:
public class MessageListAdapter extends RecyclerView.Adapter {
private static final int VIEW_TYPE_MESSAGE_SENT = 1 ;
private static final int VIEW_TYPE_MESSAGE_RECEIVED = 2 ;
@ Override
public int getItemViewType ( int position ) {
BaseMessage message = mMessageList . get (position);
// Determine if message was sent by current user
if ( message . getSenderName (). equals (currentUserId)) {
return VIEW_TYPE_MESSAGE_SENT;
} else {
return VIEW_TYPE_MESSAGE_RECEIVED;
}
}
@ Override
public RecyclerView . ViewHolder onCreateViewHolder ( ViewGroup parent , int viewType ) {
if (viewType == VIEW_TYPE_MESSAGE_SENT) {
// Inflate sent message layout
} else {
// Inflate received message layout
}
}
}
Source: Referenced in Chat/MessageListAdapter.java:12
Message Holders
Two ViewHolder classes handle different message types:
public class MessageHolder extends RecyclerView.ViewHolder {
// Sent message view holder
}
public class ReceivedMessageHolder extends RecyclerView.ViewHolder {
// Received message view holder
}
Source: Chat/MessageHolder.java:5 and Chat/ReceivedMessageHolder.java:8
Timestamp Handling
Messages include Unix timestamps for ordering:
Long tsLong = System . currentTimeMillis () / 1000 - 19800 ;
String ts = tsLong . toString ();
The timestamp subtracts 19800 seconds (5.5 hours) to adjust for IST timezone. This is a timezone offset adjustment.
Common Workflows
Salesperson: Asking Manager a Question
Open navigation drawer
Tap “Message Manager”
Type your question in the chat box
Tap send button
Wait for manager’s response (appears automatically)
Continue conversation as needed
Manager: Responding to Salesperson
Open Chat Room from navigation drawer
See list of salespersons
Tap the salesperson who messaged you
View their message in the chat
Type your response
Send message
Message appears in both your view and theirs
Manager: Team Announcement
Open Chat Room
Access group chat (if available)
Type announcement
Send to all team members
All salespersons see the message in their Chat Room
Open personal chat or chat room
Scroll up to see older messages
All messages are preserved since chat creation
Messages are ordered chronologically
Best Practices
Response Time Check messages regularly for timely responses to team inquiries
Professional Tone Maintain professional communication in all chats
Message Clarity Be clear and concise in messages to avoid confusion
Important Info Use chat for quick questions; email critical documents
Limitations
Messages cannot be edited after sending
Messages cannot be deleted
No read receipts to confirm message viewing
No typing indicators
No file attachments (text only)
The chat system is designed for real-time text communication. For sharing documents, images, or files, use alternative methods like email.
Technical Details
Firebase Realtime Database Listeners
The chat uses Firebase ChildEventListener for real-time updates:
onChildAdded: Triggered when a new message is sent
onChildChanged: Would handle message edits (not implemented)
onChildRemoved: Would handle message deletions (not implemented)
This ensures messages appear instantly without polling or manual refresh.
Chat Room Naming Convention
Chat rooms are named by concatenating manager and salesperson names with spaces removed:
Manager: “John Smith”
Salesperson: “Jane Doe”
Chat Room Key: "JohnSmith-JaneDoe"
This creates unique, predictable chat room identifiers for each manager-salesperson pair.