问题
I'm using security rules to determine in which conditions a value can be written to the database. At the moment I've setup the security rules, these are working fine (I checked with the simulator), so no issues so far.
In case that permission to write is denied (security rules not met), I want to take some action. In order to do this, I'm planning to use onComplete on setValue and if there is an error I will have to do some code.
At the moment, if the security rules are met, the values are written to the online database and I can easily check this in the browser. If the value is not written to the database due to security reasons, I can see an error in the debug/log saying that Permission is denied, so all good.
The issue is that when a value is written or not written to the database, the onComplete is not called at all, it's like it doesn't even exist in my code. I checked this in debug mode with breakpoints. The code I'm using comes straight from the documentation, please see below.
Does anybody have any ideas? Thanks a lot!
dataRef.setValue(frequency, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError, DatabaseReference dataRef) {
if (databaseError != null) {
System.out.println("Data could not be saved " + databaseError.getMessage());
} else {
System.out.println("Data saved successfully.");
}
}
});
EDIT
I just noticed that I get the above behavior only if the setValue method is called within the addValueEventListener/onDataChange. If I move the setValue method outside the listener, the onComplete gets called. Is this the expected behavior or is it a bug?
UPDATE
After further testing, I noticed that it actually doesn't matter if the setValue method is called within the addValueEventListener/onDataChange. It matters though if I call the method within the while loop below. As long as it is within the while loop, the onComplete is not called. In both cases the values get written/not get written to the database depending on security rules. Please see both cases below:
OPTION 1 - onComplete is not called
FirebaseDatabase.getInstance().setLogLevel(Logger.Level.DEBUG);
FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference databaseReference = database.getReference();
DatabaseReference dataRef = databaseReference.child("Drivers").child("23").child("Frequency");
while (errorStatus == false) {
dataRef.setValue(frequency, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError != null) {
System.out.println("Data could not be saved " + databaseError.getMessage());
errorStatus = false;
frequency = frequency + 1;
} else {
System.out.println("Data saved successfully.");
errorStatus = true;
frequency = 1;
}
}
});
}
OPTION 2 - onComplete is called.
FirebaseDatabase.getInstance().setLogLevel(Logger.Level.DEBUG);
FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference databaseReference = database.getReference();
DatabaseReference dataRef = databaseReference.child("Drivers").child("23").child("Frequency");
dataRef.setValue(frequency, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError != null) {
System.out.println("Data could not be saved " + databaseError.getMessage());
errorStatus = false;
frequency = frequency + 1;
} else {
System.out.println("Data saved successfully.");
errorStatus = true;
frequency = 1;
}
}
});
I do need the while loop though, unless a workaround can be found?
UPDATE
public class MainActivity extends AppCompatActivity {
static boolean errorStatus = false;
static int frequency = 1;
来源:https://stackoverflow.com/questions/43072547/setvalue-oncomplete-not-called-from-firebase-on-android