I want to get data from Firebase Firestore subcollection for recyclerView. But I dont know if I write codes correctly or no. I also checked another variant with another collection without any subcollection and I see there I succesfully get data from Firestore. But with subcollection part which is i uploaded it with image below I can not fetch data and my recyclerView is empty.How can i fix that? Thanks in advance
Here is my Firebase Firestore collection
Here is my Firebase Firestore subcollection
And my codes
class Posts : AppCompatActivity(), RecAdapterPosts.ClickListener {
var modalList : ArrayList<ModalImageList> = ArrayList()
private lateinit var binding: PostsBinding
private lateinit var auth: FirebaseAuth
private var userAdapter = RecAdapterPosts(modalList, this)
private var db = Firebase.firestore
private var database: FirebaseFirestore = FirebaseFirestore.getInstance()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = PostsBinding.inflate(layoutInflater)
val view = (binding.root)
setContentView(view)
auth = FirebaseAuth.getInstance()
database = FirebaseFirestore.getInstance()
gridPosts.adapter = userAdapter
gridPosts.layoutManager = GridLayoutManager(this,2)
get_information()
}
private fun get_information() {
val cu = auth.currentUser!!.uid
database.collection("İmagesPosts",).document(cu!!).collection("ImagesList").orderBy("date",
Query.Direction.DESCENDING
).addSnapshotListener { snaphot, exception ->
if (exception != null) {
Toast.makeText(this, exception.localizedMessage, Toast.LENGTH_LONG)
.show()
} else {
if (snaphot != null) {
if (!snaphot.isEmpty) {
val documents = snaphot.documents
modalList.clear()
for (document in documents) {
val imgUrl = document.get("downloadUs") as String
val imgName = document.get("imgName") as String
val download_post = ModalImageList(
imgUrl,
imgName,
)
modalList.add(download_post)
}
}
userAdapter.notifyDataSetChanged()
}
}
}
}
Related
When using anonymous authentication with firebase, the first time the app is launched from android studio (if it's uninstalled), a firebase account is created as intended, but the firebase database references don't connect. Only when launching the app a second time, the references work as intended and I can upload and retrieve data with my code. I'm guessing some stuff isn't initialized properly.
My code for anonymous authentication
class MainActivity : AppCompatActivity() {
var challenges = ArrayList<Challenge?>()
val recyclerViewAdapter = RecyclerViewAdapter(challenges)
var currentChallengeActive: Boolean = false
companion object{
var mAuth: FirebaseAuth? = FirebaseAuth.getInstance()
val userId = mAuth?.currentUser?.uid
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mAuth = FirebaseAuth.getInstance()
startService(Intent(this, MyService::class.java))
setFragment()
val currentUser = mAuth?.currentUser
if (currentUser == null){
anonymousLogin()
}
private fun anonymousLogin() {
mAuth?.signInAnonymously()?.addOnCompleteListener { task ->
if (task.isSuccessful) {
Snackbar.make(
findViewById(R.id.constraint_layout),
"Logged in anonymously",
Snackbar.LENGTH_SHORT
).show()
} else {
Toast.makeText(this, "Login fehlgeschlagen", Toast.LENGTH_SHORT).show()
}
}
}
My firebase references
class FirebaseConfig {
companion object{
var database: FirebaseDatabase? = null
var myRootRef: DatabaseReference? = null
var completedChallengesRef: DatabaseReference? = null
var openChallengesRef: DatabaseReference? = null
var swappedChallengesRef: DatabaseReference? = null
init {
database = FirebaseDatabase.getInstance()
myRootRef = userId?.let { database?.getReference("users")?.child(it) }
completedChallengesRef = userId?.let { database?.getReference("users")?.child(it)?.child("completed") }
openChallengesRef = userId?.let { database?.getReference("users")?.child(it)?.child("open") }
swappedChallengesRef = userId?.let { database?.getReference("users")?.child(it)?.child("swapped") }
}
}
}
I tried to get the data from the firebase cloud database, but the data didn't show out.
This is the code I try to retrieve data
private fun updateUI(currentUser: FirebaseUser?){
if(currentUser!=null){
fstore.collection("users")
.document(auth.currentUser!!.uid)
.get()
.addOnCompleteListener { task->
task.result!!.get("name") == name.text.toString();
task.result!!.get("email") == email.text.toString();
Toast.makeText(baseContext, "Haha", Toast.LENGTH_LONG).show()
}
}else{
Toast.makeText(baseContext, "fail", Toast.LENGTH_LONG).show()
}
}
Calling UpdateUI() form activity
class MainActivity : AppCompatActivity() {
lateinit var name: TextView
lateinit var email: TextView
private lateinit var fstore: FirebaseFirestore
private lateinit var auth : FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
name = findViewById(R.id.name)
email = findViewById(R.id.email)
auth = FirebaseAuth.getInstance()
fstore = FirebaseFirestore.getInstance()
updateUI(auth.currentUser)
}
firebase cloud database:
android simulator after I tried:
Your document id assigning is wrong
.document(doucumentID) //Not user ID
//Here your document id is
//JXoTcqxIVENTSF2.....
//As I can see your firestore image
and you are assigning data in a wrong way to TextView
name.text = "value you want to assign"
So edit your code like this
private fun updateUI(currentUser: FirebaseUser?){
if(currentUser!=null){
fstore.collection("users")
.document("JXoTcqxIVENTSF2..")
//can not see full id in image so I use '....'
//replace it with full id from firestore
.get()
.addOnCompleteListener { task->
name.text = task.result!!.get("name").toString()
email.text = task.result!!.get("email").toString()
Toast.makeText(baseContext, "Haha", Toast.LENGTH_LONG).show()
}
}else{
Toast.makeText(baseContext, "fail", Toast.LENGTH_LONG).show()
}
}
Created next structure in my database, and now want to display data in my list
Tried to add next code in onViewCreated:
databaseReference = FirebaseDatabase.getInstance().reference
val wordsRef = databaseReference?.child("talk-6e3c0")?.child("words")
val valueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
topWordsList.clear()
for (wordsSnapshot in dataSnapshot.children) {
val topWord = wordsSnapshot.getValue(TopWord::class.java)
topWord?.let { topWordsList.add(it) }
}
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("some", "Error trying to get targets for ${databaseError.message}")
}
}
wordsRef?.addListenerForSingleValueEvent(valueEventListener)
Method onDataChanged was called, but i can't get name for example.
My model:
data class TopWord(
val name: String = "",
val description: String = ""
)
You aren't getting something because you are adding the name of your project as a child in the reference and there is no need for that. So please change the following line of code:
val wordsRef = databaseReference?.child("talk-6e3c0")?.child("words")
to
val wordsRef = databaseReference?.child("words")
I just removed the call to .child("talk-6e3c0")?.
I have been developing a chatting app in Android using Kotlin and Firebase. Registering, searching and sending message to a user, all of this has been successful. But I'm unable to generate a chatlist which is a list of the recent chats of the user. The user can tap on it to access that particular chat, just like any other chatting app.
The user is stored in a User model and the data is registered in the database in that same format.
I am able to display the profile picture of the user using the addValueEventListener method but when the similar method is invoked for the chatlist, it throws an error -
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type kushwaha.samir.boop.models.User
This is the code where the error occurs -
val user = snapshot.getValue<User>(User::class.java!!)
present in the function - chatList()
Database view
MainActivityChat code >
class MainActivityChat : Fragment() {
lateinit var profile_image: CircleImageView
lateinit var firebaseUser: FirebaseUser
lateinit var reference: DatabaseReference
lateinit var referenceusers: DatabaseReference
lateinit var referenceuserschats: DatabaseReference
lateinit var referencechatlist: DatabaseReference
var root: View? = null
lateinit var auth: FirebaseAuth
lateinit var fragment: Fragment
var recyclerView: RecyclerView? = null
var userAdapter: UserAdapter? = null
var mUsers: MutableList<User>? = null
var fuser: FirebaseUser?=null
private var usersList: MutableList<Chatlist>? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
root = inflater.inflate(R.layout.activity_mainchat, container, false)
setHasOptionsMenu(true)
firebaseUser = FirebaseAuth.getInstance().currentUser!!
val uid = firebaseUser.uid
val floatingActionButton = root!!.findViewById(R.id.searchPerson) as FloatingActionButton
floatingActionButton.setOnClickListener {
val intent = Intent(activity, SearchActivity::class.java)
startActivity(intent)
}
fuser = FirebaseAuth.getInstance().currentUser!!
usersList = ArrayList()
reference = FirebaseDatabase.getInstance().getReference("Chatlist").child(fuser!!.uid)
referencechatlist = FirebaseDatabase.getInstance().getReference("Chatlist").child(fuser!!.uid)
profile_image = root!!.findViewById(R.id.profile_image)
firebaseUser = FirebaseAuth.getInstance().currentUser!!
FirebaseDatabase.getInstance().reference.child("Users").child(uid)
.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val user = dataSnapshot.getValue(User::class.java)
// usernamedisplay.text = user!!.username
if (user!!.profileImageUrl == "default") {
profile_image.setImageResource(R.mipmap.ic_launcher)
Log.d(ProfileFragment.TAG, "No image retrieved/found")
} else {
//change this
context?.let { Glide.with(it).load(user.profileImageUrl).into(profile_image) }!!
Log.d(ProfileFragment.TAG, "Image set")
}
}
override fun onCancelled(databaseError: DatabaseError) {
}
})
reference = FirebaseDatabase.getInstance().getReference("Chats")
reference.addValueEventListener(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onDataChange(dataSnapshot: DataSnapshot) {
var unread = 0
for (snapshot in dataSnapshot.children) {
val chat = snapshot.getValue<Chat>(Chat::class.java!!)
if (chat!!.receiver == firebaseUser!!.uid && !chat!!.isIsseen!!) {
unread++
}
}
reference = FirebaseDatabase.getInstance().getReference("Chatlist").child(fuser!!.uid)
reference.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
usersList!!.clear()
for (snapshot in dataSnapshot.children) {
val chatlist = snapshot.getValue<Chatlist>(Chatlist::class.java!!)
usersList!!.add(chatlist!!)
}
chatList()
}
override fun onCancelled(databaseError: DatabaseError) {
}
})
}
})
updateToken(FirebaseInstanceId.getInstance().token)
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView = view!!.findViewById(R.id.recycler_viewmain)
recyclerView!!.setHasFixedSize(true)
recyclerView!!.layoutManager = LinearLayoutManager(context)
}
private fun updateToken(token: String?) {
val reference = FirebaseDatabase.getInstance().getReference("Tokens")
val token1 = Token(token!!)
reference.child(fuser!!.uid).setValue(token1)
}
private fun chatList() {
mUsers = ArrayList()
reference = FirebaseDatabase.getInstance().getReference("Users")
reference.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
mUsers!!.clear()
for (snapshot in dataSnapshot.children) {
**val user = snapshot.getValue<User>(User::class.java!!)**
for (chatlist in usersList!!) {
if (user!!.id == chatlist.id) {
mUsers!!.add(user)
}
}
}
userAdapter = UserAdapter(context!!, mUsers!!, true)
recyclerView!!.adapter = userAdapter
}
override fun onCancelled(databaseError: DatabaseError) {
}
})
}
private fun status(status: String) {
reference = FirebaseDatabase.getInstance().getReference("Users").child(firebaseUser!!.uid)
val hashMap = HashMap<String, Any>()
hashMap["status"] = status
reference.updateChildren(hashMap)
}
override fun onResume() {
super.onResume()
status("online")
}
override fun onPause() {
super.onPause()
status("offline")
}
companion object {
val TAG = "MainActivityChat"
}
}
User Model
class User {
var id: String? = null
var phoneno: String? = null
var profileImageUrl: String? = null
var search: String? = null
var status: String? = null
var username: String? = null
constructor(id: String, phoneno: String, profileImageUrl: String, search: String, status: String, username: String) {
this.id = id
this.phoneno = phoneno
this.profileImageUrl = profileImageUrl
this.search = search
this.status = status
this.username = username
}
constructor() {
}
}
Chatlist model
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
#Parcelize
class Chatlist(val id: String):
Parcelable {
constructor() : this("")
}
Logcat
2019-03-02 22:20:52.446 20562-20562/kushwaha.samir.boop E/AndroidRuntime: FATAL EXCEPTION: main
Process: kushwaha.samir.boop, PID: 20562
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type kushwaha.samir.boop.models.User
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(com.google.firebase:firebase-database##16.0.5:423)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-database##16.0.5:214)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(com.google.firebase:firebase-database##16.0.5:79)
at com.google.firebase.database.DataSnapshot.getValue(com.google.firebase:firebase-database##16.0.5:212)
at kushwaha.samir.boop.MainActivityChat$chatList$1.onDataChange(MainActivityChat.kt:187)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database##16.0.5:75)
at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database##16.0.5:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database##16.0.5:55)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6762)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
According to your comment, you say that when you try to log the content of your snapshot object you get:
{ key = status, value = offline }
Which obviously means that you are using a wrong reference. So you get that result because you are getting a reference in database for the status property which of type String and that's why you get that error:
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type kushwaha.samir.boop.models.User
To solve this, please change the following line of code:
reference.addValueEventListener(object : ValueEventListener {}
to
val rootRef = FirebaseDatabase.getInstance().getReference()
val usersRef = rootRef.child("Users")
usersRef.addValueEventListener(object : ValueEventListener {}
I'm trying to get a document contents from Firestore. The following image link shows the database structure Firestore database structure
What I want: I want to get a document contents by a custom object and add the contents to a list.
The problem: I'm getting this error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.aalmesbah.turoodpilot, PID: 12160
java.lang.RuntimeException: Could not deserialize object. Class com.google.firebase.auth.UserInfo does not define a no-argument constructor. If you are using ProGuard, make sure these constructors are not stripped
I tried to get the document content by get() and getString() methods and it worked fine the problem is only with the toObject()?
I've searched and tried some suggested solutions from other questions here like add default values for the data class, but it didn't work, unfortunately.
data class code:
data class UserInfo (val name: String? = "",
val email: String? = "",
val phoneNum: String? = "",
val address: String? = "") {
constructor(): this("","","", "" )
}
Profile Fragment code: (where the document contents suppose to be shown)
class ProfileFragment : Fragment() {
private lateinit var auth: FirebaseAuth
private lateinit var db: FirebaseFirestore
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_profile, container, false)
auth = FirebaseAuth.getInstance()
db = FirebaseFirestore.getInstance()
return view
}
override fun onStart() {
super.onStart()
val userID = auth.currentUser?.uid
val docRef = db.collection("users").document(userID!!)
docRef.addSnapshotListener(EventListener<DocumentSnapshot> { documentSnapshot, e ->
if (e != null) {
Log.w(TAG, "Listen failed.", e)
return#EventListener
}
if (documentSnapshot != null && documentSnapshot.exists()) {
docRef.get().addOnSuccessListener { documentSnapshot ->
val userInfo = documentSnapshot.toObject(UserInfo::class.java)
emailTV.text = userInfo?.email
}
} else {
Log.d(TAG, "Current data: null")
}
})
}
}
sendUserData() method code at Registration activity
private fun sendUserData() {
val name = userN.text.toString()
val email = userEm.text.toString()
val phone = userPhone.text.toString()
val addressName = addressName.text.toString()
val area = area.text.toString()
val block = block.text.toString()
val street = strees.text.toString()
val avenue = avenue.text.toString()
val house = house.text.toString()
val floor = floor.text.toString()
val apartment = apartment.text.toString()
val additionalInfo = additional.text.toString()
val address = "Addres Name: $addressName \n Area: $area \n B: $block ST: $street Av: $avenue H: $house\n " +
"Floor: $floor Apartment: $apartment \n Notes: $additionalInfo"
val userID = auth.currentUser?.uid
val userData = UserInfo(name, email, phone, address)
db.collection("users").document(userID!!).set(userData).addOnSuccessListener {
Toast.makeText(this, "Successfully Registered", Toast.LENGTH_SHORT).show()
}.addOnFailureListener{
Toast.makeText(this, "Data Upload error!", Toast.LENGTH_SHORT).show()
}
}
If you want to use a Kotlin data class with documentSnapshot.toObject, you're going to have to make each field a nullable var instead of val. The Firestore SDK doesn't know how to map document fields into data class constructor argument.
If you want a proper immutable data class with val fields, you're going to have to manually read each field out of the document, and call the data class constructor yourself.