I have some problem when I try to save array data from an Android Kotlin to Firebase Database.
I want to save data as shown below:
Image 1
but, when I saved the data, in the Firebase database it always updated the "pemasukan" object, not creating new data.
the stored data is always like the picture below
Image 2
Anyone can help me please.
Sorry for my English ;)
This is the code I am using for
class PemasukanActivity : AppCompatActivity() {
private lateinit var database : FirebaseDatabase
private lateinit var mRef : DatabaseReference
lateinit var currentDate : String
private val id_user = "agus"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pemasukan)
btnSimpan()
}
//aksi tombol untuk simpan data
private fun btnSimpan(){
btn_simpan_pemasukan.setOnClickListener {
val pemasukan = Pemasukan()
if (edt_nama_barang.length() > 3){
pemasukan.keterangan = edt_nama_barang.text.toString()
} else {
edt_nama_barang.error ="Nama Barang Harus lebih dari 3 huruf"
return#setOnClickListener
}
if (edt_jumlah.length() > 3){
var jumlah = edt_jumlah.text.toString()
pemasukan.jumlah = jumlah.toLong()
}else{
edt_jumlah.error ="Jumlah Harus lebih dari 3 huruf"
return#setOnClickListener
}
simpanData(pemasukan)
}
}
//simpan data ke firebase
private fun simpanData(listPemasukan :Pemasukan){
val sdf = SimpleDateFormat("ddMyyyy")
currentDate = sdf.format(Date())
val data = Dataitem()
data.id = currentDate
data.user_id = id_user
val nameList = ArrayList<Pemasukan>(Arrays.asList(listPemasukan))
data.pemasukan = nameList
database = FirebaseDatabase.getInstance()
mRef = database.getReference("pendataan")
mRef.child("${currentDate}").setValue(data)
.addOnSuccessListener {
Toast.makeText(this, "Success . .", Toast.LENGTH_LONG).show()
edt_nama_barang.text.clear()
edt_jumlah.text.clear()
}
.addOnFailureListener {
Toast.makeText(this, "Gagal Input Data", Toast.LENGTH_LONG).show()
it.printStackTrace()
Log.e("FIREBASE_ERROR", it.message)
}
}
And the POJO class like this:
data class Dataitem (
var id : String = "",
var user_id : String = "",
var pemasukan : ArrayList<Pemasukan>? = null,
var pengeluaran : ArrayList<Pengeluaran>? = null
)
data class Pengeluaran (var jumlah : Long = 0,
var keterangan : String = "")
data class Pemasukan (var jumlah : Long = 0,
var keterangan : String ="")
Related
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 am trying to collect values from sqlite saved data and html value queried by jsoup inside a thread,the sqlite data was brought good,but the values inside thread that bring data from an html page didn't print anything.
why?
is this because i can't send a value outside a thread?,i made a global variable outside thread (stringbuilder) to catch data inside thread and send outside thread,but also this didn't work although i tested this thread in another page (outside database file) and works fine
what's wrong with this code?
DatabaseHandler.kt
fun allInvestments():List<InvestModelClass>{
val invList:ArrayList<InvestModelClass> = ArrayList<InvestModelClass>()
val selectQuery = "SELECT * FROM $TABLE_CONTACTS order by id desc"
val db = this.readableDatabase
var cursor: Cursor?
try{
cursor = db.rawQuery(selectQuery, null)
}catch (e: SQLiteException) {
db.execSQL(selectQuery)
return ArrayList()
}
// var invest_id: Int
var start_date: String
var amount:String
var currency: String
var karat:String
var enter_price:String
var percent:String
//moveToFirst will bring all ids
//moveToLast will bring the last inserted id
if (cursor.moveToFirst()) {
do {
// invest_id = cursor.getInt(cursor.getColumnIndex("id"))
start_date = cursor.getString(cursor.getColumnIndex("dt"))
amount = cursor.getString(cursor.getColumnIndex("amount"))
currency = cursor.getString(cursor.getColumnIndex("currency"))
karat = cursor.getString(cursor.getColumnIndex("karat"))
enter_price = cursor.getString(cursor.getColumnIndex("enter_price"))
if(enter_price.contains("إلى")){
var splitterx="إلى"
val split_strx=enter_price.split(splitterx)
enter_price=split_strx[0]
}else {
var splitterx=" "
val split_strx=enter_price.split(splitterx)
enter_price=split_strx[0]
}
//set percent,new amount
//calculate percent/profit and advice
if(currency=="الجنيه المصرى"){
url_link = "http://egypt.gold-price-today.com/"
}
if(currency=="الريال السعودي"){
url_link = "http://saudi-arabia.gold-price-today.com/"
}
if(currency=="الدرهم الإماراتى"){
url_link = "http://united-arab-emirates.gold-price-today.com/"
}
if(currency=="الدينار الكويتى"){
url_link = "http://kuwait.gold-price-today.com/"
}
//start thread to get current price
var catch_new_amount=StringBuilder()
var catch_percent=StringBuilder()
Thread(Runnable {
var init_recent_price=StringBuilder()
try{
val doc = Jsoup.connect(url_link).get()
val table = doc.select("table")[0]
val tbody = table.select("tbody")
val rows = tbody.select("tr")
for (i in rows.indices) {
val row = rows[i]//
val cols = row.select("td")
//karat 21
if (i == 2 ) {
karat_recent_price = cols[0].text()
if(karat_recent_price.contains("إلى")){
var splitter="إلى"
val split_str=karat_recent_price.split(splitter)
karat_recent_price=split_str[0]
init_recent_price.append(karat_recent_price) //show karat price text
}else {
var splitter=" "
val split_str=karat_recent_price.split(splitter)
karat_recent_price=split_str[0]
init_recent_price.append(karat_recent_price) //show karat price text
}
}
//karat 18
if (i == 3 ) {
karat_recent_price = cols[0].text()
if(karat_recent_price.contains("إلى")){
var splitter="إلى"
val split_str=karat_recent_price.split(splitter)
karat_recent_price=split_str[0]
init_recent_price.append(karat_recent_price) //show karat price text
}else {
var splitter=" "
val split_str=karat_recent_price.split(splitter)
karat_recent_price=split_str[0]
init_recent_price.append(karat_recent_price) //show karat price text
}
}
//karat 24
if (i == 0 ) {
karat_recent_price = cols[0].text()
if(karat_recent_price.contains("إلى")){
var splitter="إلى"
val split_str=karat_recent_price.split(splitter)
karat_recent_price=split_str[0]
init_recent_price.append(karat_recent_price) //show karat price text
}else {
var splitter=" "
val split_str=karat_recent_price.split(splitter)
karat_recent_price=split_str[0]
init_recent_price.append(karat_recent_price) //show karat price text
}
}
//inv_amount[index] , inv_enter_price[index] , karat_recent_price
var int_amount=amount
// new_amount=(int_amount * int_recent_price_string / int_enter_price).toString()
new_amount= karat_recent_price
catch_new_amount.append(new_amount)
if(new_amount > int_amount){
var inc=new_amount.toFloat() - int_amount.toFloat()
var percent_inc=(inc/int_amount.toFloat())* 100
percent=percent_inc.toString()
init_percent_string=percent
catch_percent.append(percent)
}else {
var dec=int_amount.toFloat() - new_amount.toFloat()
var percent_dec=(dec/int_amount.toFloat()) * 100
percent=percent_dec.toString()
init_percent_string=percent
catch_percent.append(percent)
}
}//end for
}
catch(e: IOException){
e.printStackTrace()
}
// runOnUiThread{}
}).start()
//id,start_date,enter_price,amount,currency,karat,percent,profit
val emp= InvestModelClass(
start_date = start_date,
enter_price = enter_price,
amount = amount,
currency = currency,
karat = karat,
new_amount = catch_new_amount.toString(),
percent = catch_percent.toString()
)
invList.add(emp)
} while (cursor.moveToNext())
}
return invList
}
ListInvests.kt
package com.example.parsehtml
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.view.View
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.list_invests.*
import kotlinx.android.synthetic.main.startinvest_main.*
class ListInvests : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.startinvest_main)
button.setOnClickListener(){
intent = Intent(this,MainActivity::class.java)
startActivity(intent)
}
//creating the instance of DatabaseHandler class
val databaseHandler: DatabaseHandler= DatabaseHandler(this)
//calling the viewEmployee method of DatabaseHandler class to read the records
//id,start_date,enter_price,amount,currency,karat,percent,profit
val inv: List<InvestModelClass> = databaseHandler.allInvestments()
val inv_startdate = Array<String>(inv.size){"0"}
val inv_enter_price = Array<String>(inv.size){"null"}
val inv_amount = Array<String>(inv.size){"null"}
val inv_currency = Array<String>(inv.size){"null"}
val inv_karat = Array<String>(inv.size){"null"}
val inv_new_amount=Array(inv.size){"null"}
val inv_percent=Array(inv.size){"null"}
var index = 0
for(e in inv){
inv_startdate[index] = e.start_date.toString()
inv_enter_price[index] = e.enter_price.toString()
inv_amount[index] = e.amount.toString()
inv_currency[index] = e.currency.toString()
inv_karat[index] = e.karat.toString()
inv_new_amount[index]=e.new_amount.toString()
inv_percent[index]=e.percent.toString()
index++
}
//creating custom ArrayAdapter
//id,start_date,enter_price,amount,currency,karat,percent,profit
val myListAdapter = InvestListAdapter(this,inv_startdate,inv_enter_price,inv_amount,inv_currency,inv_karat,inv_new_amount,inv_percent)
listView.adapter = myListAdapter
}//end oncreate
}
InvestModelClass.kt
package com.example.parsehtml
//id,start_date,enter_price,amount,currency,karat,percent,profit
class InvestModelClass ( val start_date:String ,val enter_price:String, val amount: String,val currency:String,val karat:String,val new_amount:String,val percent:String)
I am trying to read data from my firebase realtime database to a TextView. But every time it shows null in TextView. I want to read single user data. I want to read data when user give input.
My Data Structure look like this..
{
"Date": {
"04-10-2019": {
"-LqR-e2UJLJCccqfgGi1":{
address: Dhaka
date: 04-10-2019
name: Mark
phoneNo: 017#######
serialNo: -LqR-e2UJLJCccqfgGi1
type: New
},
},
"05-10-2019": {
"-LqU-e2UJLJCDcqfgGi9":{
address: Dhaka
date: 04-10-2019
name: Tony
phoneNo: 017#######
serialNo: -LqU-e2UJLJCDcqfgGi9
type: OLd
},
}
}
The code that I am trying.
class Info(
val serialNo: String? = "",
val name: String = "",
val address: String = "",
val phoneNo: String = "",
val date: String = "",
var type: String = ""
)
private fun saveInfo() {
// Edit Text Field
val name = editTextName.text.toString().trim()
if (name.isEmpty()) {
editTextName.error = "Please Enter Your Name"
return
}
val address = editTextAddress.text.toString().trim()
if (address.isEmpty()) {
editTextAddress.error = "Please Enter Your Address"
return
}
val phoneNo = editTextPhoneNo.text.toString().trim()
if (phoneNo.isEmpty()) {
editTextPhoneNo.error = "Please Enter Your Phone Number"
return
}
val date = dateText.text.toString().trim()
//Radio Button
var type = ""
when {
checkboxNew.isChecked -> type += "New"
checkboxOld.isChecked -> type += "Old"
radioGroup.checkedRadioButtonId <= 0 -> {
Toast.makeText(applicationContext, "Please Check New or Old", Toast.LENGTH_LONG)
.show()
return
}
}
val current = LocalDateTime.now()
val formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy")
val formatted = current.format(formatter)
val myRef = FirebaseDatabase.getInstance().getReference("Date").child(formatted)
myRef.orderByChild(formatted).startAt("28-09-2019").endAt("31-12-2070")
val patientId = myRef.push().key
val patient = Info(patientId, name, address, phoneNo, date, type)
myRef.child((patientId).toString()).setValue(patient).addOnCompleteListener {
Toast.makeText(applicationContext, "Info saved Successfully", Toast.LENGTH_LONG).show()
myRef.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
for (data in dataSnapshot.children) {
val user = data.child(formatted).value.toString()
dataText.text = user
}
}
override fun onCancelled(error: DatabaseError) {
}
})
}
}
I want to show the data into a textview when the user give input and hit a button.
If you are trying to read the date attribute from the database then change this :
val user = data.child(formatted).value.toString()
Into this:
val user = data.child("date").value.toString()
Inside the child() you need to pass the name of the attribute.
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)
}
}
}
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