When the user clicks on the "find random opponent" button, I would like the User class in Parse to create a new field (called readyToPlay) and set the value to true. Then, start a new activity where the user is randomly matched with other users whose variable readyToPlay is also set to true.
The problem is when I click the "find random opponent" button, no new field is created. I looked at the Parse documentation and cant figure out what I am doing wrong. I have attached the relevant code below.
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, FindRandomOpponent.class);
ParseUser currentUser = ParseUser.getCurrentUser();
currentUser.put(ParseConstants.KEY_READY_TO_PLAY, true);
currentUser.saveInBackground()
startActivity(intent);
}
Edit1: I called the saveInBackground method, but my user database didn't update.
Edit2: I am currently signed in as a user, so the device does have access to the internet.
This will help. It will check your user is saved or give exception for further investigation.
ParseUser currentUser = ParseUser.getCurrentUser();
currentUser.put(ParseConstants.KEY_READY_TO_PLAY, true);
currentUser.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Intent intent = new Intent(MainActivity.this, FindRandomOpponent.class);
startActivity(intent);
} else {
//log error
}
}
});
You need to call the saveInBackground() method on your currentUser object.
Reference: Parse Docs on saving objects
Related
How i can in this code
#Override
protected void onStart() {
super.onStart();
//if the user is already signed in
//we will close this activity
//and take the user to profile activity
if (mAuth.getCurrentUser() != null) {
finish();
startActivity(new Intent(this, ActivitySplash.class));
}
}
make check whether the child (userId) is set to ON / OFF and if ON then we run the code
if (mAuth.getCurrentUser() != null) {
finish();
startActivity(new Intent(this, ActivitySplash.class));
}
if OFF then we show a specific activity.
My database
As #FrankvanPuffelen said, you should spend some time reading docs, it would help you write code yourself, still I am briefing the things for you here. It should make things more clear.
Reading from database is done by correctly referencing your desired node from the database and then using the correct eventListener. There are 3 types of eventListeners present, singleValueEventListener, valueEventListener and childEventListener.
Read more about each of them in detail in docs.
This answer can also help you understand childEventListeners.
To retrieve the value of status node you have to go sequentially through your database parent nodes, that are users and that uid with value nfe....
So in code it would look something like this:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("users").child(uid);
// uid has the value nfe...
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String status = dataSnapshot.child("status").getValue(String.class);
// compare the value of status here and do what you want
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG, "onCancelled", databaseError.toException());
}
});
I have a key 'newUser' within my firebase database, which can be set to either 'true' or 'false', as shown here:
firebase database structure click here for screenshot
I have referenced to the database within a LoginActivity class, upon clicking a login button the userLogin method is called, within this method I perform the following:
mDatabase.orderByChild("email").equalTo(email)
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot singleSnapshot: dataSnapshot.getChildren()){
String newUser = singleSnapshot.getValue(User.class).newUser;
if(newUser.equals("true")){
Log.d("Yes!", "this is a new user");
startnewActivity(singleSnapshot);
}else {
Log.d("No!", "this is an old user");
startnewActivity(singleSnapshot);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Note that equalTo(email) ... email is a local variable which grabs the text within the textfield where the user inputs the email.
the startnewActivity method is defined below, to initialise the activities dependent on whether the user is new or not:
private void startnewActivity(DataSnapshot singleSnapshot) {
String s = singleSnapshot.getValue(User.class).newUser;
if (s.equals("true")) {
Intent i = new Intent(LoginActivity.this, AudiometryNewUser.class);
singleSnapshot.getRef().child("newUser").setValue("false");
Log.d("iterated!?", "");
startActivity(i);
return;
}
else if(s.equals("false")){
Intent i = new Intent(LoginActivity.this, MainDashboard.class);
Log.d("iterated", "");
startActivity(i);
}
}
my intention is when the user is a newUser = true, then they will be taken to the welcome screen AudiometryNewUser, and for the newUser value to adopt "false".
The result however is that the user is ALWAYS taken to the dashboard, even if they are a new user. If they were a newUser and logged in, upon clicking the back button the user is navigated to the expected welcome new user activity.
on top of this, several instances of the activity are sometimes launched.
I just wondered if anyone could explain why this was happening, and what am I failing to see?
If clarity is needed please say so, I'll do my best to update the post.
Many thanks in advance.
From experimentation and further reading:
The addValueEvent listener is called for every value changed, therefore when setting the singleSnapShot to false this was in affect changing the value, thus the listener was being called again. Instead the correct approach was to user a Listener for a single value event.
When swapped for this method, the solution works as expected.
Im trying to save user information in Firebase Database but a strange behavior happens that make the Save button to restart the same activity not the Intent that i made for the next activity .
public void userData () {
user.setFName(Fname.getText().toString());
user.setLName(Lname.getText().toString());
user.setEmail(Email.getText().toString());
user.setAddress(userAddress.getText().toString());
user.setPassword(UserInfo.getString("Password", ""));
user.setID(CicID.getText().toString());
user.setUsername(Usnm.getText().toString());
if (bAdmn.isChecked()) user.setMajor("Business Administrator");
if (BTech.isChecked()) user.setMajor("Business Tech");
if (masscom.isChecked()) user.setMajor("Mass Com");
if (Eng.isChecked()) user.setMajor("Engineering");
final String us = user.getUsername();
Log.i("Username", us);
MyDatabase1.child("USERS").child(us).setValue(user);
Intent i = new Intent(getApplicationContext() , chooseCoursesActivity.class);
startActivity(i);
}
that is the method for save button , Note that i want to update the user information in a profile Activity if the user wants to change his First name or Last name or something .
But after Clicking save button , the data is saved correctly but the intent never done . it recreate the same Activity .
in the Login activity there is aLogin button which checks username and password then attempt to log in based on data ,if login successful it goes to that Profile Activity .
Save button in Profile Activity re Do the method in Login button in Login Activity which checks everything and goes to Profile Activity which what causing the Re Create Problem .
Here is the code for login button :
MyDatabase = FirebaseDatabase.getInstance().getReference();
MyDatabase.child("USERS").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
boolean exists = false;
for (DataSnapshot child : dataSnapshot.getChildren()) {
final Map<String, Object> model = (Map<String, Object>) child.getValue();
if (model.get("username").equals(Username.getText().toString())) {
exists = true;
Log.i("USername"," Correct");
if(exists){
MyDatabase.child("USERS").orderByChild("username").equalTo(Username.getText().toString())
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child :dataSnapshot.getChildren()){
Log.i("Password",child.getValue().toString());
Log.i( "Password",child.child("password").toString());
if(password.getText().toString().equals(child.child("password").getValue())){
Log.i("LOGIN","Success");
loginsuccessful = true ;
if(loginsuccessful){
saveCredntials(Username.getText().toString(),password.getText().toString());
Intent i2 = new Intent(getApplicationContext(), ProfileActivity.class);
i2.putExtra("loginStats",IsLoggedIn);
i2.putExtra("Username",Un);
i2.putExtra("Password",Pw);
startActivity(i2);
finish();}
}else{
Log.i("LOGIN","Failed");
loginsuccessful= false ;
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
}
});
}
break;
}else {
Log.i("LOGIN","FAiled");
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Sorry for making this too long but i dont know the problem .
I just solved this problem! According to your case, please avoid using addValueEventListener, because it will listen to all changes you make to the database. That's why every time you make any change to the database, the code in the addValueEventListener (startActivity) will be executed no matter you call that login function or not.
My suggestion is using addListenerForSingleValueEvent instead of addValueEventListener (Make sure you change ALL the addValueEventListener in your Android project to addListenerForSingleValueEvent), or you can even remove the listener if you don't really need it. I don't know if it is a good design, but it should be able to solve your problem.
Avoid putting startActivity on a firebase listener. startActivity execute every time a value is added or removed from firebase database.
I use a Parse database. I would like to have access for simple users and an admin user. The would be that each user could see only his/her own data but the admin user could see all of users' data.
I create a ParseUser, and if the current user is equal with it, it should be known it is the admin user.
I get the following error:
java.lang.IllegalArgumentException: cannot setReadAccess for a user with null id
I think the mistakes are with if function (never become true) and this: acl.setReadAccess(ADMIN,true);
Could anyone suggest something?
ParseUser ADMIN = new ParseUser();
ADMIN.setUsername("ADMIN3");
ADMIN.setPassword("a");
// Create a post.
AnywallPost post = new AnywallPost();
// Set the location to the current user's location
post.setLocation(geoPoint);
post.setText(text);
post.setUser(ParseUser.getCurrentUser());
ParseACL acl = new ParseACL();
// Give read accesses
if (ParseUser.getCurrentUser() == ADMIN) {
acl.setReadAccess(ParseUser.getCurrentUser(), true);
}
else
{
acl.setReadAccess(ParseUser.getCurrentUser(),true);
acl.setReadAccess(ADMIN,true);
}
post.setACL(acl);
// Save the post
post.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
dialog.dismiss();
finish();
}
});
I'm using parse.com Android sdk, in the parseUser I have added a column pointer to other data class named pointer. I access this data by:
ParseUser user=ParseUser.getCurrentUser();
ParseObject pointer= user.getParseObject("pointer");
pointer.fetchIfNeededInBackground(new GetCallback<ParseObject>() {
#Override
public void done(ParseObject parseObject, ParseException e) {
}
}
But I have a problem when I try to logout before doing this fetch. I logout by:
ParseUser.logOut();
and when this function is invoked the the app get locked.
You simply need to wrap this call to fetch in a check to see if there is still a logged in user:
ParseUser user = ParseUser.getCurrentUser();
if (user != null) {
// rest of your code here, as we have a currently logged in user
}