In my app there is an option for referrals, I am using the firebase database to update the wallet if referral code matched, but the problem is user account is credting successfully but agent account(who referred )is credting multiple times like over and over continuously and that's the issue,
public void checkreffercode() {
final String refferalcode = editText.getText().toString();
if (refferalcode.equals("")) {
Toast.makeText(ReferalActivity.this, "Refferal code is empty", Toast.LENGTH_LONG).show();
} else {
final DatabaseReference reffercoderef = FirebaseDatabase.getInstance().getReference().child("Reffercode");
final DatabaseReference agentwallet = FirebaseDatabase.getInstance().getReference();
final DatabaseReference userwalletstat = FirebaseDatabase.getInstance().getReference(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("Refferal");
final DatabaseReference userwallet = FirebaseDatabase.getInstance().getReference(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("walletcoin");
userwalletstat.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String statous = dataSnapshot.getValue(String.class);
if (statous == null) {
Toast.makeText(ReferalActivity.this, "data is null in Refferal", Toast.LENGTH_LONG).show();
} else if (statous.equals("notcredited")) {
//here check all the feild....
reffercoderef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.child(refferalcode).exists()) {
final String Uid = dataSnapshot.child(refferalcode).getValue(String.class);
userwallet.setValue(String.valueOf(5000));
agentwallet.child(Uid).child("walletcoin").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String agentbalance = dataSnapshot.getValue(String.class);
Integer agentbalinint = Integer.parseInt(agentbalance);
Integer updatedbalu = (agentbalinint + 5000);
agentwallet.child(Uid).child("walletcoin").setValue(String.valueOf(updatedbalu));
userwalletstat.setValue("credited");
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(ReferalActivity.this, "error on updating agent balance", Toast.LENGTH_LONG).show();
}
});
} else {
Toast.makeText(ReferalActivity.this, "Refferal code not found", Toast.LENGTH_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(ReferalActivity.this, "Database error on checking refferal code", Toast.LENGTH_LONG).show();
}
});
//last
} else {
Toast.makeText(ReferalActivity.this, "Both wallet has been credited", Toast.LENGTH_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(ReferalActivity.this, "Database error on checking account status", Toast.LENGTH_LONG).show();
}
});
}
}
public void updateref(View view) {
Button button=findViewById(R.id.refbutton);
final ProgressDialog progressDialog = new ProgressDialog(ReferalActivity.this);
progressDialog.setMessage("Please wait..");
progressDialog.getActionBar();
progressDialog.setCancelable(false);
progressDialog.show();
checkreffercode();
progressDialog.cancel();
}
Here is my xml code
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Refer code"
android:id="#+id/refercode"
android:inputType="textPersonName"
android:padding="20dp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Update"
android:onClick="updateref"
android:layout_gravity="center"
android:id="#+id/refbutton"
android:textColor="#51122e"/>
You are using ValueEventListener on userwalletstat reference. The problem is that with ValueEventListener is that, it gets called every time a value changes under userwalletstat ("referal") child. Inside your else if (statous.equals("notcredited")) condition, you are using another ValueEventListener in which you are setting setting the value like this userwallet.setValue(String.valueOf(5000));
So your first ValueEventListener gets activated because it's a ValueEventListener. So your code is kind of like a recusive function and it is bad. So in order to fix it, you should replace your ValueEventListeners with SingleValueEventListener. You can learn more about them here and scroll down to Read Data Once section.
Basically, you need to replace
userwalletstat.addValueEventListener(new ValueEventListener() {
with
userwalletstat.addListenerForSingleValueEvent(new ValueEventListener() {
and do the same for other listeners like :
reffercoderef.addListenerForSingleValueEvent(new ValueEventListener() {
agentwallet.child(Uid).child("walletcoin").addListenerForSingleValueEvent(new ValueEventListener() {
Also, I don't know how your data structure is setup but it is not a good idea to have a listener inside a listener inside a listener. Maybe you should reorganize your datastructure.
Related
I am trying to read some values from Firebase Real time database.
My structure looks like this:
and my code to retrieve the value("Wine and Dine"):
databaseReference.child("test").child("event_name").child("drinks")
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Object dataSnapshotObject = dataSnapshot.getValue(String.class);
if(dataSnapshotObject != null){
Toast.makeText(content, "Event Name: " + dataSnapshotObject.toString(), Toast.LENGTH_LONG).show();
}else
Toast.makeText(context,"null",Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
});
However, I only get a null response as the value. What could I be doing wrong?
You may remove .child("drinks") from the chain (and put it in later, as in code below)and if you want to make the dataSnapshotObject to String anyway, then you should retrieve it in a String.
Something like this:
String value = dataSnapshot.child("drinks").getValue(String.class);
Also check if your databaseReference looks something like this or not.
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
You can use addListenerForSingleValueEvent to get the value
Code sample:
FirebaseDatabase.getInstance().getReference().child("test").child("event_name").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
HashMap hashUser = (HashMap) dataSnapshot.getValue();
if (hashUser != null) {
String Drinks = hashUser.get("drinks").toString();
//Toast.makeText(this, Drinks , Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I want to retrieve houfxWvbwyVmbHX60IGjpNkZR9w2 key , How to do?
Here is the code for the same
mQuery = mfollowing.orderByChild("following").equalTo(user_id);
mQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
final String key = dataSnapshot.getKey();
mdatabaseUsers.child(user_id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
DatabaseReference newfollscreen = mdatabaseFollwer.child(key).child(newPost.getKey());
newfollscreen.child("screen").setValue(downloadUrl.toString());
newfollscreen.child("engagement").setValue("NA");
newfollscreen.child("url").setValue("NA");
newfollscreen.child("uid").setValue(user_id);
newfollscreen.child("name").setValue(dataSnapshot.child("name").getValue());
newfollscreen.child("image").setValue(dataSnapshot.child("image").getValue()).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()){
Toast.makeText(AddimageActivity.this, "Posted among your followers", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(AddimageActivity.this, "Error", Toast.LENGTH_SHORT).show();
}
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onCancelled (DatabaseError
databaseError){
}
});
Here is the Firebase database
second image
enter image description here
I tried using child data snapshot method but did not worked. Any help for this will be much appreciated.
Assuming you have a DataSnapshot that points to the children rhZ4...wt2, you can call snapsthot.getRef().toString() which will return you something like https://xxx.firebaseio.com/.../houfxWvbwyVmbHX60IGjpNkZR9w2/rhZ4...wt2. From there you can extract the parent key.
From your example, after you query the database using mQuery, inside onDataChange you have a DataSnapshot.
So calling dataSnapshot.getRef().toString() will give you https://xxx.firebaseio.com/.../houfxWvbwyVmbHX60IGjpNkZR9w2/rhZ4...wt2/following.
Code to extract the parent key (put it inside your 1st onDataChange):
String reference = dataSnapshot.getRef().toString();
String[] tokens = reference.split("/");
String parentKey = tokens[tokens.length - 3];
This parentKey should be your houfxWvbwyVmbHX60IGjpNkZR9w2.
I am setting the value of a child in Firebase, but when I get the value from Firebase the value is null. I don't understand why.
database.child("User").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int depositInteger = 0;
try {
depositInteger = Integer.parseInt(depositText.getText().toString().trim());
} catch (NumberFormatException e) {
if (depositText.equals("")) {
Toast.makeText(getActivity(), "Failed", Toast.LENGTH_SHORT).show();
}
}
database.child(user.getDisplayName()).child("deposit").setValue(depositInteger);
Long previousDeposit = dataSnapshot.child("User").child(user.getDisplayName()).child("deposit").getValue(Long.class);
System.out.println("VAAAALUE: " + previousDeposit);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
To set a value, you can use setValue() method directly on the reference like this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userRef = rootRef.child("Users").child(user.getDisplayName());
userRef.child("deposit").setValue(9); //Sets the value to 9
To get the value, please use the following code:
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int deposit = dataSnapshot.child("deposit").getValue(Integer.class);
Log.d("TAG", deposit);
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
userRef.addListenerForSingleValueEvent(eventListener);
Please see the correct DatabaseReference which contains Users and not only User as shown in your screen-shot.
According your database structure the child you should reference is Users and in your code you are calling User. Fix that mistake...
//Replace child tag by Users to fix the error
database.child("Users").addValueEventListener(new ValueEventListener() { ...
If there's something I'm struggling with it's how to write good looking code with asynchronous calls to Firebase. Below is the code for one of my functions that retrieves all users and the current user from Firebase and checks the distance between their chosen locations.
I can't really move each of the ValueEventListeners to separate functions since they all have to fire in succession.
How do I make this code look good?
private void getUsersToDisplay() {
// Get users to display from firebase
Log.w(TAG, "User fetch initialized");
DatabaseReference currentUserRef = mDatabase.getReference().child("users/" + mCurrentUser.getUid());
// Get current user from firebase
currentUserRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot currentUserSnapshot) {
// Get the users chosen location for use in distance calculation
final Double currentUserChosenLatitude =
Double.parseDouble(currentUserSnapshot.child("chosen_location/latlng/latitude").getValue().toString());
final Double currentUserChosenLongitude =
Double.parseDouble(currentUserSnapshot.child("chosen_location/latlng/longitude").getValue().toString());
DatabaseReference usersRef = mDatabase.getReference().child("users");
// Get all users from firebase
usersRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot allUsersSnapshot) {
// For all users in firebase
for (DataSnapshot userSnap : allUsersSnapshot.getChildren()) {
String userId = userSnap.getKey();
DatabaseReference userRef = mDatabase.getReference().child("users/" + userId);
// If the user isn't the current user
if (!userId.equals(mCurrentUser.getUid())) {
// Get the user's info from firebase
userRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot userSnapshot) {
Double userChosenLatitude =
Double.parseDouble(userSnapshot.child("chosen_location/latlng/latitude").getValue().toString());
Double userChosenLongitude =
Double.parseDouble(userSnapshot.child("chosen_location/latlng/longitude").getValue().toString());
float[] results = new float[1];
Location.distanceBetween(
currentUserChosenLatitude,
currentUserChosenLongitude,
userChosenLatitude,
userChosenLongitude,
results);
// If the user is within 10km of the current user, display it
if (results[0] < 10000) {
users.put(userSnapshot.getKey(), (String) userSnapshot.child("first_name").getValue());
mUserAdapter.add((String) userSnapshot.child("first_name").getValue());
Log.w(TAG, "User to display fetch complete");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "User to display fetch cancelled");
}
});
}
}
Log.w(TAG, "Users fetch completed");
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "Users fetch cancelled");
}
});
Log.w(TAG, "Current user fetch complete");
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "Current user fetch cancelled");
}
});
}
I write my code like this so it easier to read:
onCreate() {
dataRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
doSomething(dataSnapshot);
...
}
...
}
}
doSomething(DataSnapshot dataSnapshot) {
...
}
If I want a Firebase call to run after another Firebase call, I place it inside doSomething.
BUT, if that call doesn't have to run after each other (like "get current user" and "get all user" call from your sample code), I made it like this:
boolean firstCallDone = false;
boolean secondCallDone = false;
DataSnapshot firstDataSnapshot = null;
DataSnapshot secondDataSnapshot = null;
onCreate() {
firstRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
firstCallDone = true;
firstDataSnapshot = dataSnapshot;
if (firsCallDone && secondCallDone)
doSomething();
}
...
}
secondRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
secondCallDone = true;
secondDataSnapshot = dataSnapshot;
if (firsCallDone && secondCallDone)
doSomething();
}
...
}
}
doSomething() {
// do something with firstDataSnapshot and secondDataSnapshot
...
}
Hope this help.
{
users:
{
apple:
{
username : apple
email : apple#xy.com
uid : tyutyutyu
}
mango:
{
username : mango
email : mango#xy.com
uid : erererer
}
}
}
This is what I am doing
CREATING USER if checkUsername method returns 0
if(checkFirebaseForUsername(username)==0) {
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(SignUpActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Toast.makeText(getBaseContext(),"inside",Toast.LENGTH_LONG).show();
User newUser = new User();
newUser.setUserId(mAuth.getCurrentUser().getUid());
newUser.setUsername(username);
newUser.setEmailId(email);
try{
mRef.child("users").child(username).setValue(newUser);
}
catch(Exception e){
Toast.makeText(SignUpActivity.this,"error while inserting",Toast.LENGTH_LONG).show();
}
AlertDialog.Builder builder = new AlertDialog.Builder(SignUpActivity.this);
builder.setTitle(R.string.signup_success)
.setPositiveButton(R.string.login_button_label, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(SignUpActivity.this, LoginActivity.class);
startActivity(intent);
finish();
}
});
AlertDialog dialog = builder.create();
dialog.show();
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(SignUpActivity.this);
builder.setTitle(R.string.signup_error_title)
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
}
My checkUsername method -
public int checkFirebaseForUsername(String passedUsername){
final int[] flag = {0};
final String myPassedUsername = passedUsername;
Log.e("tag","working now");
//flag[0]=1;
DatabaseReference mTest = FirebaseDatabase.getInstance().getReference();
mTest.child("users").child(passedUsername).addChildEventListener(new ChildEventListener() {
#Override
public void onDataChanged(DataSnapshot dataSnapshot) {
Log.e("tag","checking");
if(dataSnapshot.exists()){
Log.e("tag","exists");
flag[0]=1;
}
}
#Override
public void onCancelled(DataSnapshot datasnapshot){
}
});
if(flag[0]==1)
return 1;
else
return 0;
}
This is how I am inserting users in my firebase-database and I want to check if a username is available for a new user or not.
Therefore I need to check is there any user already registered with that username....Please help I have already tried whatever I could understand after reffering to documentation provided on the official firebase blog but all in vain!!
EDIT: New answer, old one still below.
I would get rid of your method "checkFirebaseForUsername" because it will always return 0, no matter what.
What you need to do is this:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.child("users").child("username").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
// use "username" already exists
// Let the user know he needs to pick another username.
} else {
// User does not exist. NOW call createUserWithEmailAndPassword
mAuth.createUserWithPassword(...);
// Your previous code here.
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Old Answer:
{
users:
{
apple[X]:
{
username : apple[Y]
email : apple#xy.com
uid : tyutyutyu
}
mango:
{
username : mango
email : mango#xy.com
uid : erererer
}
}
}
If for example, the node apple[X] will always have the same name as the child property "username":apple[Y], then it is as simple as this.
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.child("users").child("username").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
// use "username" already exists
} else {
// "username" does not exist yet.
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
however, if say, the node apple[X] can have a different value than the property apple[Y], and you want to see if any node exists where the "username" property is the same, then you will need to do a query.
Query query = FirebaseDatabase.getInstance().getReference().child("users").orderByChild("username").equalTo("usernameToCheckIfExists");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.getChildrenCount() > 0) {
// 1 or more users exist which have the username property "usernameToCheckIfExists"
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
You may try this.
final String userName = unameEditText.getText().toString();
databaseReference.child("users").orderByChild("username").equalTo(userName).addListenerForSingleValueEvent(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.i(Constants.TAG, "dataSnapshot value = " + dataSnapshot.getValue());
if (dataSnapshot.exists()) {
// User Exists
// Do your stuff here if user already exists
Toast.makeText(getApplicationContext(), "Username already exists. Please try other username.", Toast.LENGTH_SHORT).show();
} else {
// User Not Yet Exists
// Do your stuff here if user not yet exists
}
}
#Override
public void onCancelled (DatabaseError databaseError){
}
}
);
You just check if user is already exits or not by below code:
private DatabaseReference mDatabase;
// ...
mDatabase = FirebaseDatabase.getInstance().getReference();
final String userName = "your_user_name"; // replace with your user name
mDatabase.child("users").child(userName).addListenerForSingleValueEvent(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
// User Exists
// Do your stuff here if user already exits
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "getUser:onCancelled", databaseError.toException());
}
});
You can also see Firebase doc for the same on below link:
Read data once