【问题标题】:Unable to add user details on Firebase RealTime Database无法在 Firebase 实时数据库上添加用户详细信息
【发布时间】:2020-03-21 09:09:56
【问题描述】:

我目前正在尝试将使用 Firebase 电话身份验证在我的应用中注册的用户详细信息添加到 Firebase 实时数据库。我成功地验证了一个用户,但我无法发送到我需要用户输入他的详细信息的 Details Activity 类,而是直接跳转到 MainActivity。 每当我添加新用户时,我都会得到 Toast “电话验证”。

Register.java

public class Register extends AppCompatActivity {
    FirebaseAuth auth;
    String phoneNumber;
    String otpCode;
    String verificationId;
    EditText phone, optEnter;
    Button next;
    CountryCodePicker countryCodePicker;
    PhoneAuthCredential credential;
    Boolean verificationOnProgress = false;
    ProgressBar progressBar;
    TextView state, resend;
    PhoneAuthProvider.ForceResendingToken token;
    //FirebaseFirestore fStore;
    DatabaseReference reference;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_register);

        phone = findViewById(R.id.phone);
        optEnter = findViewById(R.id.codeEnter);
        countryCodePicker = findViewById(R.id.ccp);
        next = findViewById(R.id.nextBtn);
        auth = FirebaseAuth.getInstance();
        progressBar = findViewById(R.id.progressBar);
        state = findViewById(R.id.state);
        resend = findViewById(R.id.resendOtpBtn);

        resend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // todo:: resend OTP
            }
        });


        next.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (!phone.getText().toString().isEmpty() && phone.getText().toString().length() == 10) {
                    if (!verificationOnProgress) {
                        next.setEnabled(false);
                        progressBar.setVisibility(View.VISIBLE);
                        state.setVisibility(View.VISIBLE);
                        String phoneNum = "+" + countryCodePicker.getSelectedCountryCode() + phone.getText().toString();
                        Log.d("phone", "Phone No.: " + phoneNum);
                        requestPhoneAuth(phoneNum);
                    } else {
                        next.setEnabled(false);
                        optEnter.setVisibility(View.GONE);
                        progressBar.setVisibility(View.VISIBLE);
                        state.setText("Logging in");
                        state.setVisibility(View.VISIBLE);
                        otpCode = optEnter.getText().toString();
                        if (otpCode.isEmpty()) {
                            optEnter.setError("Required");
                            return;
                        }

                        credential = PhoneAuthProvider.getCredential(verificationId, otpCode);
                        verifyAuth(credential);
                    }

                } else {
                    phone.setError("Valid Phone Required");
                }
            }
        });


    }

    private void requestPhoneAuth(String phoneNumber) {
        PhoneAuthProvider.getInstance().verifyPhoneNumber(phoneNumber, 60L, TimeUnit.SECONDS, this,
                new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

                    @Override
                    public void onCodeAutoRetrievalTimeOut(String s) {
                        super.onCodeAutoRetrievalTimeOut(s);
                        Toast.makeText(Register.this, "OTP Timeout, Please Re-generate the OTP Again.", Toast.LENGTH_SHORT).show();
                        resend.setVisibility(View.VISIBLE);
                    }

                    @Override
                    public void onCodeSent(String s, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
                        super.onCodeSent(s, forceResendingToken);
                        verificationId = s;
                        token = forceResendingToken;
                        verificationOnProgress = true;
                        progressBar.setVisibility(View.GONE);
                        state.setVisibility(View.GONE);
                        next.setText("Verify");
                        next.setEnabled(true);
                        optEnter.setVisibility(View.VISIBLE);
                    }

                    @Override
                    public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {


                        verifyAuth(phoneAuthCredential);

                    }

                    @Override
                    public void onVerificationFailed(FirebaseException e) {
                        Toast.makeText(Register.this, e.getMessage(), Toast.LENGTH_SHORT).show();

                    }
                });
    }

    private void verifyAuth(PhoneAuthCredential credential) {
        auth.signInWithCredential(credential).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    Toast.makeText(Register.this, "Phone Verified", Toast.LENGTH_SHORT).show();
                    checkUserProfile();
                } else {
                    progressBar.setVisibility(View.GONE);
                    state.setVisibility(View.GONE);
                    Toast.makeText(Register.this, "Can not Verify phone and Create Account.", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();

        if (auth.getCurrentUser() != null) {
            progressBar.setVisibility(View.VISIBLE);
            state.setText("Logging IN");
            state.setVisibility(View.VISIBLE);
            checkUserProfile();
        }
    }

    private void checkUserProfile() {
        FirebaseUser firebaseUser = auth.getCurrentUser();
        assert firebaseUser != null;
        String userid = firebaseUser.getUid();
        reference = FirebaseDatabase.getInstance().getReference("Users").child(userid);
        if (userid != null) {
            Intent intent = new Intent(Register.this, MainActivity.class);
            startActivity(intent);
        } else {
            Toast.makeText(Register.this, "Profile doesnt exist", Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(Register.this, Details.class);
            startActivity(intent);
        }
    }
}

Details.java

public class Details extends AppCompatActivity {
    public static final String TAG = "TAG";
    EditText firstName,lastName,email;
    Button saveBtn;
    FirebaseAuth auth;
    FirebaseFirestore fStore;
    String userID;
    DatabaseReference reference;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_details);

        firstName = findViewById(R.id.firstName);
        lastName = findViewById(R.id.lastName);
        email = findViewById(R.id.emailAddress);
        saveBtn = findViewById(R.id.saveBtn);

        auth = FirebaseAuth.getInstance();
        fStore = FirebaseFirestore.getInstance();

        saveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String First_Name=  firstName.getText().toString();
                String Last_Name= lastName.getText().toString();
                String EMail= email.getText().toString();
                    if(firstName.getText().toString().isEmpty()||lastName.getText().toString().isEmpty() || email.getText().toString().isEmpty()){
                    Toast.makeText(Details.this, "Fill the required Details", Toast.LENGTH_SHORT).show();
                    return;
                }

                register(First_Name,Last_Name,EMail);   
            }
        });
}

