Android:can not save arrayList<String> in my firebase-realtime - android

I try to add accident in firebase-realtime with some information and some images, only the information are saved, the images paths are saved in firebase-storage but not in firebase-realtime.when I get the path of images from firebase-storage. I put this result path in arrayList of String. I want to put this arrayList in accident .I don't know why only the information are saved and the arrayList not saved, can some one help me please ?
class Accident (
var date:String?,
var id:String?,
var description:String?,
// var video:Array<String>?=null,
// var gravite:Int?=null,
val geolocalisation:Localisation?,
var photos: ArrayList<String>?,
val adress:String?
//var nbVictime:Int?=null
): Serializable
class Localisation( var altitude:Double=0.0,
var longitude:Double = 0.0)
: Serializable {
}
fun loadDatabase(firebaseData: DatabaseReference) {
uploadFile()
var loc = Localisation(currentLatLng!!.latitude, currentLatLng!!.longitude)
var uri=tabpath as ArrayList<String>
val availableAccident: List<Accident> = mutableListOf(
Accident(SimpleDateFormat("yyyy/MM/dd_HH:mm:ss").format(Date()), "", "il est tres grave", loc, uri, "Monastir")
)
var t=""
availableAccident.forEach {
val key = firebaseData.child("accidents").push().key
it.id = key!!
it.photos=uri
if (key != null) {
firebaseData.child("accidents").child(key).setValue(it)
}
}
}

Related

How to map aggregated data from Firestore document back to a Kotlin List

Would like to reduce the number of reads in my app with Firestore. So I created a document in my collection with the following structure to hold values for 10 "records", that I will get with a single read - since the size of this document is pretty decent, no worries about the 1MB limit size for a single document. I am updating the content of this document with cloud functions.
name of collection: helperz
name of document: top10
field name in top10: tresholdCounter - this I need to check if a single map should be added to top10 or not
field name in top10: top10 . . array of maps
helperz/top10/tresholdCounter
helperz/top10/top10/0/author
helperz/top10/top10/0/name
helperz/top10/top10/0/url
helperz/top10/top10/1/author
helperz/top10/top10/1/name
helperz/top10/top10/1/url
helperz/top10/top10/2/author
helperz/top10/top10/2/name
helperz/top10/top10/2/url
helperz/top10/top10/3/author
helperz/top10/top10/3/name
helperz/top10/top10/3/url
helperz/top10/top10/4/author
helperz/top10/top10/4/name
helperz/top10/top10/4/url
..
helperz/top10/top10/10/author
helperz/top10/top10/10/name
helperz/top10/top10/10/url
I have a data class . . like this:
data class MyClass(
var name: String? = null,
var url: String? = null,
var author: String? = null,
var counter: Int = 0,
var free: Boolean? = false,
var global: Boolean?=true,
var poses: ArrayList<MyPoze>? = null,
var docId: string? = null,
var category: ArrayList<String>? = null,
#get:PropertyName(CREATED)
#set:PropertyName(CREATED)
#ServerTimestamp var created: Timestamp? = null
)
There are some other fields as well, but for the purpose of this problem, that should be ok.
I have a code for retrieving data from Firestore (in my viewModel):
private fun getHelperzTop10() = viewModelScope.launch {
Log.d("MP23", "getHelperzTop10")
val docRef = db.collection("helperz").document("top10")
docRef.addSnapshotListener { snapshot, e ->
if (e != null) {
Log.w("MP23", "Listen failed.", e)
return#addSnapshotListener
}
if (snapshot != null && snapshot.exists()) {
val docSize = firestoreDocument.getSize(snapshot);
Log.d("MP23","docSize in Bytes: $docSize, in KB: ${docSize * 0.001}, in MB: ${docSize * 0.000001}"
)
val top10 = snapshot.data
Log.d("MP23", top10!!::class.simpleName.toString() )
if ("top10" in keys) {
val top10arr = top10["top10"] as ArrayList<MyClass>
Log.d("MP23", "we have top10 in top10")
Log.d("MP23", top10arr!!::class.simpleName.toString())
Log.d("MP23", top10arr.toString())
//// 👇 PROBLEM HERE ///
// here I need somehow to cast this array of maps as MyClass, but I am getting error:
// java.util.ArrayList cannot be cast to java.lang.MyClass
// or
// java.util.ArrayList cannot be cast to java.lang.Object[] - with some other versions
}
} else {
Log.d("MP23", "Current data: null")
}
}
}
If someone can suggest how can I cast result to MyClass, that would be great. In normal situation (where I have documents that I query against) nicely as single docs, I can easily do:
val singleRec = singleRec.toObject(MyClass::class.java)
If you want to get the top10 array as a List<MyClass>, the simplest solution that I can think of would be to create another class:
data class Document(
var top10: MutableList<MyClass>? = null
)
And read the content of the document like this:
docRef.get().addOnCompleteListener {
if (it.isSuccessful) {
val snapshot = it.result
snapshot?.let {
val document = snapshot.toObject(Document::class.java)
document?.let {
val top10 = document.top10
top10?.let {
for (myClass in top10) {
val name = myClass.name
Log.d("TAG", "$name")
}
}
}
}
} else {
it.exception?.message?.let { message ->
Log.d("TAG", message) //Never ignore potential errors!
}
}
}
I will also recommend you read the following resource for a better understanding:
How to map an array of objects from Cloud Firestore to a List of objects?

