Home » Android » java – How to use snapshot result, in a firebase transaction-Exceptionshub

java – How to use snapshot result, in a firebase transaction-Exceptionshub

Posted by: admin February 24, 2020 Leave a comment

Questions:

0

I have a Scores node in my database. At the moment, I can update the score after a game. For the purposes of creating a leaderboard, I want to add the users username to the node as well. I have tried to use Transactions that take a snapshot, to get the current logged in username, that when the score is updated, the name will also be added to the Scores node.

I can retrieve the username using my transaction, but cant figure out how to pass this value, to the Scores node.

This is what I have so far, this code allows me to update the “Points” in the scores node, and allows me to retrieve the name of the logged in user, but not set this value in the Scores node of the database:

package com.example.securityapp;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.MutableData;
import com.google.firebase.database.Transaction;
import com.google.firebase.database.ValueEventListener;

import java.util.ArrayList;
import java.util.Collections;

public class industry_standards_questions extends AppCompatActivity {

    DatabaseReference databaseUsers, databaseUsername;
    FirebaseDatabase database = FirebaseDatabase.getInstance();
    FirebaseAuth mAuth;
    TextView stmnt;
    ImageView image_true, image_false;
    Button points, finished;
    Statements tfStatements;
    int statementsLength;
    ArrayList<Item> statementList;
    int currentStatement = 0;
    int grade = 0;
    String name;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_industry_standards_questions);

        databaseUsers = database.getReference("Scores");
        databaseUsername = database.getReference("Users");

        mAuth = FirebaseAuth.getInstance();
        FirebaseUser user = mAuth.getCurrentUser();
        stmnt = (TextView) findViewById(R.id.statement_TV);
        image_true = (ImageView) findViewById(R.id.trueImage);
        image_true.setFocusable(false);
        image_false = (ImageView) findViewById(R.id.falseImage);
        image_false.setFocusable(false);
        tfStatements = new Statements();
        statementsLength = tfStatements.tfStatements.length;
        statementList = new ArrayList<>();
        finished = (Button) findViewById(R.id.finish);
        points = (Button) findViewById(R.id.final_score);

        for (int i = 0; i < statementsLength; i++)
        {
            statementList.add(new Item(tfStatements.getStatement(i), tfStatements.getAnswer(i)));
        }
        Collections.shuffle(statementList);
        setStmnt(currentStatement);



    }

    // show Statement
    private void setStmnt(int number) {
        stmnt.setText(statementList.get(number).getStatement());
    }

    //check is answer is right
    private boolean checkAnswer(int number) {
        String answer = statementList.get(number).getAnswer();
        return answer.equals("true");
    }

    public void trueClicked(View view) {
        if (checkAnswer(currentStatement)) {
            grade++;
        }
        currentStatement++;
        if (currentStatement >= statementsLength) {
            score();
            return;
        }
        if (currentStatement <= statementsLength )
            setStmnt(currentStatement);
    }

    public void falseClicked(View view) {
        if (!checkAnswer(currentStatement)) {
            grade++;
        }
        currentStatement++;
        if (currentStatement >= statementsLength) {
            score();
            return;
        }
        if (currentStatement <= statementsLength )
            setStmnt(currentStatement);
    }



    public void score() {


        String id = mAuth.getCurrentUser().getUid();
        DatabaseReference score = databaseUsers.child(id).child("Points");
        DatabaseReference set_username = databaseUsers.child(id).child("Username");
        final DatabaseReference get_user_name = databaseUsername.child(id).child("username");



        final int pointsEarned = grade;


        score.runTransaction(new Transaction.Handler() {
                                 @Override
                                 public Transaction.Result doTransaction(MutableData mutableData) {
                                     System.out.println("You scored: " + pointsEarned);
                                     System.out.println("The current score is: " + mutableData.getValue(Integer.class));
                                     mutableData.setValue((mutableData.getValue() == null ? 0 : mutableData.getValue(Integer.class)) + pointsEarned);
                                     System.out.println("The new score is: " + mutableData.getValue(Integer.class));
                                     return Transaction.success(mutableData);
                                 }

                                 @Override
                                 public void onComplete(@Nullable DatabaseError databaseError, boolean b, @Nullable DataSnapshot dataSnapshot) {

                                 }
                             }
        );


        get_user_name.runTransaction(new Transaction.Handler() {

            @NonNull
            @Override
            public Transaction.Result doTransaction(@NonNull MutableData mutableData) {
                String name = mutableData.getValue(String.class);
                return Transaction.success(mutableData);
            }

            @Override
            public void onComplete(@Nullable DatabaseError databaseError, boolean b, @Nullable DataSnapshot dataSnapshot) {
                String username = dataSnapshot.getValue().toString();
            }

        });

        set_username.runTransaction(new Transaction.Handler() {
            @NonNull
            @Override
            public Transaction.Result doTransaction(@NonNull MutableData mutableData) {
                mutableData.setValue(name);
                return Transaction.success(mutableData);

            }

            @Override
            public void onComplete(@Nullable DatabaseError databaseError, boolean b, @Nullable DataSnapshot dataSnapshot) {


            }
        });


        Toast.makeText(this, "You scored " + grade + " points!", Toast.LENGTH_LONG).show();
        grade = 0;
    }






    public void FinishedOnClick (View view)
    {
        Intent intent_finished = new Intent(industry_standards_questions.this, industry_standards_rating_screen.class);
        startActivity(intent_finished);
        finish();
    }


}

How to&Answers:

When you want to add new User Data in the Scores. I suggest to use set() instead of runTransaction. As Frank Explained in his answer that runTransaction can be used update data from Database.

Map<String,int> points = new HashMap<String,int>();
points.put("Points", pointsEarned);
databaseUsers.child(id).setValue(points);