Firebase Chat

MainActivity

import android.graphics.drawable.BitmapDrawable
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.ktx.auth
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.ValueEventListener
import com.google.firebase.database.ktx.database
import com.google.firebase.ktx.Firebase
import com.neco_desarrollo.fbchat.databinding.ActivityMainBinding
import com.squareup.picasso.Picasso
import java.util.ArrayList

class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
lateinit var auth: FirebaseAuth
lateinit var adapter: UserAdapter

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
auth = Firebase.auth
setUpActionBar()
val database = Firebase.database
val myRef = database.getReference("messages")
binding.bSend.setOnClickListener {
myRef.child(myRef.push().key ?: "blabla").setValue(User(auth.currentUser?.displayName, binding.edMessage.text.toString()))
}
onChangeListener(myRef)
initRcView()

}

private fun initRcView() = with(binding){
adapter = UserAdapter()
rcView.layoutManager = LinearLayoutManager(this@MainActivity)
rcView.adapter = adapter
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main_menu, menu)
return super.onCreateOptionsMenu(menu)
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
if(item.itemId == R.id.sign_out){
auth.signOut()
finish()
}
return super.onOptionsItemSelected(item)
}

private fun onChangeListener(dRef: DatabaseReference){
dRef.addValueEventListener(object : ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
val list = ArrayList<User>()
for(s in snapshot.children){
val user = s.getValue(User::class.java)
if(user != null)list.add(user)
}
adapter.submitList(list)
}

override fun onCancelled(error: DatabaseError) {

}

})
}

private fun setUpActionBar(){
val ab = supportActionBar
Thread{
val bMap = Picasso.get().load(auth.currentUser?.photoUrl).get()
val dIcon = BitmapDrawable(resources, bMap)
runOnUiThread {
ab?.setDisplayHomeAsUpEnabled(true)
ab?.setHomeAsUpIndicator(dIcon)
ab?.title = auth.currentUser?.displayName
}
}.start()

}
}

SignInActivity

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInClient
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.api.ApiException
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.GoogleAuthProvider
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase
import com.neco_desarrollo.fbchat.databinding.ActivitySignInBinding

class SignInAct : AppCompatActivity() {
lateinit var launcher: ActivityResultLauncher<Intent>
lateinit var auth: FirebaseAuth
lateinit var binding: ActivitySignInBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySignInBinding.inflate(layoutInflater)
setContentView(binding.root)
auth = Firebase.auth
launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
val task = GoogleSignIn.getSignedInAccountFromIntent(it.data)
try {
val account = task.getResult(ApiException::class.java)
if(account != null){
firebaseAuthWithGoogle(account.idToken!!)
}
} catch (e: ApiException){
Log.d("MyLog","Api exception")
}
}
binding.bSignIn.setOnClickListener {
signInWithGoogle()
}
checkAuthState()
}

private fun getClient(): GoogleSignInClient{
val gso = GoogleSignInOptions
.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build()
return GoogleSignIn.getClient(this, gso)
}

private fun signInWithGoogle(){
val signInClient = getClient()
launcher.launch(signInClient.signInIntent)
}

private fun firebaseAuthWithGoogle(idToken: String){
val credential = GoogleAuthProvider.getCredential(idToken, null)
auth.signInWithCredential(credential).addOnCompleteListener {
if(it.isSuccessful){
Log.d("MyLog","Google signIn done")
checkAuthState()
} else {
Log.d("MyLog","Google signIn error")
}
}
}

private fun checkAuthState(){
if(auth.currentUser != null){
val i = Intent(this, MainActivity::class.java)
startActivity(i)
}
}

}

User

data class User(
val name: String? = null,
val message: String? = null
)

UserAdapter

import android.view.LayoutInflater
import android.view.ViewGroup

import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.neco_desarrollo.fbchat.databinding.UserListItemBinding

class UserAdapter : ListAdapter<User, UserAdapter.ItemHolder>(ItemComparator()) {

class ItemHolder(private val binding: UserListItemBinding) : RecyclerView.ViewHolder(binding.root){
fun bind(user: User) = with(binding){
message.text = user.message
userName.text = user.name
}
companion object{
fun create(parent: ViewGroup): ItemHolder{
return ItemHolder(UserListItemBinding
.inflate(LayoutInflater.from(parent.context), parent, false))
}
}
}

class ItemComparator : DiffUtil.ItemCallback<User>(){
override fun areItemsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem == newItem
}

override fun areContentsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem == newItem
}

}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemHolder {
return ItemHolder.create(parent)
}

override fun onBindViewHolder(holder: ItemHolder, position: Int) {
holder.bind(getItem(position))
}
}

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"
tools:context=".MainActivity">

<Button
android:id="@+id/bSend"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="Send"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />

<EditText
android:id="@+id/edMessage"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Message"
android:inputType="textPersonName"
app:layout_constraintBottom_toTopOf="@+id/bSend"
app:layout_constraintEnd_toEndOf="@+id/bSend"
app:layout_constraintStart_toStartOf="@+id/bSend" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rcView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/edMessage"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_sign_in.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"
tools:context=".SignInAct">

<Button
android:id="@+id/bSignIn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="google signin"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

user_list_item.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"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:backgroundTint="#C9FACB"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dp">

<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:textColor="@color/black" />

<TextView
android:id="@+id/userName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="12sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

main_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

<item
android:title="Sign Out"
android:id="@+id/sign_out"/>
</menu>

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *