Skip to main content

[Make-A] Simple Chat Application using Cloud Firestore Part 5 – Creating a Chat Room

As a user,
When I create a new room,
I want to be able to enter the room name
  • Display a field where a user can enter the room name
  • User should not be able to create a room with an empty name
  • Display an error message if user attempts to create a room with an empty name

Table of Contents

  1. Part 1 – Specs and Introduction
  2. Part 2 – Setting up Firebase Cloud Firestore
  3. Part 3 – Adding a Simple Authentication
  4. Part 4 – Adding a FloatingActionButton (FAB)
  5. Part 5 – Creating a Chat Room
  6. Part 6 – Entering The Chat Room
  7. Part 7 – Displaying The Chat Rooms
  8. Part 8 – Chat
  9. 10 Exercises and Thanks!

1. Download icons for our menu

1. Download these icons (Choose any color that you want):

2. Extract .zip the files.

3. I assume you already know how to copy these icons to your project. As previously demonstrated in adding a FAB.

4. Be sure to copy all the folders and paste it in your res/ folder okay? Don’t DRAG the folders to your res/ folder. Just copy and paste it so that it will just merge the folders and not overwrite it.

2. Creating an activity for creating a chat room

1. Create a new activity by right-clicking your package name New > Activity > Empty Activity.

2. I’ll name it CreateRoomActivity. You can name it however you want.

3. In your strings.xml, add these strings.

<resources>
    ...
    <string name="hint_create_room">Enter room name&#8230;</string>
    <string name="create_room">Create room</string>
    <string name="error_empty_room>Please enter a room name</string>
</resources>

4. In your activity_create_room.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <EditText
        android:id="@+id/room_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/hint_create_room"
        android:layout_margin="8dp" />
</LinearLayout>

5. In your CreateRoomActivity.class

public class CreateRoomActivity extends AppCompatActivity {

    private EditText roomName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_create_room);

        roomName = findViewById(R.id.room_name);
    }
}

3. Creating our menu for CreateRoomActivity

1. Right click your res/ folder. New > Android Resource Directory

2. Change Resource type to menu.

3. Right click your menu folder under res/ folder. New > Menu resource file.

4. Enter create_room_menu as file name.

5. In your create_room_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/create_room"
        android:icon="@drawable/ic_done_white_24dp"
        android:title="@string/create_room"
        app:showAsAction="always" />
</menu>

4. Using our menu in CreateRoomActivity

1. In your CreateRoomActivity.class

public class CreateRoomActivity extends AppCompatActivity {

    private EditText roomName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_create_room);

        roomName = findViewById(R.id.room_name);

        setTitle(getString(R.string.create_room));

        if (getSupportActionBar() != null) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_clear_white_24dp);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.create_room_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
            case R.id.create_room:
                // TODO: Check if roomName is empty show error
                // TODO: If roomName is not empty, save room name to Firestore
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

2. Open your MainActivity.class, in initUI() method start CreateRoomActivity when the FAB is clicked.

private void initUI() {
    createRoom.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ...
            Intent intent = new Intent(MainActivity.this, CreateRoomActivity.class);
            startActivity(intent);
        }
    });
}

3. Launch your app and you should see a screen similar to this one.

You might be wondering why create an Activity for just one EditText instead of a Dialog. We never know you might come up with more ideas as you’re going through this and you want to add more fields. 😉

5. Handling empty room name

1. In your CreateRoomActivity.class, show a Toast if roomName is empty

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        ...
        case R.id.create_room:
            if (isRoomEmpty()) {
                Toast.makeText(this, getString(R.string.error_empty_room), Toast.LENGTH_SHORT).show();
            } else {
                // TODO: If roomName is not empty, save room name to Firestore
            }
            return true;
        ...
    }
}

private boolean isRoomEmpty() {
    return roomName.getText().toString().isEmpty();
}

2. Let’s test it. If you try to click the done icon in your menu and roomName is empty it should show a Toast like this one.

If you want to make it more elegant, I highly encourage you to use TextInputLayout for showing an error and a label. You can check JournalDev’s Android TextInputLayout Example for a more in-depth tutorial.

6. Saving our chat room name to Cloud Firestore

1. Create a new class called ChatRoomRepository.class

2. In your ChatRoomRepository.class

public class ChatRoomRepository {
    private static final String TAG = "ChatRoomRepo";

    private FirebaseFirestore db;

    public ChatRoomRepository(FirebaseFirestore db) {
        this.db = db;
    }

    public void createRoom(String name,
                           final OnSuccessListener<DocumentReference> successCallback,
                           final OnFailureListener failureCallback) {
        Map<String, Object> room = new HashMap<>();
        room.put("name", name);

        db.collection("rooms")
                .add(room)
                .addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
                    @Override
                    public void onSuccess(DocumentReference documentReference) {
                        successCallback.onSuccess(documentReference);
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        failureCallback.onFailure(e);
                    }
                });
    }
}

3. Back to our CreateRoomActivity.class, let’s add the functionality

public class CreateRoomActivity extends AppCompatActivity {

    private ChatRoomRepository chatRoomRepository;

    ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_create_room);

        chatRoomRepository = new ChatRoomRepository(FirebaseFirestore.getInstance());

        ...
    }

    ...

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            ...
            case R.id.create_room:
                if (isRoomEmpty()) {
                    Toast.makeText(this, getString(R.string.error_empty_room), Toast.LENGTH_SHORT).show();
                } else {
                    createRoom();
                }
                return true;
            ...
        }
    }

    ...

    private void createRoom() {
        chatRoomRepository.createRoom(
                roomName.getText().toString(),
                new OnSuccessListener<DocumentReference>() {
                    @Override
                    public void onSuccess(DocumentReference documentReference) {
                        finish();
                    }
                },
                new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Toast.makeText(
                                CreateRoomActivity.this,
                                getString(R.string.error_creating_room),
                                Toast.LENGTH_SHORT
                        ).show();
                    }
                }
        );
    }
}

For now, after successfully creating we just finish our activity. We will implement entering the chat room right away after creation later.

7. Let’s test it out!

1. Launch your app.

2. Enter a room name and click the done icon your menu.

3. For now, it will just finish() our CreateRoomActivity. To verify that a chat room was created just head over to your Firebase project console and you should see your chat room created! 😮🎉

8. Review

As a user,
When I create a new room,
I want to be able to enter the room name
  • Display a field where a user can enter the room name
  • User should not be able to create a room with an empty name
  • Display an error message if user attempts to create a room with an empty name

Display a field where a user can enter the room name
User should not be able to create a room with an empty name
Display an error message if user attempts to create a room with an empty name

Play around with this Activity. Change colors, or instead of menu use buttons, or add more fields if you like.

We don’t want them to go back to the chat rooms screen right after they created their chat room right? We should let them enter their chat room right away.