问题:
我将MutableData值变为null,直到我多次点击onClick(这对用户来说是不可行的)。
每次添加员工时,我都会尝试增加数据库中的员工数量值。我研究了交易并看到了以下内容(Firebase runTransaction not working)和(https://www.firebase.com/docs/android/guide/saving-data.html#section-transactions)并遵循了此文档。
使用调试程序重新创建问题的步骤:
MutableData {key =,value = null}“
“MutableData {key =,value = 4}”
数据库结构:
相关守则:
private void incrementNumEmp(String compid) {
Log.i("insideIncrementMethod", compid);
mCompTotalEmpRef.child(compid).child("CompanyTime").child("TotalEmployees").runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
if(mutableData.getValue() !=null) {
mutableData.setValue((Long) mutableData.getValue() + 1);
}
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
Log.d("TAG", "countTransaction:onComplete:" + databaseError);
}
});
}
代码的全部内容:
public class RegisterEmployeeActivity extends Activity {
EditText firstName, lastName, phoneNumber, emailET, ssnET, passwordET;
String email, password, ssn, fName, lName, phone;
String companyID;
boolean fieldsFilled;
private ImageView checkmarkImage;
private FirebaseAuth auth;
DatabaseReference mDatabase;
FirebaseStorage storage;
StorageReference storageReference;
//PHOTO STUFF
StorageMetadata metadata;
UploadTask uploadTask;
Uri file;
private static FirebaseUser currentUser;
String currentUserString;
FirebaseDatabase database;
DatabaseReference mDatabaseEmp, mDatabaseComp, mDatabaseUnverified;
DatabaseReference mDatabseCompEmp;
DatabaseReference mCompTotalEmpRef;
//PHONE STUFF
PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
String mVerificationId;
PhoneAuthProvider.ForceResendingToken mResendToken;
FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private FirebaseMethods firebaseMethods;
private Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register_employee);
firstName = (EditText) findViewById(R.id.firstNameET);
lastName = (EditText) findViewById(R.id.lastNameET);
phoneNumber = (EditText) findViewById(R.id.phoneET);
emailET = (EditText) findViewById(R.id.emailET);
ssnET = (EditText) findViewById(R.id.ssnET);
passwordET = (EditText) findViewById(R.id.passwordET);
//Get Firebase auth instance
auth = FirebaseAuth.getInstance();
//PHOTO STORAGE
storage = FirebaseStorage.getInstance();
storageReference = storage.getReferenceFromUrl("gs://timeclock-fc.appspot.com");
//storageReference = storage.getReferenceFromUrl("gs://timeclock-fc.appspot.com").child("20170702_174811.jpeg"); //was PNG
//FIREBASE METHODS
mContext = RegisterEmployeeActivity.this;
firebaseMethods = new FirebaseMethods(mContext);
//DATABASE REFERENCES
mDatabase = FirebaseDatabase.getInstance().getReference("/Unverified Employees");
//Log.i("db ref", mDatabase.child("RC9zIioE6vc5vlhrIethmbqyFDS2").getKey());
database = FirebaseDatabase.getInstance();
mDatabaseEmp = database.getReference("/Employees");
mDatabaseComp = database.getReference("/Companies");
mDatabaseUnverified = database.getReference("/Unverified Employees");
mDatabseCompEmp = database.getReference("/CompanyEmployees/CompanyIDs");
mCompTotalEmpRef = database.getReference("/CompanyEmployeeTime/CompanyIDs");
currentUser =
FirebaseAuth.getInstance().getCurrentUser();
mAuth = FirebaseAuth.getInstance();
//final ImageView checkmarkImage = (ImageView) findViewById(R.id.checkmarkImage);
checkmarkImage = (ImageView) findViewById(R.id.checkmarkImage);
//Insert information into FirebaseDB and go to next screen
checkmarkImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
//public void onClick(View view) {
//Assigns EditText values to String values
assignStringValues();
//Ensures that EditText fields are filled. If not will give a warning
fieldsFilled = areFieldsFilled();
mDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.i("DATA VALUE", dataSnapshot.child("RC9zIioE6vc5vlhrIethmbqyFDS2").getValue().toString());
//Used https://github.com/mitchtabian/Android-Instagram-Clone/tree/6e2ffe29621c592e57057b8561d3cac4df9c14a1/app/src/main/java/tabian/com/instagramclone and https://www.youtube.com/watch?v=I-2T4i75gfw
Log.i("EMAIL NULL?", email);
Log.i("SSN", ssn);
Log.i("ds/Input", dataSnapshot.toString());
companyID = firebaseMethods.checkIfSsnExists(ssn, dataSnapshot);
//Log.i("companyIDRegister", companyID);
if(email!= null && !email.equals("")) {
//CHECK IF IT MATCHES (SSN) *AND* Email
//companyID = firebaseMethods.checkIfSsnExists(ssn, dataSnapshot);
if (firebaseMethods.checkIfEmailExists(email, dataSnapshot) && companyID.length()>0) {
//if (firebaseMethods.checkIfEmailExists(email, dataSnapshot) && firebaseMethods.checkIfSsnExists(ssn, dataSnapshot)) {
auth.createUserWithEmailAndPassword(emailET.getText().toString(), passwordET.getText().toString())
.addOnCompleteListener(RegisterEmployeeActivity.this, new OnCompleteListener() {
@Override
public void onComplete(@NonNull Task task) {
//progressBar.setVisibility(View.GONE);
if (!task.isSuccessful()) {
//EXCEPTION MESSAGES
try {
throw task.getException();
} catch (FirebaseAuthWeakPasswordException e) {
MethodHelper.showAlert(RegisterEmployeeActivity.this, "Authentication failed.", "Password should be atleast 6 characters");
} catch (FirebaseAuthInvalidCredentialsException e) {
MethodHelper.showAlert(RegisterEmployeeActivity.this, "Authentication failed.", "The email address is badly formatted");
} catch (FirebaseAuthUserCollisionException e) {
MethodHelper.showAlert(RegisterEmployeeActivity.this, "Authentication failed.", "The email address is already in use by another account");
} catch (Exception e) {
e.printStackTrace();
}
} else {
//SEND INFORMATION TO FIREBASE DATABASE
//companyID = firebaseMethods.getCompanyID();
//addEmployeeToFirebase(currentUser);
currentUser =
FirebaseAuth.getInstance().getCurrentUser();
Log.i("beforeAddEmail",currentUser.getUid());
addEmployeeToFirebase(currentUser, companyID);
removeEmail();
/*if(fieldsFilled == true) {
startActivity(new Intent(RegisterEmployeeActivity.this, EmployeeHome.class));
finish();
} */
}
} //END OF ONCOMPLETE
}); //END OF ONCOMPLETELISTENER
} //END OF (IF) CHECKEMAILEXISTS
else {
MethodHelper.showAlert(RegisterEmployeeActivity.this, "Authentication failed.", "You must use the email and ssn your employer has entered");
}
} //END OF EMAIL CHECK
//PHONE # CHECK
if(phone != null && !phone.equals("")) {
//CHECK IF SSN *AND* PHONE EXISTS
//companyID.length()>0
if (firebaseMethods.checkIfPhoneExists(phone, dataSnapshot) && companyID.length()>0) {
//if (firebaseMethods.checkIfPhoneExists(phone, dataSnapshot) && firebaseMethods.checkIfSsnExists(ssn, dataSnapshot)) {
Log.i("IF", "INSIDE IF");
mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
//USING https://github.com/firebase/quickstart-android/blob/master/auth/app/src/main/java/com/google/firebase/quickstart/auth/PhoneAuthActivity.java
// Originally https://firebase.google.com/docs/auth/android/phone-auth
@Override
public void onVerificationCompleted(PhoneAuthCredential credential) {
// This callback will be invoked in two situations:
// 1 - Instant verification. In some cases the phone number can be instantly
// verified without needing to send or enter a verification code.
// 2 - Auto-retrieval. On some devices Google Play services can automatically
// detect the incoming verification SMS and perform verification without
// user action.
Log.i("VERIFICATION_COMPLETED", "onVerificationCompleted:" + credential);
//unnecessary?
// [START_EXCLUDE silent]
//mVerificationInProgress = false;
// [END_EXCLUDE]
// [START_EXCLUDE silent]
// Update the UI and attempt sign in with the phone credential
//updateUI(STATE_VERIFY_SUCCESS, credential);
// [END_EXCLUDE]
//TODO: See why this is no longer called
signInWithPhoneAuthCredential(credential);
}
@Override
public void onVerificationFailed(FirebaseException e) {
// This callback is invoked in an invalid request for verification is made,
// for instance if the the phone number format is not valid.
Log.i("VERIFICATION_FAILED", "onVerificationFailed", e);
if (e instanceof FirebaseAuthInvalidCredentialsException) {
// Invalid request
} else if (e instanceof FirebaseTooManyRequestsException) {
// The SMS quota for the project has been exceeded
}
// Show a message and update the UI
}
//Looks Good
@Override
public void onCodeSent(String verificationId,
PhoneAuthProvider.ForceResendingToken token) {
// The SMS verification code has been sent to the provided phone number, we
// now need to ask the user to enter the code and then construct a credential
// by combining the code with a verification ID.
Log.i("CODE_SENT", "onCodeSent:" + verificationId);
// Save verification ID and resending token so we can use them later
mVerificationId = verificationId;
mResendToken = token;
//PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, mResendToken);
// ...
}
}; //END OF MCALLBACKS
verifyPhone(phone, mCallbacks);
} //END OF (IF) CHECK IF PHONE EXISTS
else {
MethodHelper.showAlert(RegisterEmployeeActivity.this, "Authentication failed.", "You must use the phone number and ssn your employer has entered");
}
} //END OF PHONE# Check
} //END OF ONDATACHANGE
@Override
public void onCancelled(DatabaseError databaseError) {
} //CLOSE ONCANCELLED
}); //END OF mDatabase Listener
// } //END OF ONAUTHSTATECHANGED
// }; //END OF FIREBASE AUTH STATE LISTENER
} //END OF ONCLICK
}); //END OF CHECKMARK
} //END OF ONCREATE
private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
//Log.i("mAuth", mAuth.toString());
//FirebaseAuth.getInstance().signInWithCredential(credential)
mAuth.signInWithCredential(credential)
.addOnCompleteListener(RegisterEmployeeActivity.this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.i("SIGNINWITHCREDENTIAL", "signInWithCredential:success");
FirebaseUser user = task.getResult().getUser();
// ...
}
else {
// Sign in failed, display a message and update the UI
Log.i("SIGNINWITHCREDENTIAL", "signInWithCredential:failure", task.getException());
if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
// The verification code entered was invalid
}
}
assignStringValues();
currentUser =
FirebaseAuth.getInstance().getCurrentUser();
//SEND INFORMATION TO FIREBASE DATABASE
companyID = firebaseMethods.getCompanyID();
Log.i("companyID", companyID);
addEmployeeToFirebase(currentUser, companyID);
// addEmployeeToFirebase(currentUser);
Log.i("fieldsFilled", String.valueOf(fieldsFilled));
if(fieldsFilled == true) {
finish();
startActivity(new Intent(RegisterEmployeeActivity.this, EmployeeHome.class));
//finish();
}
} //End of OnComplete
});
}
//PhoneAuthProvider.OnVerificationStateChangedCallbacks()
public void verifyPhone(String phone, PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks)
{
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phone, // Phone number to verify
120, // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
RegisterEmployeeActivity.this, // Activity (for callback binding)
mCallbacks); // OnVerificationStateChangedCallbacks
}
DatabaseReference.CompletionListener completionListener =
new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError,
DatabaseReference databaseReference) {
if (databaseError != null) {
notifyUser(databaseError.getMessage());
}
}
};
private void notifyUser(String message) {
Toast.makeText(RegisterEmployeeActivity.this, message,
Toast.LENGTH_SHORT).show();
}
private void assignStringValues() {
email = emailET.getText().toString().trim();
password = passwordET.getText().toString().trim();
ssn = ssnET.getText().toString().trim();
fName = firstName.getText().toString().trim();
lName = lastName.getText().toString().trim();
phone = phoneNumber.getText().toString().trim();
}
private boolean areFieldsFilled() {
fieldsFilled = true;
if (TextUtils.isEmpty(fName)) {
MethodHelper.showAlert(RegisterEmployeeActivity.this, "First Name Required", "A First Name is required. Please enter your name and try again.");
fieldsFilled = false;
}
if (TextUtils.isEmpty(lName)) {
MethodHelper.showAlert(RegisterEmployeeActivity.this, "Last Name Required", "A Last Name is required. Please enter your name and try again.");
fieldsFilled = false;
}
if ( (TextUtils.isEmpty(phone)) && TextUtils.isEmpty(email)) {
MethodHelper.showAlert(RegisterEmployeeActivity.this, "Phone Number OR Email Required", "A Phone Number OR Email is required. Please enter your number OR email and try again.");
fieldsFilled = false;
}
if (TextUtils.isEmpty(password)) {
MethodHelper.showAlert(RegisterEmployeeActivity.this, "Password Required", "A password is required. Please enter your password and try again.");
fieldsFilled = false;
}
if(TextUtils.isEmpty(ssn)) {
MethodHelper.showAlert(RegisterEmployeeActivity.this, "Social Security Number Required", "A social security number is required. Please enter the last 4 digits of your social security number and try again.");
fieldsFilled = false;
}
return fieldsFilled;
}
private void addEmployeeToFirebase(FirebaseUser currentUser, final String compid) {
//SEND INFORMATION TO FIREBASE DATABASE
// mDatabaseEmp.child(currentUser.getUid()).child("firstName")
// .setValue(fName, completionListener);
//May want to set currentUser.getUid()) to a String?
Log.i("addEmployeeToFirebase", "inside method");
currentUserString = currentUser.getUid();
Log.i("currentUserStringADDEMP", currentUserString);
mDatabaseEmp.child(currentUserString).child("firstName")
.setValue(fName, completionListener);
mDatabaseEmp.child(currentUserString).child("lastName")
.setValue(lName, completionListener);
mDatabaseEmp.child(currentUserString).child("phoneNumber")
.setValue(phone, completionListener);
mDatabaseEmp.child(currentUserString).child("email")
.setValue(email, completionListener);
mDatabaseEmp.child(currentUserString).child("ssn")
.setValue(ssn, completionListener);
Log.i("addEmp-CompID?", compid);
mDatabaseEmp.child(currentUserString).child("CompanyID").setValue(compid, completionListener);
mDatabseCompEmp.child(compid).child("EmployeeIDs").child(currentUserString).child("ID").setValue(currentUserString);
//INCREMENT Total # Employees
/*mCompTotalEmpRef.child(compid).child("CompanyTime").addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
try {
long total = Long.parseLong(dataSnapshot.child("TotalEmployees").getValue().toString());
total = total + 1;
mCompTotalEmpRef.child(compid).child("CompanyTime").child("TotalEmployees").setValue(total);
}
catch (Exception e) { Log.i("LNull?", e.toString()); }
}
@Override
public void onCancelled(DatabaseError databaseError) { Log.d("Cancelled",databaseError.toString()); }
}); */
incrementNumEmp(compid);
}
private void incrementNumEmp(String compid) {
Log.i("insideIncrementMethod", compid);
mCompTotalEmpRef.child(compid).child("CompanyTime").child("TotalEmployees").runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
//long total = Long.parseLong(mutableData.getValue().toString()); //why is mutable data key none value null??
/* long total = 0;
if(mutableData.getValue(Long.class) != null) {
String numEmp = (String) mutableData.getValue();
//total = Long.parseLong(numEmp);
total = Long.parseLong(numEmp, 16);
} */
if(mutableData.getValue() !=null) {
mutableData.setValue((Long) mutableData.getValue() + 1);
}
//total = mutableData.getValue(Long.class);
/* Log.i("totalBefore", String.valueOf(total));
total++;
Log.i("totalAfter", String.valueOf(total));
String incHex = Long.toHexString(total); */
//mutableData.setValue(total);
//mutableData.setValue(incHex);
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
Log.d("TAG", "countTransaction:onComplete:" + databaseError);
}
});
}
private void removeEmail() {
/*Query emailQuery = mDatabase.child("emailAddress").equalTo(email);
Log.i("emailRemove", email);
Log.i("removeEmail","Inside");
//mDatabaseEmp.child("emailAddress").equalTo(email).setValue("");
//mDatabaseUnverified.child("emailAddress").equalTo(email).removeEventListener();
emailQuery.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot emailSnapshot: dataSnapshot.getChildren()) {
Log.i("snapshot", emailSnapshot.toString());
Log.i("snapshotRef", emailSnapshot.getRef().toString());
emailSnapshot.getRef().removeValue();
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.e("TAG", "onCancelled", databaseError.toException());
}
}); */
/*Query queryRef = mDatabase.orderByChild("Unverified Employees").equalTo(email);
queryRef.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot snapshot, String previousChild) {
Log.i("snapshot", snapshot.toString());
Log.i("snapshotRef", snapshot.getRef().toString());
snapshot.getRef().setValue(null);
}
@Override
public void onChildRemoved(DataSnapshot snapshot) {
Log.e("TAG","onChildRemoved "+ snapshot.toString());
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
Log.e("TAG","onChildChanged "+ dataSnapshot.toString()+" \n String "+s);
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
Log.e("TAG","onChildAdded "+ dataSnapshot.toString()+" \n String "+s);
}
}); */
Query emailQuery = mDatabase.child("emailAddress").equalTo(email);
emailQuery.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot emailSnapshot: dataSnapshot.getChildren()) {
Log.i("snapshot", emailSnapshot.toString());
Log.i("snapshotRef", emailSnapshot.getRef().toString());
emailSnapshot.getRef().removeValue();
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.e("TAG", "onCancelled", databaseError.toException());
}
});
}
}
答案 0 :(得分:0)
因此,在添加了更多日志语句之后,似乎我的“finish()”出现在了错误的位置。由于DB Listener是异步的,因此必须在Transactions可变之前调用finish。
我最初拥有的DB Listener内部:
addEmployeeToFirebase(currentUser, companyID);
finish();
我将其更改为以下内容,现在可以正常使用!:
finish();
addEmployeeToFirebase(currentUser, companyID);
对我来说奇怪的是另一个.setValues工作正常,但对于Transaction mutableData我必须在它之前完成