Can't add Firebase document Id to dataClass

I have a data class for data that come from user entries. İt is carrying this data to Firebase. This data class also includes documentId variable which is a empty string by default. I want to add document Id's that Firebase created automatically. I tried every way I could think of. But it takes default value in any way.
Here are the four code snippets about this issue. Data class, adding data activity, and retrieving data activity and their View Models.
Dataclass:
data class AnalyzeModel(
var concept: String?="",
var reason: String?="",
var result: String?="",
var rrRatio: Double?=0.0,
var tarih: Timestamp=Timestamp.now(),
var tradingViewUrl: String="",
var id : String="")
AddAnalyzeActivity, addData function:
fun addData(view: View) {
val tarih = com.google.firebase.Timestamp.now()
val rr = rrText.text.toString()
var doubleRR = rr.toDoubleOrNull()
if (doubleRR == null) { doubleRR = 0.0 }
val analyzeDTO = AnalyzeModel(
conceptText.text.toString(),
reasonForText.text.toString(),
resultAddingText.text.toString(),
doubleRR,
tarih,
chartImage.text.toString()
)
viewModel.save(analyzeDTO)
val intent = Intent(this, PairDetailActivity::class.java)
startActivity(intent)
finish()
}
AddAnalyze ViewModel, save function:
fun save(data: AnalyzeModel) {
database.collection(dbCollection!!).document("Specified").collection("Pairs")
.document(chosenPair!!)
.collection("Analysis")
.add(data)
.addOnFailureListener { exception ->
exception.printStackTrace()
Toast.makeText(getApplication(), exception.localizedMessage, Toast.LENGTH_LONG).show()
}
}
PairViewModel, retrieveData function:
private fun retrieveData() {
val docRef = collectionRef.orderBy("tarih", Query.Direction.DESCENDING)
docRef.addSnapshotListener { value, error ->
try {
if (value != null && !value.isEmpty) {
val allAnalysis= ArrayList<AnalyzeModel>()
val documents = value.documents
documents.forEach {
val analyze = it.toObject(AnalyzeModel::class.java)
if (analyze!=null){
allAnalysis.add(analyze)
}
}
list.value = allAnalysis
} else if (error != null) {
Toast.makeText(Application(), error.localizedMessage, Toast.LENGTH_LONG).show()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
I want to add document IDs that Firebase created automatically.
To solve this, you only need to annotate the field with #DocumentId.
data class AnalyzeModel(
var concept: String?="",
var reason: String?="",
var result: String?="",
var rrRatio: Double?=0.0,
var tarih: Timestamp=Timestamp.now(),
var tradingViewUrl: String="",
#DocumentId 👈
var id : String=""
)
Be also sure to have the latest version of Firestore.

How to retrieve data from nested array of maps in Firestore (Kotlin) for RecyclerView

I would like to ask for help on how to retrieve data from Firestore for nested Array of Maps called "cities" into MutableList , which I then want to insert into recycler view, where the data from the “regions” are for the header and data “cities” for the regular list items.
Data for regions: MutableList , when I follow the procedure https://medium.com/firebase-tips-tricks/how-to-map-an-array-of-objects-from-cloud-firestore-to-a-list -of-objects-122e579eae10 by Alex Mamo, got fine, but data for: cities: MutableList , according same approach, is null (unable to retrive).
Can you please advise how to get data for “cities”?
P.s. somewhere I read the recommendation to iterate over "cities", but I have no idea how, please go straight for an example (ideally in Kontlin).
Code:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
…..
regionsRef.get().addOnCompleteListener { document ->
if (document.isSuccessful()) {
val documentSnapshot = document.result
// Retrieve array of maps for „regions“
val regions = documentSnapshot.toObject(RegionDocument::class.java)?.regions
// Retrieve array of maps for „cities“
val cities = documentSnapshot.toObject(CityDocument::class.java)?.cities
…
}
}
Data classes for object City:
data class City(
val cityNumber: Long? = null,
val cityName: String? = "" )
data class CityDocument(
var cities: MutableList<City>? = null)
Firestore structure:
To be able to get the data that corresponds to your document structure, you need three classes:
class Document {
var regions: MutableList<Region>? = null
}
class Region {
var cities: MutableList<City>? = null
var regionName: String? = null
var regionNumber: Long? = null
}
class City {
var cityName: String? = null
var cityNumber: Long? = null
}
And below you can find a solution for reading all cities:
val db = FirebaseFirestore.getInstance()
val docIdRef = db.collection("collName").document("docId")
docIdRef.get().addOnCompleteListener { task ->
if (task.isSuccessful) {
val document = task.result
if (document != null) {
val doc = document.toObject(Document::class.java)
if (doc != null) {
val regions = doc.regions
if (regions != null) {
for (region in regions) {
val cities = region.cities
//Do what you need to to do with your List<City>.
}
}
}
}
} else {
Log.d("TAG", task.exception!!.message!!) //Never ignore potential errors!
}
}
Now, simply replace collName and docId with the one you have in your database.

firestore read data adding hashmap get data when added

when the user presses the button onlick ,read data and add hashmap
When completed I want to read with getfirestore2() method
data to come
comment1
comment2
comment3
comment4
but incoming data with getfirestore2() method
comment 4
my using method failed and not safe because I use delay
I how to fix codes?
my codes
binding.AllAskedBtn.setOnClickListener {
a1hliste.clear()
a2hliste.clear()
a3hliste.clear()
a4hliste.clear()
fun getfirestore2(){
println("listedekiler A1 "+a1hliste)
println("listedekiler A2 "+a2hliste)
println("listedekiler A3 "+a3hliste)
println("listedekiler A4 "+a4hliste)
println("\n veri 2 db size "+dbsize)
var sayi=0
var g1=a1hliste.getValue(sayi).toString()
var g2=a2hliste.getValue(sayi).toString()
var g3=a3hliste.getValue(sayi).toString()
var g4=a4hliste.getValue(sayi).toString()
for (a in 0..dbsize-1){
db.collection(g1).document(g2).collection(g3).document(g4).addSnapshotListener { task,e->
var veri= task!!.get("comment") as String
println("This is the data from "+veri)
}
}
}
db.collection("users").document(uuid).collection("Questions").orderBy("date",Query.Direction.DESCENDING).addSnapshotListener{ result, e->
var veri=result!!.documents
var verisize=result!!.documents.size
dbsize=0
for (a in veri){
var dersler=a.get("FBDersler") as String
var konular=a.get("FBKonular") as String
var sinavturu=a.get("sinavturu") as String
var QuestionUİD=a.get("QuestionUİD") as String
a1hliste.put(dbsize,sinavturu.toString())
a2hliste.put(dbsize,dersler.toString())
a3hliste.put(dbsize,konular.toString())
a4hliste.put(dbsize,QuestionUİD.toString())
dbsize+=1
GlobalScope.launch {
delay(2000L)
if (dbsize==verisize){
getfirestore2()
}
}
}
println("db size "+dbsize)
}
}
I finding solution
nested firestore listeners for , I am using .addOnSuccessListener method
binding.AllAskedBtn.setOnClickListener {
a1hliste.clear()
a2hliste.clear()
a3hliste.clear()
a4hliste.clear()
db.collection("users").document(uuid).collection("Questions").orderBy("date",Query.Direction.DESCENDING).get().addOnSuccessListener{ task->
var a=0
for (documents in task){
var dersler:String?=null
var konular:String?=null
var sinavturuu:String?=null
var QuestionUİD:String?=null
sinavturuu=documents["sinavturu"] as String
dersler=documents["FBDersler"] as String
konular=documents["FBKonular"] as String
QuestionUİD=documents["QuestionUİD"] as String
println(QuestionUİD.toString())
a1hliste.put(a,sinavturuu.toString())
a2hliste.put(a,dersler.toString())
a3hliste.put(a,konular.toString())
a4hliste.put(a,QuestionUİD.toString())
a+=1
}
}.addOnSuccessListener {
var Anumber=0
for (b in 0..a4hliste.size-1){
var g1=a1hliste.getValue(b).toString()
var g2=a2hliste.getValue(b).toString()
var g3=a3hliste.getValue(b).toString()
var g4=a4hliste.getValue(b).toString()
db.collection(g1).document(g2).collection(g3).document(g4).addSnapshotListener { value,e->
val Aphotourl=value!!.get("questionphotourl") as String
val Asinavtürü=value!!.get("sinavturu") as String
val Akonular=value!!.get("FBKonular") as String
val Adersler=value!!.get("FBDersler") as String
val Adocid=value!!.get("QuestionUİD") as String
val AFBusername=value!!.get("username") as String
val Aanswercheck=value!!.get("answercheck") as Boolean
Anumber+=1
usernamelist.add(AFBusername)
ProfileSınavTürü.put(Anumber,Asinavtürü)
ProfileFBDersler.put(Anumber,Adersler)
ProfileKonular.put(Anumber,Akonular)
ProfileQuestionUİD.put(Anumber,Adocid)
photoUrlList.put(Anumber,Aphotourl)
answercheckmap.put(Anumber,Aanswercheck)
adapter!!.notifyDataSetChanged()
}
}
}
}

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