I need you to help me to solve this problem:
The problem is that I want to read a String called coins from the database of Firebase and then turn it into an Integer value. Then when I push a button I want to add 1 to coins and after that, I turn it back into a String value to save it in the database.
So I tried to do this by using onDataChange to read the data and then use
int score = Integer.parseInt(coins) to turn it into an Integer value called score.
After that, I used onClickListener to add 1 to the integer, but Android Studio tells me:
Cannot resolve score
I don't know how to solve this issue so I would be so happy if you could help me with that thing.
This is my code :
public class HomeFragment extends Fragment {
public HomeFragment() {
// Required empty public constructor
}
//firebase
FirebaseAuth firebaseAuth;
FirebaseUser user;
FirebaseDatabase firebaseDatabase;
DatabaseReference databaseReference;
StorageReference storageReference;
//init view
ImageButton addCoinsBtn;
TextView coinsTv;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view =inflater.inflate(R.layout.fragment_home, container, false);
//init firebase
firebaseAuth = FirebaseAuth.getInstance();
user = firebaseAuth.getCurrentUser();
firebaseDatabase = FirebaseDatabase.getInstance();
databaseReference = firebaseDatabase.getReference("Users");
storageReference = getInstance().getReference();//firebase storage reference
coinsTv=(TextView)view.findViewById(R.id.coinsTv);
addCoinsBtn=(ImageButton)view.findViewById(R.id.add_coins);
Query query = databaseReference.orderByChild("email").equalTo(user.getEmail());
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
//check until required data get
for (DataSnapshot ds : dataSnapshot.getChildren()){
//get data
String coins = ""+ds.child("coins").getValue();
int score = Integer.parseInt(coins);
//set data
coinsTv.setText(score);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
addCoinsBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference coins = database.getReference("Users/"+ user.getUid() +"/coins");
Integer score = score + 1;
String scorefinal = Integer.toString(score);
coins.setValue(scorefinal);
}
});
return view;
}
}
Thank you very much for all your bits of help.
This is a basic scoping problem: variables only exist in the scope where you declare them.
So the int score that you declare in onDataChange is not available in the onClick method anymore.
And the Integer score that you declare in onClick is a new variable, which means that Integer score = score + 1; won't work, because the score on the right-hand side doesn't exist/have a value.
The solution is to declare score one level higher, as a member field of your `` class:
Integer score = -1;
Query query = databaseReference.orderByChild("email").equalTo(user.getEmail());
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()){
String coins = ""+ds.child("coins").getValue();
score = Integer.parseInt(coins);
coinsTv.setText(score);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});
addCoinsBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference coinsRef = database.getReference("Users/"+ user.getUid() +"/coins");
score = score + 1;
String scorefinal = Integer.toString(score);
coinsRef.setValue(scorefinal);
}
});
I'd highly recommend storing the value as a number in the database, as it saves you constantly converting from string to integer and back. If you do this, the above code becomes:
Integer score = -1;
Query query = databaseReference.orderByChild("email").equalTo(user.getEmail());
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()){
score = ds.child("coins").getValue(Integer.class);
coinsTv.setText(score);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});
addCoinsBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference coinsRef = database.getReference("Users/"+ user.getUid() +"/coins");
coinsRef.setValue(score+1);
}
});
Related
The data from the Realtime Database Firebase does not appear in textview. I've looked for similar problems here, but I haven't solved them. I'd appreciate it if you could help me solve this problem.
firebase structure:
"state" : {
"open_close" : "open",
"weight" : 2500
}
java code:
public class SubActivity extends AppCompatActivity {
TextView tvWeight;
TextView tvOpen_close;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sub);
tvWeight = findViewById(R.id.textView_weight);
tvOpen_close = findViewById(R.id.textView_open_close);
final DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("state");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
String value = dataSnapshot.child("open_close").getValue(String.class);
int weight = dataSnapshot.child("weight").getValue(int.class);
tvWeight.setText(weight);
tvOpen_close.setText(value);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
There is no need of for loop ,you can directly access it like this.
public class SubActivity extends AppCompatActivity {
TextView tvWeight;
TextView tvOpen_close;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sub);
tvWeight = findViewById(R.id.textView_weight);
tvOpen_close = findViewById(R.id.textView_open_close);
final DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("state");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String value = dataSnapshot.child("open_close").getValue(String.class);
int weight = dataSnapshot.child("weight").getValue(int.class);
tvWeight.setText(weight);
tvOpen_close.setText(value);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
String value = snapshot.child("open_close").getValue(String.class);
int weight = snapshot.child("weight").getValue(Integer.class);
You are already iterating over children from your snapshot. You don't need to get to the parent snapshot to get child values. Use the iterated value of your snapshot and get values from it. Change your code to above.
Edit
Also if you don't have many nodes same as state I don't see any point of iterating over children.
If your database contain only one node as
`"state" : {
"open_close" : "open",
"weight" : 2500
}`
then don't iterate over it. Just call it directly as below:
final DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String value = dataSnapshot.child("state").child("open_close").getValue(String.class);
int weight = dataSnapshot.child("state").child("weight").getValue(Integer.class);
tvWeight.setText(weight);
tvOpen_close.setText(value);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
onCreate() method is never executed. I just want to take the below data to 4 TextViews. "Detail" is the model class.
No errors are shown when running the app.
view_temp is an activity.
this is firebase realtime db
this is the java class
`public class view_temp extends AppCompatActivity {
private view_temp viewTemp;
public Detail detail;
private TextView roomtemp, roomhuminity, bodypulse, bodytemp;
private DatabaseReference mDatabase;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_temp);
mDatabase = FirebaseDatabase.getInstance().getReference("heat-stroke-device");
roomtemp = (TextView) findViewById(R.id.txt_room_temp);
roomhuminity = (TextView) findViewById(R.id.txt_huminity_temp);
bodypulse = (TextView) findViewById(R.id.txt_body_pulse);
bodytemp = (TextView) findViewById(R.id.txt_body_temp);
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
detail = postSnapshot.getValue(Detail.class);
String rtemp = detail.getRoomtemp();
String rhumidity = detail.getRoomhumidity();
String bpulse = detail.getBodypulse();
String btemp = detail.getBodytemp();
roomtemp.setText(rtemp);
roomhuminity.setText(rhumidity);
bodypulse.setText(bpulse);
bodytemp.setText(btemp);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getMessage());
}
});
}
}`
There is no need to add the name of the project in the getReference() method. To get those names and the corresponding values correctly, please use the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String name = ds.getKey();
double value = ds.getValue(Double.class);
Log.d("TAG", name "/" + value);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore potential errors!
}
};
rootRef.addListenerForSingleValueEvent(valueEventListener);
The result in the logcat will be:
RoomHumi/86.0
RoomTemp/30.8
bodyPulse/126.0
bodyTemp/29.0
If the keys are always fixed, then simply use:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
double roomHumi = dataSnapshot.child("RoomHumi").getValue(Double.class);
Log.d("TAG", "RoomHumi" "/" + valueroomHumi);
double roomTemp = dataSnapshot.child("RoomTemp").getValue(Double.class);
Log.d("TAG", "RoomTemp" "/" + roomTemp);
double bodyPulse = dataSnapshot.child("bodyPulse").getValue(Double.class);
Log.d("TAG", "bodyPulse" "/" + bodyPulse);
double bodyTemp = dataSnapshot.child("bodyTemp").getValue(Double.class);
Log.d("TAG", "bodyTemp" "/" + bodyTemp);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore potential errors!
}
};
rootRef.addListenerForSingleValueEvent(valueEventListener);
And you'll have the same result in the logcat.
Just change your line
mDatabase = FirebaseDatabase.getInstance().getReference("heat-stroke-device");
to
mDatabase = FirebaseDatabase.getInstance().getReference();
Note: You do not need to put your database name into reference.
I want to create an "edit user profile" page on Android Studio. The user(which is logged in obviously) can go in and edit user info such as weight and age. Here is how my firebase database is set up:
The database
In this case, a user who is logged in as "Raxor2k", wants to change he`s info such as Age and Weight.
I have made a function that queries the database, and it manages to reach the "AdditionalUserInfo" table which is good. But the next task is to reach those specific values that belong to the logged-in user.
here is the code:
public class UserSettingsActivity extends AppCompatActivity {
private Button mEditInfoButton;
private TextView usernameField;
private EditText ageField, weightField;
private DatabaseReference dbUsernames;
DatabaseReference the_additional_userInfo_table = FirebaseDatabase.getInstance().getReference("AdditionalUserInfo");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_settings);
ageField = (EditText) findViewById(R.id.ageID);
weightField = (EditText) findViewById(R.id.weightID);
mEditInfoButton = (Button) findViewById(R.id.editButton);
usernameField = (TextView) findViewById(R.id.usernameTextViewID);
mEditInfoButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
QueryUserInfo();
}
});
}
public void QueryUserInfo(){
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference the_additional_userInfo_table = database.getReference("AdditionalUserInfo");
//Query query =the_additional_userInfo_table.child("username");
the_additional_userInfo_table.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Toast.makeText(UserSettingsActivity.this, "User exists!", Toast.LENGTH_SHORT).show();
// dataSnapshot is the "issue" node with all children with id 0
for (DataSnapshot issue : dataSnapshot.getChildren()) {
// do something with the individual "issues"
}
if(!dataSnapshot.exists()){
Toast.makeText(UserSettingsActivity.this, "nooooo user!", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
To get the data under AdditionalUserInfo that corresponds to a specific user, you need to use a query that looks like this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference additionalUserInfoRef = rootRef.child("AdditionalUserInfo");
Query userQuery = additionalUserInfoRef.orderByChild("username").equalTo("Raxor2k");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
Map<String, Object> map = new HashMap<>();
map.put("user-age", "30");
map.put("user-weight", "30");
ds.getRef().updateChildren(map);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
userQuery.addListenerForSingleValueEvent(valueEventListener);
The result in your database will be the change of both properties from 25 to 30. Since you didn't add the database as a text, file I have used in the query he user name but a more elegant way of querying the database would be to use the uid.
Query userQuery = additionalUserInfoRef.orderByChild("user-id").equalTo("IXL ... Eoj");
I am having trouble with my Firebase code to add a contact to a user profile. This exact code used to work fine, and now as of today it gets itself into an infinite loop and creates contacts repeatedly until I force kill the application. I can't work out where the loop is, or what may have changed!
Code:
public class AddContacts extends AppCompatActivity {
private EditText addContactNumber;
private Button btnAddContact;
private String userResult, searchPhone, ping_userID;
private FirebaseAuth pingAuth;
DatabaseReference ref;
private FirebaseAuth.AuthStateListener pingAuthListener;
addContactNumber = (EditText) findViewById(R.id.addContactNumber);
btnAddContact = (Button) findViewById(R.id.btnAddContact);
btnAddContact.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
searchPhone = addContactNumber.getText().toString();
ref = FirebaseDatabase.getInstance().getReference().child("Profiles");
ref.orderByChild("Phone").equalTo(searchPhone).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot datas : dataSnapshot.getChildren()) {
userResult = datas.getKey();
if (userResult != null) {
ping_userID = pingAuth.getCurrentUser().getUid();
DatabaseReference newContact = FirebaseDatabase.getInstance().getReference().child("Profiles").child(ping_userID).child("Contacts");
newContact.setValue(userResult);
DatabaseReference newContactPing = FirebaseDatabase.getInstance().getReference().child("Profiles").child(ping_userID).child("Contacts").child(userResult).child("PingStatus");
newContactPing.setValue(false);
DatabaseReference addRef = FirebaseDatabase.getInstance().getReference().child("Profiles").child(userResult).child("Name");
addRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String resultName = dataSnapshot.getValue(String.class);
DatabaseReference addContactName = FirebaseDatabase.getInstance().getReference().child("Profiles").child(ping_userID).child("Contacts").child(userResult).child("Name");
addContactName.setValue(resultName);
Toast.makeText(getBaseContext(), "User: " + resultName + " added successfully.", Toast.LENGTH_SHORT).show();
ref.removeEventListener(this);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
} else {
Toast.makeText(getBaseContext(), "User not found.", Toast.LENGTH_SHORT).show();
ref.removeEventListener(this);
break;
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
}
Also, perhaps as an aside, it never triggers the "User not found" event, even if I enter details that are not in the database.
Any ideas? I am sure it is staring me in the face but I don't see it.
#Peter Haddad Database as requested:
MyAppDatabase
-Profiles
-BCsuC4XAZqVhWj
-Name: "Simon"
-Phone: 123456
-Contacts
-pnYn1NhzzNQAm
-Name: "Bill"
-PingStatus: false
-pnYn1NhzzNQAm
-Name: "Bill"
-Phone: 987654
-Contacts
-BCsuC4XAZqVhWj
-Name: "Simon"
-PingStatus: false
Use addListenerForSingleValueEvent instead of addValueEventListener in both the cases.
I am developing an android recipe app, User's have the option to only view vegan recipes. I am using Firebase as my Database where I am storing a variable "vegan", in my activity which displays the recipes I am retrieving the value of "vegan" from my database, which can be either "yes" or "no" (line: 54) and then the if statement (line: 65) checks if the user want's vegan recipes or not, however vegan = user.Vegan; does not seem to be changing the variable vegan, I know I am getting the value from the database but it won't change the value of vegan, can anyone tell me where I'm going wrong?
public class SwipeActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private DatabaseReference mRecipeReference;
private DatabaseReference newRef;
private DatabaseReference myRef3;
private DatabaseReference veganRef;
private TextView editTextName;
private TextView editTextCategory;
private ImageView profileImageView;
private ImageButton Back;
private ImageButton Like;
private ImageButton Dislike;
private DatabaseReference databaseReference;
private DatabaseReference userRef;
String imgURL;
String recipeKey;
Map<String, Recipe> likedRecipes = new HashMap<String,Recipe>();
String user = FirebaseAuth.getInstance().getCurrentUser().getUid();
String vegan = "no"; //Here is the variable declaration
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swipe);
databaseReference = FirebaseDatabase.getInstance().getReference();
userRef = FirebaseDatabase.getInstance().getReference().child("user").child(user);
mRecipeReference = FirebaseDatabase.getInstance().getReference().child("recipe");
editTextName = (TextView) findViewById(R.id.editTextName);
editTextCategory = (TextView) findViewById(R.id.editTextCategory);
profileImageView = (ImageView) findViewById(R.id.profileImageView);
Back = (ImageButton) findViewById(R.id.Back);
Back.setOnClickListener(this);
Like = (ImageButton) findViewById(R.id.Like);
Like.setOnClickListener(this);
Dislike = (ImageButton) findViewById(R.id.Dislike);
Dislike.setOnClickListener(this);
}
#Override
public void onStart() {
super.onStart();
ValueEventListener userListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
vegan = user.Vegan; //Here I am retrieving the string from firebase database, which is either "yes" or "no"
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
// ...
}
};
userRef.addValueEventListener(userListener);
if (vegan == "yes") { //Here I am checking if the user is vegan or not
veganRef = databaseReference.child("recipe");
veganRef.orderByChild("Category").equalTo("Vegan").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot recipeSnapshot : dataSnapshot.getChildren()) {
Recipe recipe = recipeSnapshot.getValue(Recipe.class);
recipeKey = recipeSnapshot.getKey();
editTextName.setText(recipe.Name + ", " + recipe.Calories);
editTextCategory.setText(recipe.Category);
imgURL = recipe.Img;
Picasso.with(getApplicationContext()).load(imgURL)//download URL
.placeholder(R.drawable.placeholder_image)//use default image
.error(R.drawable.placeholder_image)//if failed
.into(profileImageView);//imageview
likedRecipes.put(recipeKey, recipe);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
}
});
}
}
}
The problem is more than likely that onDataChange hasn't been called by time you check vegan in that if statement. Callbacks like that are asynchronous so you will need to wait for callback before performing any logic that's dependent on result.
In general what you're running in to is something many people moving to Firebase from SQL background encounter when trying to map over "joins" like this to the nested queries that Firebase requires. Probably outside scope of this particular question but use of RxJava makes managing set of operations like this much easier (for example that have async responses and 2nd query needs to use response of first one).
In your onStart() do something like this
#Override
public void onStart() {
super.onStart();
ValueEventListener userListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
vegan = user.Vegan;
if (vegan == "yes") { //Here I am checking if the user is vegan or not
veganRef = databaseReference.child("recipe");
veganRef.orderByChild("Category").equalTo("Vegan").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot recipeSnapshot : dataSnapshot.getChildren()) {
Recipe recipe = recipeSnapshot.getValue(Recipe.class);
recipeKey = recipeSnapshot.getKey();
editTextName.setText(recipe.Name + ", " + recipe.Calories);
editTextCategory.setText(recipe.Category);
imgURL = recipe.Img;
Picasso.with(getApplicationContext()).load(imgURL)//download URL
.placeholder(R.drawable.placeholder_image)//use default image
.error(R.drawable.placeholder_image)//if failed
.into(profileImageView);//imageview
likedRecipes.put(recipeKey, recipe);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
// ...
}
};
userRef.addValueEventListener(userListener);
}