Previously, I had given this prompt to you:
I have an Android app that uses Firebase database. I want to add a functionality (a different Class, activity) for the user to message me (the developar). How should I do it? There is a button in the side menu called Message Me. Can you code the .xml and Java (including the firebase integration) for this function? Or maybe if you can solve the problem that way, it’s okay if the app behind the interface in the background without the user knowing sends an email to me. And if we were to use Firebase to store the message, how would I be notified that I have a new message?

And you've given me this solution:
Sure, below are basic examples of how you can create an activity in Android to send a message from a user to the developer, using Firebase as the backend. This approach involves saving user messages into the Firebase Realtime Database.

1. First, you need to create an activity with a layout to input the message.
Here is a simple layout XML (activity_message_me.xml):

<RelativeLayout xmlns:android=“http://schemas.android.com/apk/res/android”
    android:layout_width=“match_parent”
    android:layout_height=“match_parent”
    android:padding=“16dp”>

    <EditText
        android:id=“@+id/messageEditText”
        android:layout_width=“match_parent”
        android:layout_height=“wrap_content”
        android:hint=“Enter your message here”/>

    <Button
        android:id=“@+id/sendMessageButton”
        android:layout_width=“wrap_content”
        android:layout_height=“wrap_content”
        android:text=“Send”
        android:layout_below=“@id/messageEditText”
        android:layout_marginTop=“16dp”/>

</RelativeLayout>


2. Then, in your activity class (MessageMeActivity.java), you need to handle button click to send the message to Firebase.
Make sure to include Google’s Firebase libraries in your project’s build.gradle file.

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.DocumentReference;

import java.util.HashMap;
import java.util.Map;

public class MessageMeActivity extends AppCompatActivity {

    private EditText messageEditText;
    private Button sendMessageButton;
    private FirebaseFirestore firestoreDB;

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

    messageEditText = findViewById(R.id.messageEditText);
    sendMessageButton = findViewById(R.id.sendMessageButton);

    // Initialize Firestore
    firestoreDB = FirebaseFirestore.getInstance();

    sendMessageButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            sendMessage();
        }
    });
}

private void sendMessage() {
    String messageText = messageEditText.getText().toString().trim();
    if (!messageText.isEmpty()) {
        // Create a new message with a Map
        Map<String, Object> message = new HashMap<>();
        message.put(“content”, messageText);
        // You may want to add other relevant details like timestamp and senderId

        // Add a new document with a generated id.
        firestoreDB.collection(“messages”)
                .add(message)
                .addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
                    @Override
                    public void onSuccess(DocumentReference documentReference) {
                        // Clear the field after the message is sent
                        messageEditText.setText(“”);
                        // Handle success case
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        // Handle error case
                    }
                });
    }
}
}



For Firestore, you don’t need to define a node like in the Realtime Database. Instead, you create a collection (e.g., “messages”) where each document will represent a message. Each document will contain the fields we’ve added to our message Map.

To get notified of new messages, you can still use Cloud Functions, but they will be written to work with Firestore triggers. Here’s an example in JavaScript using Node.js (index.js for Firebase Cloud Functions):

const functions = require(‘firebase-functions’);
const admin = require(‘firebase-admin’);
admin.initializeApp();

const nodemailer = require(‘nodemailer’);
// Configure your Nodemailer transporter here

// Function to send email upon new Firestore document creation
exports.sendEmailOnNewMessage = functions.firestore
.document(‘messages/{messageId}’)
.onCreate((snapshot, context) => {
    const messageData = snapshot.data();
    const messageContent = messageData.content; // Edit this according to your message structure

    // Set up your email content here
    const mailOptions = {
        // …your mail options
        subject: ‘New Message from App’,
        text: New message received: ${messageContent}
        // …other options
    };
    
    // Send email logic (similar to previous example)
});


Remember to set up Nodemailer as you did before and consider using environment variables or another secure method to handle your email server credentials. Deploy this function and it will notify you whenever a new document/message is created in your Firestore “messages” collection.

Please ensure that you’ve set up your Firestore database rules correctly to allow for the expected read/write access by the client and the Firebase Functions.




I haven't set up cloud functions yet. How can I set a character limit to the message in the app? And how can I add a counter to the UI, so user knows how many character is left. Eg. let's set the character limit to be 4000 characters. And also give the user a popup when the message has been sent successfully that the user needs to OK (confirm).