private void register(String first_name, String last_name, String eMail) {

    FirebaseUser firebaseUser = auth.getCurrentUser();
    assert firebaseUser != null;
    String userid = firebaseUser.getUid();
    reference = FirebaseDatabase.getInstance().getReference("Users").child(userid);
    Map<String,Object> hashmap=new HashMap<>();
    hashmap.put("First Name",first_name);
    hashmap.put("Last Name",last_name);
    hashmap.put("Email-Id",eMail);

    reference.setValue(hashmap).addOnCompleteListener(new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {
            if(task.isSuccessful()){
                Intent intent=new Intent(Details.this,MainActivity.class);
                startActivity(intent);
            }
            else{
                Toast.makeText(Details.this,"Registration failed...",Toast.LENGTH_SHORT).show();
            }
        }
    });
  }
}

【问题讨论】:

  • 这段代码有什么问题?究竟有什么不符合您的预期?
  • @AlexMamo@AlexMamo 我无法让用户在注册后更新他的详细信息。我的应用正在跳过详细信息活动并直接进入 main_activity。

标签: android firebase-realtime-database firebase-authentication


【解决方案1】:

似乎在 checkUserProfile() 函数的 Register 类中,您正在检查来自 firebaseUser.getUid() 的 userId 是否不为空。目前这将始终不为空,因为您已经断言此时必须对用户进行身份验证。

从您的代码来看,这只是您的一个错误。我假设您实际上要做的是查看 FirebaseDatabase 中是否已经存在详细信息。你有一个你没有使用的数据库的引用。

