Type mismatch: inferred type is com.google.firebase.firestore.auth.User but com.example.socialmediaapp.model.User was expected - android

Error is showing for the user when passed in post i.e val post = Post(text, user, currentTime)
class PostDao {
private val db = FirebaseFirestore.getInstance()
private val postCollection = db.collection("posts")
private val auth = Firebase.auth
fun addPost(text:String){
val currentUserId = auth.currentUser!!.uid
GlobalScope.launch {
val userDao = UserDao()
//getting actual user document from the task through user id
val user = userDao.getUserById(currentUserId).await().toObject(User::class.java)!!
val currentTime = System.currentTimeMillis()
val post = Post(text, user, currentTime)
}
}
}
Here is the Post data class :
data class Post(
val text:String = "",
val createdBy: User = User(),
val createdAt:Long = 0L,
val likedBy: ArrayList<String> = ArrayList()
)
Please help me solve this issue.
Thank you !

This is because you are not using same user object at both of the places. You need to declare and get same type of USER class in your code.
You are trying to get the value of com.google.firebase.firestore.auth.User but com.example.socialmediaapp.model.User is expected as per your code.

Related

Values are not added in an array instead it keeps updating value at 0th index in Firebase Firestore

On clicking like button , it is not either increasing like count in UI nor adding a userid in likes array. It is not adding a userid into an array instead it is updating value at 0th index. I am attaching photos of logic to add values in array in firestore.
I have also added the project on github. Please take a look at it for more clearification.
https://github.com/Anshi10/Social-Media-App
Post data class which has array of user ids which liked a post.
data class Post(
val text : String = "" ,
val createdBy : user = user() ,
val createdAt : Long = 0L ,
val Likes : ArrayList<String> = ArrayList()
)
Post Dao for adding post into firestore and updating likes
class PostDao {
val db = FirebaseFirestore.getInstance()
val PostCollection = db.collection("Post")
val auth = Firebase.auth
fun addPost(text : String){
//!! is to ensure that post is created only when user is logged in otherwise it will count as illegal exception
val currentUserId = auth.currentUser!!.uid
val userdao = userDao()
GlobalScope.launch{
//getuserbyid return task which will turn into object of user data class
val Postuser = userdao.getuserbyId(currentUserId).await().toObject(user::class.java)!!
//this will give the time when the post is created
val currentTime = System.currentTimeMillis()
val post = Post(text,Postuser,currentTime)
PostCollection.document().set(post)
}
}
fun getPostById(postid : String) : Task<DocumentSnapshot>{
return PostCollection.document(postid).get()
}
fun updateLikes(postid: String) {
GlobalScope.launch {
val currentUserid = auth.currentUser!!.uid
val post = getPostById(postid).await().toObject(Post::class.java)!!
val isliked = post.Likes.contains(currentUserid)
if (isliked) {
post.Likes.remove(currentUserid)
} else {
post.Likes.add(currentUserid)
}
PostCollection.document(postid).set(post)
}
Log.d("msg","updateLikes called")
}
}
onBindViewHolder function
override fun onBindViewHolder(holder: PostViewHolder, position: Int, model: Post) {
holder.userName.text = model.createdBy.name
holder.userText.text = model.text
//with(context) load(url) into(view)
Glide.with(holder.userImage.context).load(model.createdBy.imageUrl).circleCrop().into(holder.userImage)
holder.Likecount.text = model.Likes.size.toString()
holder.userTime.text = Utils.getTimeAgo(model.createdAt)
val auth = FirebaseAuth.getInstance()
val currentuserId = auth.currentUser!!.uid
val isliked = model.Likes.contains(currentuserId)
if(isliked){
holder.likeButton.setImageDrawable(ContextCompat.getDrawable(holder.likeButton.context,R.drawable.ic_baseline_favorite_24))
}
else{
holder.likeButton.setImageDrawable(ContextCompat.getDrawable(holder.likeButton.context,R.drawable.unliked))
}
}
}
Firestore structure
first collection named post which contains field createdAt , createdBy,likesCount,text of the post.
second collection named users which contains field id , imageUrl , name

I want to show a data whose values I have determined myself in text

calculateButton.setOnClickListener {
val panelC = binding.panelCount.text.toString()
val panelS = binding.panelSize.text.toString()
val landS = binding.landSlope.text.toString()
val landSi = binding.landSize.text.toString()
val cit = binding.city.text.toString()
val sun = (1000).toInt()
val air = (1.25).toFloat()
val cel = (25).toInt()
val verim = ((sun * air)/ cel).toString().toDouble()
if (panelC.equals("") || panelS.equals("")|| landS.equals("")|| landSi.equals("")||cit.equals("")){
Toast.makeText(requireContext(),"Alanları Doldurunuz.", Toast.LENGTH_SHORT).show()
}
else{
val action = SignUpCalculateFragmentDirections.actionSignUpCalculateFragmentToDataFragment()
Navigation.findNavController(view).navigate(action)
}
val postMap = hashMapOf<String, Any>()
postMap.put("Panel Sayisi",binding.panelCount.text.toString())
postMap.put("Panel Boyutu",binding.panelSize.text.toString())
postMap.put("Arazi Eğimi",binding.landSlope.text.toString())
postMap.put("Arazi Boyutu",binding.landSize.text.toString())
postMap.put("Şehir",binding.city.text.toString())
postMap.put("date", Timestamp.now())
postMap.put("verim",verim.toString().toDouble())
firestore.collection("Posts").add(postMap).addOnFailureListener {
}.addOnFailureListener {
Toast.makeText(requireContext(),it.localizedMessage,Toast.LENGTH_SHORT).show()
}
There is a calculatePage Fragment Codes. On this page, I am trying to make a yield calculation based on the data I receive from the user. However, I need to add the values that are kept constant in the efficiency calculation, such as "sun", "cel", "air" that I defined in the code. I wrote a random operation there as an example. To see if I can write inside the text I'm trying to print without getting any errors. But the app crashed.
private fun getData(){
firestore.collection("Posts").addSnapshotListener { value, error ->
if (error!=null){
Toast.makeText(requireContext(),error.localizedMessage,Toast.LENGTH_SHORT).show()
}else{
if (value !=null){
if (!value.isEmpty){
val documents = value.documents
for (document in documents){
val pc = document.get("Panel Sayisi") as String
val ps = document.get("Panel Boyutu") as String
val ls = document.get("Arazi Eğimi") as String
val lsi = document.get("Arazi Boyutu") as String
val c = document.get("Şehir") as String
val v = document.get("verim") as Double
val post = Post(pc,ps,ls,lsi,c,v)
postArrayList.add(post)
}
}
}
}
val db = FirebaseFirestore.getInstance()
db.collection("Posts").orderBy("date",Query.Direction.DESCENDING).limit(1)
.get()
.addOnCompleteListener {
val result : StringBuffer = StringBuffer()
if (it.isSuccessful){
for (document in it.result){
result.append(document.data.getValue("verim"))
}
verimText.setText(result)
}
}
On this page, I added the values I defined in my class named 'post' to the postList and added them to Firestore.
data class Post(val pc: String, val ps: String, val ls: String, val lsi: String, val c: String, val v : Double)
#ServerTimestamp
var date: Date? = null
This is my post class
The error is like this: java.lang.NullPointerException: null cannot be cast to non-null
type kotlin.Double
As I explained at the beginning of my question, what I am trying to do is using both the data such as "panelCount", "panelSize" that I get from the user and the "sun", "cel", "air" values that are defined as constants, using the "verimText.setText(result)" in the DataFragment page. I need to show this calculation to the user.
The user enters values such as 'Panel Sayisi', 'Panel Boyutu' that should be used while calculating on the calculation page. I need to show this to the user in verimText using both this data and the 'cel', 'sun', 'air' constants that I wrote in the first code.
PS: verim: 20000 value is the result of hypothetical values that I wrote in the first code. In this part, I need to make a calculation using the other data entered by the user and these constant values and show it in the verimText.

How To Dynamically Change Properties In ViewModel

So in my DAO, I have a query like this
#Query("Select * from transaction_history where wallet_type=:walletType AND email=:email AND transaction_type='Expenses' AND date BETWEEN :from AND :to")
fun getLastSevenDaysExpensesTransaction(walletType: String, email:String, from: Long?, to: Long?) : LiveData<List<ExpensesTransaction>>?
#Query("Select * from transaction_history where wallet_type=:walletType AND email=:email AND transaction_type='Income' AND date BETWEEN :from AND :to")
fun getLastSevenIncomeTransaction(walletType: String, email:String, from: Long?, to: Long?) : LiveData<List<IncomeTransaction>>
And in my viewModel, this is how I call getLastSevenDaysExpensesTransaction method
class GraphViewModel(dataSource: NetWalletDatabaseDao, application: Application, email: String, walletType: String) : ViewModel() {
val database = dataSource
var from : Long = 0L
var to : Long = 0L
val lastSevenDaysIncome = database.getLastSevenIncomeTransaction(walletType, email, from, to)
val lastSevenDaysExpenses = database.getLastSevenDaysExpensesTransaction(walletType, email, from, to)
fun funcLastSevenDaysIncome(fromParam: Long, toParam: Long) {
from = fromParam
to = toParam
}
And in my Fragment, this is how I display the data
val application = requireNotNull(this.activity).application
val dataSource = NetWalletDatabase.getInstance(application).netWalletDatabaseDao
val viewModelFactory = GraphViewModelFactory(
dataSource,
application,
getEmail.toString(),
getWalletType.toString(),
)
val viewModel =
ViewModelProvider(this, viewModelFactory).get(GraphViewModel::class.java)
val tvLastSevenDays = binding.tvLastSevenDays
viewModel.funcLastSevenDaysIncome(sevenDaysInMili, todayMili)
val chart : LineChart = binding.chart
val expenses = ArrayList<Entry>()
viewModel.lastSevenDaysMut.observe(viewLifecycleOwner, Observer { list ->
list?.let {
for (i in 0..list.size - 1) {
expenses.add(Entry(i.toFloat(), list.get(i).value!!.toFloat()))
}
Log.e("Result", list.get(0).value!!.toString())
}
val expensesLineDataSet = LineDataSet(expenses, "Expenses")
expensesLineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER
expensesLineDataSet.color = Color.BLUE
expensesLineDataSet.circleRadius = 5f
expensesLineDataSet.setCircleColor(Color.BLUE)
val income = ArrayList<Entry>()
viewModel.lastSevenDaysMut.observe(viewLifecycleOwner, Observer { list ->
list?.let {
for (i in 0..list.size - 1) {
income.add(Entry(i.toFloat(), list.get(i).value!!.toFloat()))
Log.e("Result", list.get(0).value!!.toString())
}
}
val incomeLineDataSet = LineDataSet(income, "Income")
incomeLineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER
incomeLineDataSet.color = Color.RED
incomeLineDataSet.circleRadius = 5f
incomeLineDataSet.setCircleColor(Color.RED)
val legend = chart.legend
legend.isEnabled = true
legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP)
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER)
legend.setOrientation(Legend.LegendOrientation.HORIZONTAL)
legend.setDrawInside(false)
chart.description.isEnabled = false
chart.xAxis.position = XAxis.XAxisPosition.BOTTOM
chart.data = LineData(expensesLineDataSet, incomeLineDataSet)
chart.animateXY(100, 500)
})
})
The problem is that the data won't show. What I understand so far why the data won't show is that, when val lastSevenDaysIncome = database.getLastSevenIncomeTransaction(walletType, email, from, to) and val lastSevenDaysExpenses = database.getLastSevenDaysExpensesTransaction(walletType, email, from, to) from my viewModel is run, the properties of var from : Long = 0L and var to : Long = 0L is still zero even though in my Fragment, I have called the method to change those properties viewModel.funcLastSevenDaysIncome(sevenDaysInMili, todayMili).
So how do I fix it? How do I change the properties var from : Long = 0L and var to : Long = 0L before they are used for query?
P.S. I used to put all the necessary parameters for query in constructor. For example
class GraphViewModel(dataSource: NetWalletDatabaseDao, application: Application, email: String, walletType: String, from: Long, to: Long) : ViewModel()
and use it for example
val lastSevenDaysIncome = database.getLastSevenIncomeTransaction(walletType, email, from, to)
But, since "from" and "to" is dynamic, I can't use it anymore because then in my fragment, I have to initialize the viewModelProvider something like this
val viewModelFactory = GraphViewModelFactory(
dataSource,
application,
getEmail.toString(),
getWalletType.toString(),
***dynamic from*
*dynamic to***
)
Thank you in advance.

Is there a way with Gson to retrieve sub JSON object information without having to create custom classes for them?

I am using Retrofit and Gson to fetch Json and convert data form the OpenWeatherMap API, i was hoping that there is a way to omit the need to write sub-classes for each nested object.
And just to as for your opinion what do you think of this code:
My goal was to enable accessing the properties directly
Would you scream at the monitor if you saw this or is it OK
class PlaceWeatherInfo(
val id: Long,
val name: String,
private val weather: List<Weather>,
private val wind: Wind,
#SerializedName("coord") val latLng: LatLng,
#SerializedName("dt") val time : Long,
#SerializedName("main") private val mainInfo: MainInfo,
#SerializedName("sys") private val countryInfo: Country
){
val weatherType get() = weather[0].type
val description get() = weather[0].description
val temp get() = mainInfo.temp
val minTemp get() = mainInfo.minTemp
val maxTemp get() = mainInfo.maxTemp
val feelsLikeTemp get() = mainInfo.feelsLike
val pressure get() = mainInfo.pressure
val humidity get() = mainInfo.humidity
val windSpeed get() = wind.speed
val windDegree get() = wind.degree
val country get() = countryInfo.country
val sunrise get() = countryInfo.sunrise
val sunset get() = countryInfo.sunset
}
Just so you know i am new to android development and do not have to much experience with Gson.
I suggest you always use "JSON To Kotlin Class ​(JsonToKotlinClass)​" plugin for that stuff:
(Never manual create classes from JSON)
Link plugin:
https://plugins.jetbrains.com/plugin/9960-json-to-kotlin-class-jsontokotlinclass-/
Demo:
json actually is actually HashMap or ArrayList
You just need to read slowly layer by layer
for example (by firebase):
public static void getCourse_class(){
DatabaseReference database_course = FirebaseDatabase.getInstance().getReference("course").child("0001");
database.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot ds :dataSnapshot.getChildren()){
HashMap<String,Objest> hashmap = ds.getKey();
String s = hashmap.get("coord").get("dt").get("main").get("sys");
}
}
}
}

Android Kotlin save data class in Firebase Database

I am working on an Android application in Kotlin which integrate Firebase.
Now I want to store my data (Kotlin data class) into Firebase Database.
Data Classes:
#Parcelize
data class Trip(
val fromAddress: String,
val toAddress: String,
val fromLocation: String,
val toLocation: String,
val orderUid: String
) : Parcelable
#Parcelize
data class Order(val trip: Trip, val date: Date, var status: OrderStatus, val userUid: String) : Parcelable {
var pickUpDate: Date? = null
var dropOffDate: Date? = null
var price: Double? = null
}
Fireabase Database write operation:
fun createNewOrder(
fromAddress: String,
toAddress: String,
fromLocation: Location,
toLocation: Location
) {
val fromGeoLocation = fromLocation.convertToGeoLocation()
val toGeoLocation = toLocation.convertToGeoLocation()
val userUid = sharedPreferences[CURRENT_USER_UID_KEY, ""]!!
val orderKey = databaseReference.child(DB_ORDERS_KEY).push().key
val tripKey = databaseReference.child(DB_TRIPS_KEY).push().key
val trip = orderKey?.let { createNewTrip(fromAddress, toAddress, it) }
val order = trip?.let { Order(it, Date(), OrderStatus.PENDING, userUid) }
if (trip != null && order != null && !userUid.isNullOrEmpty()) {
ordersGeoFire.setLocation(trip.fromGeoLocation, fromGeoLocation)
ordersGeoFire.setLocation(trip.toGeoLocation, toGeoLocation)
val allData = mutableMapOf<String, Any>()
allData["/$DB_TRIPS_KEY/$tripKey"] = trip?.convertToMap()
allData["/$DB_ORDERS_KEY/$orderKey"] = order?.convertToMap()
allData["/$DB_USERS_KEY/$userUid/$DB_ORDERS_KEY/$orderKey"] = true
databaseReference.updateChildren(allData)
}
}
I received this error:
com.google.firebase.database.DatabaseException: No properties to serialize found on class kotlin.Unit
Any suggestions?
The problem in your code is that the fileds inside your Trip class are not initialized. A recommended way in which you can create your model class would be:
class Trip(
val displayName: String = "",
val email: String = "",
val photoUrl: String = "",
val userId: String = ""
)
This is only what you need. And a way to create a new object of your Trip class, would be:
val trip = Trip(displayName, email, photoUrl, userId)
It was my mistake, because I was forget to add return type in my extensions convertToMap functions. Now they look like this:
fun Trip.convertToMap(): MutableMap<String, Any> {
val map = mutableMapOf<String, Any>()
map["fromAddress"] = fromAddress
map["toAddress"] = toAddress
map["fromGeoLocation"] = fromGeoLocation
map["toGeoLocation"] = toGeoLocation
map["orderUid"] = orderUid
return map
}
And also thanks to #Alex Mamo for his answer, it helps me in my investigation.
Now my code looks like this and works fine:
#Parcelize
data class Trip(
var fromAddress: String = "",
var toAddress: String = "",
var fromGeoLocation: String = "",
var toGeoLocation: String = "",
var orderUid: String = ""
) : Parcelable
#Parcelize
data class Order(
var trip: Trip? = null,
var date: Date? = null,
var status: OrderStatus? = null,
var userUid: String = ""
) : Parcelable {
var pickUpDate: Date? = null
var dropOffDate: Date? = null
var price: Double? = null
}
fun createNewOrder(
fromAddress: String,
toAddress: String,
fromLocation: Location,
toLocation: Location
): LiveData<Order> {
orderLiveData = MutableLiveData()
orderLiveData.value = null
val userUid = sharedPreferences[CURRENT_USER_UID_KEY, ""]!!
val orderKey = databaseReference.child(DB_ORDERS_KEY).push().key
val tripKey = databaseReference.child(DB_TRIPS_KEY).push().key
val trip = orderKey?.let { createNewTrip(fromAddress, toAddress, fromLocation, toLocation, it) }
val order = trip?.let { Order(it, Date(), OrderStatus.PENDING, userUid) }
if (trip != null && order != null && !userUid.isNullOrEmpty()) {
val allData = mutableMapOf<String, Any>()
allData["/$DB_TRIPS_KEY/$tripKey"] = trip.convertToMap()
allData["/$DB_ORDERS_KEY/$orderKey"] = order.convertToMap()
allData["/$DB_USERS_KEY/$userUid/$DB_ORDERS_KEY/$orderKey"] = true
databaseReference.updateChildren(allData) { databaseError, databaseReference ->
if (databaseError == null) orderLiveData.value = order
}
}
return orderLiveData
}
Hope this will be helpful

Categories

Resources