Abdullah Alshawa
Abdullah Alshawa

Reputation: 1

Google FireBase not storing chat messages in the real-time database?

Explanation: https://github.com/aalshawa97/ImamFinder

Line 48 is throwing an exception when trying to retrieve the user: val fromUser = intent.extras?.get("fromUser") as com.example.detailapplication.User

My FireBase API is enabled. Could you please let me know the steps to fix this problem? Thank you!

P.S. I am testing on a Google Pixel 2 API 28 and Samsung Galaxy 8+.

Code:

package com.example.detailapplication

import android.content.ContentValues
import android.os.Bundle
import android.util.Base64
import android.util.Log
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import android.widget.ListView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import com.example.detailapplication.ChatActivity.AESEncyption.encrypt
import com.firebase.ui.auth.data.model.User
import com.firebase.ui.firestore.FirestoreRecyclerOptions
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.Query
import com.google.firebase.firestore.SetOptions
import java.security.NoSuchAlgorithmException
import javax.crypto.Cipher
import javax.crypto.SecretKey
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.PBEKeySpec
import javax.crypto.spec.SecretKeySpec

open class ChatActivity: AppCompatActivity() {
    lateinit var editText: EditText
    lateinit var listView: ListView
    private var rootRef: FirebaseFirestore? = null
    private var fromUid: String? = ""
    private var adapter: MessageAdapter? = null
    private lateinit var recycler_view  : RecyclerView
    lateinit var edit_text :EditText
    fun byteArrayOfInts(vararg ints: Int) = ByteArray(ints.size) { pos -> ints[pos].toByte() }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_chat)
        supportActionBar!!.setDisplayHomeAsUpEnabled(true)

        try {
            val fromUser = intent.extras?.get("fromUser") as com.example.detailapplication.User

            fromUid = fromUser.uid
            var fromRooms = fromUser.rooms
            val toUser = intent.extras?.get("toUser") as com.example.detailapplication.User
            val toUid = toUser.uid
            var toRooms = toUser.rooms

            var roomId = intent.extras?.get("roomId") as String

            if (roomId == "noRoomId") {
                roomId = rootRef!!.collection("messages").document().id
                if (fromRooms != null) {
                    for ((key, _) in fromRooms) {
                        if (toRooms != null) {
                            if (toRooms.contains(key)) {
                                roomId = key
                            }
                        }
                    }
                }
            }

            val button = findViewById<Button>(R.id.button)

            button.setOnClickListener {
                if (fromRooms == null) {
                    fromRooms = mutableMapOf()
                }
                fromRooms!![roomId] = true
                fromUser.rooms = fromRooms
                rootRef!!.collection("users").document(fromUid!!).set(fromUser, SetOptions.merge())
                rootRef!!.collection("contacts").document(toUid).collection("userContacts").document(fromUid!!).set(fromUser, SetOptions.merge())
                rootRef!!.collection("rooms").document(toUid).collection("userRooms").document(roomId).set(fromUser, SetOptions.merge())

                if (toRooms == null) {
                    toRooms = mutableMapOf()
                }
                toRooms!![roomId] = true
                toUser.rooms = toRooms
                rootRef!!.collection("users").document(toUid).set(toUser, SetOptions.merge())
                rootRef!!.collection("contacts").document(fromUid!!).collection("userContacts").document(toUid).set(toUser, SetOptions.merge())
                rootRef!!.collection("rooms").document(fromUid!!).collection("userRooms").document(roomId).set(toUser, SetOptions.merge())

                val messageText = edit_text.text.toString()
                val message = MessageChat(messageText, fromUid!!)
                rootRef!!.collection("messages").document(roomId).collection("roomMessages").add(message)
                edit_text.text.clear()
            }

            val query = rootRef!!.collection("messages").document(roomId).collection("roomMessages").orderBy("sentAt", Query.Direction.ASCENDING)
            val options = FirestoreRecyclerOptions.Builder<MessageChat>().setQuery(query, MessageChat::class.java).build()
            adapter = MessageAdapter(options)
            recycler_view.adapter = adapter

            title = toUser.userName

            //Testing RSA
            encrypt("This is secret!")

            try {
                //cipher = Cipher.getInstance("RSA")
                val keyBytes = byteArrayOfInts(0xA1, 0x2E, 0x38, 0xD4, 0x89, 0xC3)
                val secretKey: SecretKey = SecretKeySpec(keyBytes, "AES")
                //cipher.init()
                //decipher = Cipher.getInstance("AES")
            }
            catch(e: NoSuchAlgorithmException)
            {
                e.printStackTrace()
            }

            editText = findViewById(R.id.edit_text)
            listView = findViewById(R.id.list_viw)
            rootRef = FirebaseFirestore.getInstance()
            recycler_view = findViewById(R.id.recycler_view)
        }
        catch (e : java.lang.Exception)
        {
            Log.d(ContentValues.TAG, "onCreate: exception thrown when getting user")
        }

        //secretKeySpec = new SecreyKeySpec()
    }

    object AESEncyption {

        const val secretKey = "tK5UTui+DPh8lIlBxya5XVsmeDCoUl6vHhdIESMB6sQ="
        const val salt = "QWlGNHNhMTJTQWZ2bGhpV3U=" // base64 decode => AiF4sa12SAfvlhiWu
        const val iv = "bVQzNFNhRkQ1Njc4UUFaWA==" // base64 decode => mT34SaFD5678QAZX

        fun encrypt(strToEncrypt: String) :  String?
        {
            try
            {
                Log.d("ChatActivity", "Before encrypting: RSA " + strToEncrypt)

                val ivParameterSpec = IvParameterSpec(android.util.Base64.decode(iv, android.util.Base64.DEFAULT))

                val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")
                val spec =  PBEKeySpec(secretKey.toCharArray(), android.util.Base64.decode(salt, android.util.Base64.DEFAULT), 10000, 256)
                val tmp = factory.generateSecret(spec)
                val secretKey =  SecretKeySpec(tmp.encoded, "AES")

                val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding")
                cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec)
                //Toast.makeText(this, "Opening chat", Toast.LENGTH_LONG).show()
                Log.d("ChatActivity", "Encrypted: RSA " + android.util.Base64.encodeToString(cipher.doFinal(strToEncrypt.toByteArray(Charsets.UTF_8)), android.util.Base64.DEFAULT))

                //[email protected](new Intent(this@ChatActivitiy, RSA::class.java))
                //Toast.makeText(this, "Testing encryption with RSA", Toast.LENGTH_LONG).show()
                return android.util.Base64.encodeToString(cipher.doFinal(strToEncrypt.toByteArray(Charsets.UTF_8)), android.util.Base64.DEFAULT)
            }
            catch (e: Exception)
            {
                println("Error while encrypting: $e")
            }
            return null
        }

        fun decrypt(strToDecrypt : String) : String? {
            try
            {

                /*
                val ivParameterSpec =  IvParameterSpec(android.util.Base64.(iv, android.util.Base64.DEFAULT))

                val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")
                val spec =  PBEKeySpec(secretKey.toCharArray(), android.util.Base64.decode(salt, android.util.Base64.DEFAULT), 10000, 256)
                val tmp = factory.generateSecret(spec);
                val secretKey =  SecretKeySpec(tmp.encoded, "AES")

                val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
                cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
                return  String(cipher.doFinal(android.util.Base64.decode(strToDecrypt, android.util.Base64.DEFAULT)))
                */
            }
            catch (e : Exception) {
                println("Error while decrypting: $e");
            }
            return null
        }
    }

    inner class MessageAdapter internal constructor(options: FirestoreRecyclerOptions<MessageChat>) : com.firebase.ui.firestore.FirestoreRecyclerAdapter<MessageChat, MessageAdapter.MessageViewHolder>(options) {
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
            return if (viewType == R.layout.item_message_to) {
                val view = LayoutInflater.from(parent.context).inflate(R.layout.item_message_to, parent, false)
                MessageViewHolder(view)
            } else {
                val view = LayoutInflater.from(parent.context).inflate(R.layout.item_message_from, parent, false)
                MessageViewHolder(view)
            }
        }

        inner class MessageViewHolder internal constructor(private val view: View) :
            RecyclerView.ViewHolder(view) {
            internal fun setMessage(messageChat: MessageChat) {
                val textView = view.findViewById<TextView>(R.id.text_view)
                //We can encrypt here...
                textView.text = messageChat.messageText
            }
        }

        /**
         * @param model the model object containing the data that should be used to populate the view.
         * @see .onBindViewHolder
         */
        override fun onBindViewHolder(
            holder: MessageViewHolder,
            position: Int,
            model: MessageChat
        ) {
            TODO("Not yet implemented")
        }

        /*
         inner class MessageAdapter internal constructor(options: FirestoreRecyclerOptions<MessageChat>) : com.firebase.ui.firestore.FirestoreRecyclerAdapter<MessageChat, MessageViewHolder>(options) {
             override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
                 return if (viewType == R.layout.item_message_to) {
                     val view = LayoutInflater.from(parent.context).inflate(R.layout.item_message_to, parent, false)
                     MessageViewHolder(view)
                 } else {
                     val view = LayoutInflater.from(parent.context).inflate(R.layout.item_message_from, parent, false)
                     MessageViewHolder(view)
                 }
             }

             override fun onBindViewHolder(holder: MessageViewHolder, position: Int, model: MessageChat) {
                 holder.setMessage(model)
             }


             override fun getItemViewType(position: Int): Int {
                 return if (fromUid != getItem(position).fromUid) {
                     R.layout.item_message_to
                 } else {
                     R.layout.item_message_from
                 }
             }


             override fun onDataChanged() {
                 recycler_view.layoutManager?.scrollToPosition(itemCount - 1)
             }
         }


        private val encryptionKey: IntArray = intArrayOf(5, 115, 51, 86, 105, 4, -31, -23, -60, 80, 17, 20, 3, -105, -53)
        private var cipher: Cipher = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>")
        //var d: Decipher = null
        //private SecretKeySpec secretKeySpec

        object AESEncyption {

            const val secretKey = "tK5UTui+DPh8lIlBxya5XVsmeDCoUl6vHhdIESMB6sQ="
            const val salt = "QWlGNHNhMTJTQWZ2bGhpV3U=" // base64 decode => AiF4sa12SAfvlhiWu
            const val iv = "bVQzNFNhRkQ1Njc4UUFaWA==" // base64 decode => mT34SaFD5678QAZX

            fun encrypt(strToEncrypt: String) :  String?
            {
                try
                {
                    Log.d("ChatActivity", "Before encrypting: RSA " + strToEncrypt)

                    val ivParameterSpec = IvParameterSpec(Base64.decode(iv, Base64.DEFAULT))

                    val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")
                    val spec =  PBEKeySpec(secretKey.toCharArray(), Base64.decode(salt, Base64.DEFAULT), 10000, 256)
                    val tmp = factory.generateSecret(spec)
                    val secretKey =  SecretKeySpec(tmp.encoded, "AES")

                    val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding")
                    cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec)
                    //Toast.makeText(this, "Opening chat", Toast.LENGTH_LONG).show()
                    Log.d("ChatActivity", "Encrypted: RSA " + android.util.Base64.encodeToString(cipher.doFinal(strToEncrypt.toByteArray(Charsets.UTF_8)), android.util.Base64.DEFAULT))

                    //[email protected](new Intent(this@ChatActivitiy, RSA::class.java))
                    //Toast.makeText(this, "Testing encryption with RSA", Toast.LENGTH_LONG).show()
                    return android.util.Base64.encodeToString(cipher.doFinal(strToEncrypt.toByteArray(Charsets.UTF_8)), android.util.Base64.DEFAULT)
                }
                catch (e: Exception)
                {
                    println("Error while encrypting: $e")
                }
                return null
            }

            fun decrypt(strToDecrypt : String) : String? {
                try
                {

                    /*
                    val ivParameterSpec =  IvParameterSpec(android.util.Base64.(iv, android.util.Base64.DEFAULT))

                    val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")
                    val spec =  PBEKeySpec(secretKey.toCharArray(), android.util.Base64.decode(salt, android.util.Base64.DEFAULT), 10000, 256)
                    val tmp = factory.generateSecret(spec);
                    val secretKey =  SecretKeySpec(tmp.encoded, "AES")

                    val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
                    cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
                    return  String(cipher.doFinal(android.util.Base64.decode(strToDecrypt, android.util.Base64.DEFAULT)))
                    */
                }
                catch (e : Exception) {
                    println("Error while decrypting: $e");
                }
                return null
            }
        }

        fun byteArrayOfInts(vararg ints: Int) = ByteArray(ints.size) { pos -> ints[pos].toByte() }

        inner class MessageViewHolder internal constructor(private val view: View) : RecyclerView.ViewHolder(view) {
            internal fun setMessage(messageChat: MessageChat) {
                val textView = view.findViewById<TextView>(R.id.text_view)
                //We can encrypt here...
                textView.text = messageChat.messageText
            }
        }

        inner class MessageAdapter internal constructor(options: FirestoreRecyclerOptions<MessageChat>) : com.firebase.ui.firestore.FirestoreRecyclerAdapter<MessageChat, MessageViewHolder>(options) {
            override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
                return if (viewType == R.layout.item_message_to) {
                    val view = LayoutInflater.from(parent.context).inflate(R.layout.item_message_to, parent, false)
                    MessageViewHolder(view)
                } else {
                    val view = LayoutInflater.from(parent.context).inflate(R.layout.item_message_from, parent, false)
                    MessageViewHolder(view)
                }
            }

            override fun onBindViewHolder(holder: MessageViewHolder, position: Int, model: MessageChat) {
                holder.setMessage(model)
            }

            override fun getItemViewType(position: Int): Int {
                return if (fromUid != getItem(position).fromUid) {
                    R.layout.item_message_to
                } else {
                    R.layout.item_message_from
                }
            }

            override fun onDataChanged() {
                recycler_view.layoutManager?.scrollToPosition(itemCount - 1)
            }
        }

        override fun onOptionsItemSelected(menuItem: MenuItem): Boolean {
            return when (menuItem.itemId) {
                android.R.id.home -> {
                    finish()
                    true
                }

                else -> super.onOptionsItemSelected(menuItem)
            }
        }

        override fun onStart() {
            super.onStart()

            if (adapter != null) {
                adapter!!.startListening()
            }
        }

        override fun onStop() {
            super.onStop()

            if (adapter != null) {
                adapter!!.stopListening()
            }
        }

            inner class MessageViewHolder internal constructor(private val view: View) : RecyclerView.ViewHolder(view) {
            internal fun setMessage(messageChat: MessageChat) {
                val textView = view.findViewById<TextView>(R.id.text_view)
                //We can encrypt here...
                textView.text = messageChat.messageText
            }
        }
         */
    }

}

Upvotes: 0

Views: 75

Answers (0)

Related Questions