private void checkUserProfile() {
            FirebaseUser firebaseUser = auth.getCurrentUser();
            assert firebaseUser != null;
            String userid = firebaseUser.getUid();
            //Unused reference
            reference = FirebaseDatabase.getInstance().getReference("Users").child(userid);
            if (userid != null) {
                 Intent intent = new Intent(Register.this, MainActivity.class);
                 startActivity(intent);
}

但我的问题也是,您确定要使用实时数据库获取用户详细信息吗?您正在使用 FirebaseFirestore 在 Details 函数中保存详细信息。您不想检查 FirebaseFirestore 中是否已存在详细信息吗?

如何解决:

首先,让我们创建用户数据类:

public class User {
    public String uid;
    public String firstName;
    public String lastName;
    public String email;

    public User {
        // Default constructor required for calls to DataSnapshot.getValue(User.class)
    }

    public User(String uid, String firstName, String lastName, String email) {
        this.uid = uid;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }
}

现在,让我们将 Details.java 类中的代码更改为使用 User 类:

private void register(String first_name, String last_name, String eMail) {

    FirebaseUser firebaseUser = auth.getCurrentUser();
    assert firebaseUser != null;
    String userid = firebaseUser.getUid();
    reference = FirebaseDatabase.getInstance().getReference("Users").child(userid);
    User user = new User(userid, firstName, lastName, eMail)

    reference.setValue(user).addOnCompleteListener(new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {
            if(task.isSuccessful()){
                Intent intent=new Intent(Details.this,MainActivity.class);
                startActivity(intent);
            }
            else{
                Toast.makeText(Details.this,"Registration failed...",Toast.LENGTH_SHORT).show();
            }
        }
    });
  }

让我们在 checkUserProfile() 方法中检查注册详情是否存在于数据库中:

private void checkUserProfile() {
                FirebaseUser firebaseUser = auth.getCurrentUser();
                assert firebaseUser != null;
                String userid = firebaseUser.getUid();
                reference = FirebaseDatabase.getInstance().getReference("Users").child(userid);
                reference.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot.exists()) {
                Intent intent = new Intent(Register.this, MainActivity.class);
                    startActivity(intent);
            }
            else {
            Toast.makeText(Register.this, "Profile doesnt exist", Toast.LENGTH_SHORT).show();
                    Intent intent = new Intent(Register.this, Details.class);
                startActivity(intent);
            }
        }

        @Override
        public void onCancelled(DatabaseError error) {
            // Failed to read value
            Log.w(TAG, "Failed to read value.", error.toException());
        }
    });
}

让我知道它是否适合你。

【讨论】:

  • 实际上我正在尝试创建消息传递应用程序。首先我使用 firestore 来获取用户详细信息和实时数据库来获取消息,但代码变得有点复杂,所以我转向了实时数据库。早些时候使用 Firestore 获取详细信息时能够成功上传和检索详细信息。
  • 我应该进行哪些更正以使应用按预期运行
  • 点击保存按钮后,实时数据库中没有保存任何详细信息,但点击详细信息活动中的保存按钮后,我移至主要活动
  • 好吧,这很有趣。因为如果你从 Details 类移动到 MainActivity 就意味着写操作一定是成功的。
【解决方案2】:

无论使用电子邮件/电话号码,Firebase 都会在注册帐户时生成一个唯一密钥 (UID)。在该帐户存在于 Firebase 身份验证列表中之前,此密钥一直与该帐户关联。

因此,一旦您使用某个号码/电子邮件注册,就会为该号码/电子邮件创建 UID。每次您获取 UID 时,它都会返回该用户 UID,并且您还断言 Firebase 用户是 NotNull 因此,每次您从 firebase 和应用程序获取 UID 时都会移动到仪表板屏幕。

如果您想将用户移动到详细信息屏幕,那么。您还可以添加基于 firebase 用户的条件。

if(firebaseUser != null){
   // Get UID and Move to Dashboard
}else{
  // Move to Detail Screen
}

【讨论】:

  • 没用,添加上述条件后仍然移动到此仪表板
  • 请从 Firebase 控制台中删除所有注册电话号码。此外,您需要更新 onStart() 条件。请查看您的情况,您正在断言 auth.getCurentUser() Is NotNull。当您的 FirebaseUser 不为空时,它将执行您的 checkUserProfile()。因此,请更新您的条件,例如 1.从 OnStart() 方法中删除条件。 2. 将相同的条件添加到 checkUserProfile() 方法中。并在上面使用导航屏幕。
猜你喜欢
  • 2018-03-16
  • 2015-09-11
  • 1970-01-01
  • 2018-09-13
  • 2012-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多