Kotlin ChatApp doesnt show messages - firebase

I simply followed this video: https://www.youtube.com/watch?v=8Pv96bvBJL4&ab_channel=GeeksforGeeks
Untill the end it was working fine. At the end, chat application started to crash when you try to text someone. I simply added push() method.
Now it stopped crashing but I am not able to see the messages. Firebase`s database is perfectly fine but I couldnt make it seen in the app. Sorry for the inexperience. I am new in Kotlin and this is the first time I am a asking a question. Thanks for all of the support.
Here is the code of Chat Activity (In my opinion messageList never adds a thing.. So messages arent showed in the app. But added to database perfectly):
package com.biointel.biointelchatapplication
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.EditText
import android.widget.ImageView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.*
import com.google.firebase.ktx.Firebase
class ChatActivity : AppCompatActivity() {
private lateinit var chatRecyclerView: RecyclerView
private lateinit var messageBox: EditText
private lateinit var sendButton: ImageView
private lateinit var messageAdapter: MessageAdapter
private lateinit var messageList: ArrayList<Message>
private lateinit var mDbRef: DatabaseReference
var receiverRoom: String? = null
var senderRoom: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chat)
val name = intent.getStringExtra("name")
val receiverUid = intent.getStringExtra("uid")
val senderUid = FirebaseAuth.getInstance().currentUser?.uid
mDbRef = FirebaseDatabase.getInstance().getReference()
senderRoom = receiverUid + senderUid
receiverRoom = senderUid + receiverUid
supportActionBar?.title = name
chatRecyclerView = findViewById(R.id.chatRecyclerView)
messageBox = findViewById(R.id.messageBox)
sendButton = findViewById(R.id.sentButton)
messageList = ArrayList()
messageAdapter = MessageAdapter(this,messageList)
chatRecyclerView.layoutManager = LinearLayoutManager(this)
chatRecyclerView.adapter = messageAdapter
// Logic for adding to recyclerView
mDbRef.child("chats").child(senderRoom!!).child("messages").push()
.addValueEventListener(object: ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
//messageList.clear()
for(postSnapshot in snapshot.children){
val message = postSnapshot.getValue(Message::class.java)
messageList.add(message!!)
}
messageAdapter.notifyDataSetChanged()
}
override fun onCancelled(error: DatabaseError) {
}
})
sendButton.setOnClickListener{
// adding the message to database
val message = messageBox.text.toString()
val messageObject = Message(message, senderUid)
mDbRef.child("chats").child(senderRoom!!).child("messages")
.setValue(messageObject).addOnSuccessListener {
mDbRef.child("chats").child(receiverRoom!!).child("messages")
.setValue(messageObject)
}
messageBox.setText("")
}
}
}

Related

Google SignIn with Android (kotlin) but NO pop up window to LogIn

I've been working recently in one of my projects in Android (kotlin), and in my LogIn page I was trying to implement the Google Sign In, for my surprise I was able to log in, but I can never see the typical pop up window that pops when you press the button to sign in (in my android app), it directly redirects me into gmail sign in in the browser, and then that's how I'm able to sign in, but never get to see the pop up.
I've tried changing some of the deprecated function, but never got anything (startActivityForResult)!
`This is my code:
package com.example.googlesignin
import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Button import android.widget.Toast import com.google.android.gms.auth.api.signin.GoogleSignIn import com.google.android.gms.auth.api.signin.GoogleSignInAccount import com.google.android.gms.auth.api.signin.GoogleSignInOptions import com.google.android.gms.common.api.ApiException import com.google.android.material.snackbar.Snackbar import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.GoogleAuthProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.tasks.await import kotlinx.coroutines.withContext
const val REQUEST_CODE_SIGNIN = 21 class MainActivity : AppCompatActivity() {
lateinit var auth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
auth = FirebaseAuth.getInstance()
val googleButton = findViewById<Button>(R.id.googleButton)
googleButton.setOnClickListener {
val options = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id_googleSignIn))
.requestEmail()
.build()
val signInClient = GoogleSignIn.getClient(this,options)
signInClient.signInIntent.also {
this.startActivityForResult(it, REQUEST_CODE_SIGNIN)
}
}
}
private fun googleAuthForFirebase(account: GoogleSignInAccount) {
val credentials = GoogleAuthProvider.getCredential(account.idToken,null)
CoroutineScope(Dispatchers.IO).launch {
try
{
auth.signInWithCredential(credentials).await()
withContext(Dispatchers.Main)
{
Toast.makeText(this#MainActivity,"Successfully Logged In",Toast.LENGTH_LONG).show()
}
}catch (e: java.lang.Exception)
{
withContext(Dispatchers.Main)
{
Toast.makeText(this#MainActivity,e.message,Toast.LENGTH_LONG).show()
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == REQUEST_CODE_SIGNIN)
{
val account = GoogleSignIn.getSignedInAccountFromIntent(data).result
account?.let {
googleAuthForFirebase(it)
}
}
}
}
PD: I have only this activity and I have the xml of main_activity containing only one button to sign in. And I've done all the correct steps linking my project to firebase, if not I wouldn't be able to log in with my gmail account, but no pop up window.

I am trying to edit a thought in my thoughts app. I am not able to update it

package com.example.demo
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.android.synthetic.main.activity_update_thought.*
class UpdateThoughtActivity : AppCompatActivity() {
private lateinit var thoughtDocumentId: String
lateinit var commentDocId: String
lateinit var thoughtTxt: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_update_thought)
thoughtDocumentId = intent.getStringExtra(THOUGHT_DOC_ID_EXTRA)!!
commentDocId = intent.getStringExtra(COMMENT_USER_ID_EXTRA)!!
thoughtTxt = intent.getStringExtra(COMMENT_TXT_EXTRA)!!
updateThoughtTxt.setText(thoughtTxt)
}
fun updateThoughtClicked(view: View) {
FirebaseFirestore.getInstance().collection(THOUGHTS_REF).document(thoughtDocumentId)
.update(THOUGHT_TXT, updateThoughtTxt.text.toString())
.addOnSuccessListener {
hideKeyboard()
finish()
}
.addOnFailureListener { exception ->
Log.e("Exception", "Could not update thought: ${exception.localizedMessage}")
}
}
private fun hideKeyboard() {
val inputManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
if (inputManager.isAcceptingText) {
inputManager.hideSoftInputFromWindow(currentFocus!!.windowToken,0)
}
}
}
Here I am trying to update the thought. I am not able to update it.When I click on update button during runtime. I see this error.
E Could not update thought: NOT_FOUND: No document to update: projects/fir-ee876/databases/(default)/documents/thoughts/null
I did for comments activity the same thing. It works fine. I am getting problem only for this.
Can you please help me with this?
I am trying to edit the thought and when I click on edit option it navigates to a new activity. In the new activity I want to update the thought and click on update button.When I click on that button the thought must be updated and must be displayed. When I tried this I am getting this error.
E Could not update thought: NOT_FOUND: No document to update: projects/fir-ee876/databases/(default)/documents/thoughts/null

unresolved reference in Firestore UI and display it

am using Firebase UI for displaying data in recyler view from Firestore.And i wanna that this query will display on my app but i can't add this reference. Can anyone please guide me on this?
i do my app witch a tutorial but its expired and i try to do and lern a lot of my self but with this i cant do enything
MainACtivity.kt
package com.example.nfc
import android.content.Intent
import android.os.Bundle
import android.view.*
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.ktx.auth
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import com.firebase.ui.firestore.FirestoreRecyclerAdapter
import com.firebase.ui.firestore.FirestoreRecyclerOptions
data class User(
val displayName: String = "",
val emojis: String = ""
)
class UserViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
class MainActivity : AppCompatActivity() {
private val db = Firebase.firestore
private lateinit var auth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
auth = Firebase.auth
// Query the users collection
val query = db.collection("users")
val options = FirestoreRecyclerOptions.Builder<User>().setQuery(query, User::class.java)
.setLifecycleOwner(this).build()
val adapter = object: FirestoreRecyclerAdapter<User, UserViewHolder>(options) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = LayoutInflater.from(this#MainActivity).inflate(android.R.layout.simple_list_item_2,parent,false)
return UserViewHolder(view)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int, model: User) {
val tvName: TextView=holder.itemView.findViewById(android.R.id.text1)
val tvEmojis: TextView=holder.itemView.findViewById(android.R.id.text2)
tvName.text = model.displayName
tvEmojis.text = model.emojis
}
}
uzytkownicy.adapter = adapter
uzytkownicy.layoutManager = LinearLayoutManager(this)
//end
val addButton = findViewById(R.id.addButton)as Button
addButton.setOnClickListener{
val intent = Intent(this, addtrasa::class.java)
startActivity(intent)
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/szarytlo"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvUsers"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
and thats my error
enter image description here
You do not assign an object to uzytkownicy anywhere in your MainActivity, so it is not clear to the compiler what type of object it is meant to be. From the context of the code, it looks like you mean for it to be a RecyclerView, and you probably want to use the one in activity_main.xml. If so, you would need to assign it as such:
val uzytkownicy: RecyclerView = findViewById(R.id.rvUsers)
Then you can go ahead and use that reference to set the adapter and layout manager as you're already attempting to do.

Passing values from one fragment to another

I'm working in Kotlin and using retrofit. I have a recycler view, which consists of cards. Each card has a typeName and an image associated to it which for now I have added statically using dataclass. Now, I need to pass the typeName only from the CategoryFragment to the LocationFragment once the user clicks on a particular card. And at the LocationFragment I want to check the latitude, longitude and typeName from the database if it already exists.
Here's my code for the dataclass of Category:
data class Category_dataclass ( val category_image : Int , val typeName: String)
Here's my code for the CategoryFragment:
package com.example.atry.MakeComplaint
import android.content.Context
import android.net.Uri
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.atry.History.Complaints
import com.example.atry.History.MyComplainRecyclerViewAdapter
import com.example.atry.R
import kotlinx.android.synthetic.main.existing_complaint_popup.*
class CategoryFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val v = inflater.inflate(R.layout.fragment_category, container, false)
val recyclerView = v.findViewById(R.id.category_list) as RecyclerView
recyclerView.apply {
layoutManager = GridLayoutManager(context!!, 2)
}
//creating an arraylist to store category using the data class user
val category = ArrayList<Category_dataclass>()
//adding some dummy data to the list of categories
category.add(Category_dataclass((R.drawable.trash) , "Water"))
category.add(Category_dataclass((R.drawable.fire) , "Sewerage"))
category.add(Category_dataclass((R.drawable.dustbin) , "load"))
//creating our adapter
val adapter = CategoryRecyclerViewAdapter(category)
//now adding the adapter to recyclerview
recyclerView.adapter = adapter
// Inflate the layout for this fragment
return v
}
}
Here's the CategoryRecyclerViewAdapter:
package com.example.atry.MakeComplaint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import com.example.atry.History.ComplaintDetailsFragment
import com.example.atry.History.Complaints
import com.example.atry.MakeComplaint.Category_dataclass
import com.example.atry.MakeComplaint.CategoryRecyclerViewAdapter
import com.example.atry.R
import java.util.*
import kotlin.collections.ArrayList
class CategoryRecyclerViewAdapter(val categoryList: ArrayList<Category_dataclass>) : RecyclerView.Adapter<CategoryRecyclerViewAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryRecyclerViewAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.fragment_category_single, parent, false)
return ViewHolder(v)
}
//this method is binding the data on the list
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindItems(categoryList[position])
holder.mView.setOnClickListener{view->
val lFragment = LocationFragment()
val oldFragment = CategoryFragment()
val manager = (holder.mView.context as AppCompatActivity).supportFragmentManager
val transaction = manager.beginTransaction()
transaction.replace(
R.id.first_screen_of_makecomplaint,
lFragment
) // give your fragment container id in first parameter
transaction.show(lFragment)
transaction.hide(oldFragment)
transaction.isAddToBackStackAllowed
transaction.addToBackStack(oldFragment.fragmentManager.toString()) // if written, this transaction will be added to backstack
transaction.commit()
}
}
//this method is giving the size of the list
override fun getItemCount(): Int {
return categoryList.size
}
inner class ViewHolder(val mView : View) : RecyclerView.ViewHolder(mView) {
fun bindItems(cat:Category_dataclass) {
val imageViewName = mView.findViewById(R.id.category_image) as ImageView
val textViewtext = mView.findViewById(R.id.category_text) as TextView
imageViewName.setImageResource(cat.category_image)
textViewtext.text = cat.typeName
}
}
}
And this is my retrofit:
//to check existing complaint
#GET("api/existingComplain")
#FormUrlEncoded
fun checkExistingComplain(#Query("typeName") typeName:String,
#Query("longitude") longitude:String,
#Query("latitude") latitude:String):Observable<Observables.checkExistingResult>
I've created and object where i stored the dataclass which will return the following:
data class checkExistingResult(val description:String , val Complain:String)
if the typeName and location already exists in the database I want the description and Complain to be displayed on a material styled dialog.
You can try this:
1st Step:-
val dashboard = "Dashboard"
take variable like this you can take it's name as your fragment name so page name you can check like this MainActivity().dashboard
Now, 2nd Step:-
create one class and write function like this in that class
fun openPage(
activity: Activity,
pagename: String?, model: PaymentDetails
) {
when (pagename) {
MainActivity().dashboard -> {
val mfragment = DashboardFragment()
(activity as MainActivity).fragmentManager.beginTransaction()
.replace(R.id.nav_host, mfragment).commit()
val a = Bundle()
a.putSerializable("model", model)
mfragment.arguments = a
}
}
}
take key value pair as I take my whole model and key is model in my code you can write any thing.
3rd Step:-
Make your model Serializable
4th Step:- When you are adding your values into model add details and add your model for method in which you want to use these values like following
val payment = PaymentDetails(
type,
price,
name,
id,
)
paymentData!!.add(payment)
CustomMethods().openPagePaymentDetails(
activity!!,
MainActivity().sessionPaymentFragment, payment
)
5th Step:-
Declare and initialise your object with type of your model like following:
//Declare
private var model: PaymentDetails? = null
//initialise
model = arguments!!.getSerializable("model") as PaymentDetails?
And now finally you can access value of previous fragment into your next fragment like this,
var type: String
type = model!!.type
Note:- please do no forgot to make your model class Serializable
Hope so it will help you.

Flex 4.5 - Custom NativeWindow and problems

I have a class FlexNativeWindow who extends to NativeWindow.
I use this method to create new window on my AIR app.
All works well but some keyboard interraction is not availaible.
For exemple focus arround textinput is not visible.
Key down and up don't work on DropDownList.
TabOrder doesn't work well!
Can you explain Why? Because I'm very desapointed!
Code to create the new window
var wdetcorr:wDetailCorrespondant = new wDetailCorrespondant();
wdetcorr.monIdCorresp = correspDG.selectedItem.crIndex;
var wOptions:NativeWindowInitOptions = new NativeWindowInitOptions();
wOptions.systemChrome = NativeWindowSystemChrome.NONE;
wOptions.transparent = false;
var fnwDetailPatient:FlexNativeWindow = new FlexNativeWindow(wdetcorr, wOptions);
fnwDetailPatient.active();
Code about my custom NativeWindow
package fr.int.ui.windowSkin
{
import flash.display.NativeWindow;
import flash.display.NativeWindowInitOptions;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import mx.core.IUIComponent;
import mx.core.IVisualElement;
import mx.core.IVisualElementContainer;
import mx.core.UIComponent;
import mx.events.*;
import mx.managers.WindowedSystemManager;
[Event(name="creationComplete", type="mx.events.FlexEvent")]
public class FlexNativeWindow extends NativeWindow implements IFlexNativeWindow
{
private var _systemManager:WindowedSystemManager;
private var _content:UIComponent;
private var _window:IVisualElementContainer;
public function FlexNativeWindow(window:IVisualElementContainer, initOptions:NativeWindowInitOptions = null)
{
super(initOptions);
_window = window;
addEventListener(Event.ACTIVATE, windowActivateHandler);
}
public function addElement(control:IVisualElement):void
{
_window.addElement(control);
}
public function removeElement(control:IVisualElement):void
{
_window.removeElement(control);
}
private function windowActivateHandler(event:Event):void
{
event.preventDefault();
event.stopImmediatePropagation();
removeEventListener(Event.ACTIVATE, windowActivateHandler);
if (stage)
{
if (!_systemManager)
_systemManager = new WindowedSystemManager(IUIComponent(_window));
stage.addChild(_systemManager);
dispatchEvent(new FlexEvent(FlexEvent.CREATION_COMPLETE));
stage.addEventListener(Event.RESIZE, windowResizeHandler);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownListener);
}
}
private function keyDownListener (e:KeyboardEvent):void {
if (e.keyCode == Keyboard.ESCAPE) {
stage.nativeWindow.dispatchEvent(new Event("myEventClose", true));
stage.nativeWindow.close();
}
}
private function windowResizeHandler(event:Event):void
{
// prise en compte de la valeur mini
UIComponent(_window).height = stage.stageHeight;
UIComponent(_window).width = stage.stageWidth;
}
}
}
You should implement IFocusManagerContainer in FlexNativeWindow to fix the focus issues.
Here is how to do it in Flash Builder:
Press Ctrl + Shift + T and type in IFocusManagerContainer
Open corresponding file
Implement all declared methods in your class FlexNativeWindow
P.S: However this approach can fail because flex components should be placed inside flex container while NativeWindow is a native class, not a Flex SDK class. I suggest you to use Window class that is a Flex container and already implements IFocusManagerContainer.

Resources