-1

The app is connected to Firebase and is using the Realtime database on the free spark plan. The app is based in kotlin.

This code properly stores the number of button presses across all devices and saves the number of presses after the application restarts, however I'm having trouble retrieving the number of times the button has been pressed from the database, to be displayed on screen.


    //private var database : DatabaseReference = FirebaseDatabase.getInstance().getReference("IncrementButton")
    
    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_second)

    val rootRef = FirebaseDatabase.getInstance().reference
    val pressedRef = rootRef.child("pressed")

    button_increment.setOnClickListener {
        pressedRef.setValue(ServerValue.increment(1));
    }

    val valueEventListener = object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {
            val pressed = dataSnapshot.getValue(Long::class.java)
            Log.d("TAG", "Button has been pressed $pressed times!")
        }

        override fun onCancelled(databaseError: DatabaseError) {
            Log.d("TAG", databaseError.getMessage()) //Don't ignore potential errors!
        }
    }
    pressedRef.addValueEventListener(valueEventListener)
}

Here is what I have in my data class:

data class IncrementButton(val pressed : Int? = null)

John Doe
  • 33
  • 5
  • We kind of need to know which part you're specifically stuck on to be able to answer effectively without writing a long tutorial. Is it how to react to button presses, how to update a property value, how to persist data, how to interact with the cloud so users on different devices can see the same data, etc? And then we need to know what specifically about that task you are stuck on. – Tenfour04 Jul 19 '21 at 20:24
  • Sorry, I'll be more specific. I want to know how to interact with cloud services so that the entire user base can see the button presses across all devices. I have the button set up to record presses, I just don't know how to add them all up together. I believe firebase would allow me to see how many times the button was pressed in total by everyone but I don't know how to go about implementing it. My app is already connected to firebase. – John Doe Jul 19 '21 at 21:37
  • This is actually quite possible. Do you need this functionality in Cloud Firestore or in the Firebase Realtime Database? Please respond with @AlexMamo – Alex Mamo Jul 20 '21 at 04:53
  • @AlexMamo Thank you for your response, I need this functionality in Firebase – John Doe Jul 22 '21 at 22:53
  • Which Firebase product? Firebase Cloud Firestore or the Firebase Realtime Database? These are two different products. – Alex Mamo Jul 23 '21 at 05:18
  • Hello @AlexMamo, I was aiming to use Firebase Realtime Database with the free Spark Plan – John Doe Jul 23 '21 at 19:37
  • Have you solved the issue? – Alex Mamo Jul 24 '21 at 09:11
  • @AlexMamo Unfortunately I have not. I've found a decent amount of videos about properly utilizing Firebase Realtime database, however I have yet to figure out how to use this information for my specific task. I will continue to research. – John Doe Jul 25 '21 at 01:36
  • Will it be helpful an answer now, with my particular approach? – Alex Mamo Jul 25 '21 at 08:18
  • @AlexMamo, yes your help would be very much appreciated! – John Doe Jul 25 '21 at 18:29

2 Answers2

1

You can simply use

val counter = 0 //class level variable(global)


button.setOnClickListener { 
    Log.d(TAG, "button clicked...increasing the counter")
    counter++
    updateTextOnScreen()
}

fun updateUI() {
    textView.text = counter.toString() 
}

Everytime the button is clicked by the user, this will print a log statement you can see in logcat. Also, it will update the user interface with the number of times user has clicked the button.

Shahzad Ansari
  • 317
  • 3
  • 10
  • 1
    This works only locally, op mentioned that the count has to take all the users interactions too. – javdromero Jul 19 '21 at 22:05
  • Thank you for your example Shahzad Ansari, but I believe this would only work for a single user and the counter would not save the amount of clicks after the app closes. – John Doe Jul 19 '21 at 22:31
1

Since you say that the button can be clicked by multiple users, there might be a situation in which two or even more users can click the button simultaneously. This means that you should implement a mechanism that can allow you to have consistent data. This can be done using transactions, as explained in my answer from the following post:

However, since a button click will always increment the counter by one, please see below an even simpler atomic solution:

button.setOnClickListener { 
    rootRef.child("counter").setValue(ServerValue.increment(1))
}

Edit:

You are getting the following error:

UninitializedPropertyAccessException: lateinit property rootRef has not been initialized

Because by the time you are using the rootRef the is not yet object initialized. So please make sure you call first:

val rootRef = FirebaseDatabase.getInstance().reference

Edit2:

I've seen you have added a similar question here. Maybe I didn't understand that in the first place, but you cannot update a counter atomically using a model Total class. There is no need for that. It's true that you can read the data and update it using a transaction, but for a simple increment, you should only use the above code. That means that you can only take a reference of the field that needs to be incremented and that's it. No need for any model classes. Model classes are used when you want to map an object from the database into an object of the particular class.

Edit3:

To display the newly added counter, please use the following lines of code:

val rootRef = FirebaseDatabase.getInstance().reference
val counterRef = rootRef.child("counter")
val valueEventListener = object : ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
        val counter = dataSnapshot.getValue(Long::class.java)
        Log.d("TAG", "counter: $counter")
    }

    override fun onCancelled(databaseError: DatabaseError) {
        Log.d("TAG", databaseError.getMessage()) //Don't ignore potential errors!
    }
}
counterRef.addValueEventListener(valueEventListener)

The output will always be the value of the incremented counter.

Edit4:

This is all you need:

//private lateinit var pressed : IncrementButton
//private var database : DatabaseReference = FirebaseDatabase.getInstance().getReference("IncrementButton")


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_second)

    val rootRef = FirebaseDatabase.getInstance().reference
    val pressedRef = rootRef.child("pressed")

    button_increment.setOnClickListener {
        pressedRef.setValue(ServerValue.increment(1));
    }

    val valueEventListener = object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {
            val pressed = dataSnapshot.getValue(Long::class.java)
            Log.d("TAG", "Button has been pressed $pressed times!")
        }

        override fun onCancelled(databaseError: DatabaseError) {
            Log.d("TAG", databaseError.getMessage()) //Don't ignore potential errors!
        }
    }
    pressedRef.addValueEventListener(valueEventListener)
}

Edit5:

When you remove:

private var database : DatabaseReference = FirebaseDatabase.getInstance().getReference("IncrementButton")

It makes sense to get this error:

"unresolved reference: database"

As the line of code:

database.child("pressed").setValue(ServerValue.increment(1))

Because this line is notcorrect. It should be:

pressedRef.setValue(ServerValue.increment(1))
// ^ ^ See the reference?

So use the exact code I have provided in the Edit4, nothing else. Besides that, your schema should look like this:

Firebase-root
  |
  --- pressed: 2 <- Not counter, not anything else. Just "pressed"

In this way, you won't get:

"Button has been pressed null times!"

You certainly get:

"Button has been pressed 2 times!"
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193