Android: пользователь все еще может войти в систему, не завершив создание учетной записи

# #android #firebase-realtime-database #firebase-authentication

Вопрос:

Мой новый пользователь приложения может регистрироваться только с авторизацией по телефону без электронной почты, теперь у приложения есть 3 действия для регистрации нового пользователя, сначала нужно ввести номер телефона, затем ввести отправленный код, а затем перейти к 3 действиям, в которых пользователь может загрузить изображение профиля и имя, проблема с последним действием заключается в том, что если пользователь каким-то образом закрыл приложение без загрузки изображения профиля или установки имени, что означает, что firebase его вообще не регистрирует, он все равно сможет получить доступ к приложению как обычный пользователь.

Активность ОТП:

 public class OTPActivity extends AppCompatActivity {
    ActivityOTPBinding binding;
    FirebaseAuth auth;

    String verificationId;
    ProgressDialog dialog;
    private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
    private PhoneAuthProvider.ForceResendingToken mResendToken;
    private static final String TAG = "PhoneAuthActivity";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityOTPBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);


        auth = FirebaseAuth.getInstance();

        dialog = new ProgressDialog(this);
        dialog.setMessage("Checking...");

        // force prevent canceling the check
        dialog.setCancelable(false);
        dialog.show();

        String phoneNumber =  getIntent().getStringExtra("phoneNumber");

        binding.phoneLbl.setText(phoneNumber);

        binding.changePhone.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });

        PhoneAuthOptions options = PhoneAuthOptions.newBuilder(auth)
                .setPhoneNumber(phoneNumber)
                .setTimeout(60L, TimeUnit.SECONDS)
                .setActivity(OTPActivity.this)
                .setCallbacks(mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
                    @Override
                    public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) {

                    }

                    @Override
                    public void onVerificationFailed(@NonNull FirebaseException e) {
                        dialog.dismiss();
                        Toast.makeText(OTPActivity.this, "Verification Failed, Check Phone Number.", Toast.LENGTH_SHORT).show();
                        Log.w(TAG, "onVerificationFailed", e);
                    }

                    @Override
                    public void onCodeSent(@NonNull String verifyId, @NonNull PhoneAuthProvider.ForceResendingToken forceResendingToken) {
                        super.onCodeSent(verifyId, forceResendingToken);
                        dialog.dismiss();
                        verificationId = verifyId;
                        mResendToken = forceResendingToken;

                        InputMethodManager imm = (InputMethodManager)   getSystemService(Context.INPUT_METHOD_SERVICE);
                        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                        binding.otpView.requestFocus();
                        Log.d(TAG, "onCodeSent:"   verifyId);
                    }
                }).build();

        PhoneAuthProvider.verifyPhoneNumber(options);

        binding.otpView.setOtpCompletionListener(new OnOtpCompletionListener() {
            @Override
            public void onOtpCompleted(String otp) {
                PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, otp);
                auth.signInWithCredential(credential).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()){
                            Intent intent = new Intent(OTPActivity.this, SetupProfileActivity.class);
                            startActivity(intent);
                            finishAffinity();
                        } else {
                            Toast.makeText(OTPActivity.this, "Verification Failed, Please Try Again.", Toast.LENGTH_LONG).show();
                        }
                    }
                });
            }
        });

        binding.resendOTP.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(OTPActivity.this, getString(R.string.code_is_being_resent), Toast.LENGTH_SHORT).show();
                resendVerificationCode(phoneNumber, mResendToken);
            }
        });
    }

    // [START resend_verification]
    private void resendVerificationCode(String phoneNumber,
                                        PhoneAuthProvider.ForceResendingToken token) {
        PhoneAuthOptions options =
                PhoneAuthOptions.newBuilder(auth)
                        .setPhoneNumber(phoneNumber)       // Phone number to verify
                        .setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit
                        .setActivity(this)                 // Activity (for callback binding)
                        .setCallbacks(mCallbacks)          // OnVerificationStateChangedCallbacks
                        .setForceResendingToken(token)     // ForceResendingToken from callbacks
                        .build();
        PhoneAuthProvider.verifyPhoneNumber(options);

    }
    // [END resend_verification]
}
 

Профиль настройки:

 public class SetupProfileActivity extends AppCompatActivity {

    ActivitySetupProfileBinding binding;
    FirebaseAuth auth;
    FirebaseDatabase database;
    FirebaseStorage storage;
    Uri selectedImage;
    ProgressDialog dialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivitySetupProfileBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        database = FirebaseDatabase.getInstance();
        storage = FirebaseStorage.getInstance();
        auth = FirebaseAuth.getInstance();

        dialog = new ProgressDialog(this);
        dialog.setMessage("Uploading Profile Setting...");
        dialog.setCancelable(false);

        binding.profileImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_GET_CONTENT);
                intent.setType("image/*");
                startActivityForResult(intent, 45);
            }
        });

        binding.finishBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String name = binding.nameBox.getText().toString();
                if (name.isEmpty()) {
                    binding.nameBox.setError(getString(R.string.cant_be_empty));
                }
                dialog.show();

                if (selectedImage !=null){
                    StorageReference reference = storage.getReference().child("Profiles").child(auth.getUid());
                    reference.putFile(selectedImage).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
                        @Override
                        public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {
                            if (task.isSuccessful()) {
                                reference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                                    @Override
                                    public void onSuccess(Uri uri) {
                                        String imageUrl = uri.toString();

                                        String uid = auth.getUid();
                                        String phone = auth.getCurrentUser().getPhoneNumber();
                                        String name = binding.nameBox.getText().toString().trim();

                                        User user = new User(uid, name, phone, imageUrl);

                                        database.getReference()
                                                .child("Users")
                                                .child(phone)
                                                .setValue(user)
                                                .addOnSuccessListener(new OnSuccessListener<Void>() {
                                                    @Override
                                                    public void onSuccess(Void aVoid) {
                                                        dialog.dismiss();
                                                        Intent intent = new Intent(SetupProfileActivity.this, MainActivity.class);
                                                        SharedPreferences preferences = getSharedPreferences("DisplayUserInfo", MODE_PRIVATE);
                                                        SharedPreferences.Editor editor = preferences.edit();
                                                        editor.putString("DisplayName", name);
                                                        editor.putString("DisplayProfileImage", imageUrl);
                                                        editor.apply();
                                                        startActivity(intent);
                                                        finish();
                                                    }
                                                });
                                    }
                                });
                            }
                        }
                    });
                } else {
                    String uid = auth.getUid();
                    String phone = auth.getCurrentUser().getPhoneNumber();
                    User user = new User(uid, name, phone, "No Image");
                    database.getReference()
                            .child("Users")
                            .child(phone)
                            .setValue(user).addOnCompleteListener(new OnCompleteListener<Void>() {
                        @Override
                        public void onComplete(@NonNull Task<Void> task) {
                            if (task.isSuccessful()) {
                                dialog.dismiss();
                                Intent intent = new Intent(SetupProfileActivity.this, MainActivity.class);
                                startActivity(intent);
                                finish();
                            } else {
                                Toast.makeText(SetupProfileActivity.this, "Failed To Reg Account", Toast.LENGTH_SHORT).show();
                            }
                        }
                    });
                }
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (data !=null){
            if (data.getData() !=null){
                binding.profileImageView.setImageURI(data.getData());
                selectedImage = data.getData();
            }
        }
    }

    // check if want to exit
    boolean doubleBackToExitPressedOnce = false;
    @Override
    public void onBackPressed() {
        if (doubleBackToExitPressedOnce) {
            super.onBackPressed();
            return;
        }

        this.doubleBackToExitPressedOnce = true;
        Toast.makeText(this, getString(R.string.click_again_to_Exit), Toast.LENGTH_SHORT).show();

        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {

            @Override
            public void run() {
                doubleBackToExitPressedOnce=false;
            }
        }, 2000);
    }
}
 

Код, используемый для автологинизации :

 //AutoLogin
if (auth.getCurrentUser() !=null){
    Intent intent = new Intent(PhoneLoginActivity.this, MainActivity.class);
    startActivity(intent);
    finish();
}
 

Комментарии:

1. Так в чем же вопрос?

2. опубликуйте код, в котором вы непосредственно открываете основное действие, если пользователь вошел в систему

3. //АвтоЛогин if (auth.getCurrentUser() !=null){ Намерение намерение = новое намерение(PhoneLoginActivity.this, MainActivity.class); Начало(намерение); завершение(); }

Ответ №1:

Простой способ справиться с вашей ситуацией-сохранить логическую переменную типа «isProfileComplete» в профиле пользователя. Установите это значение в значение true, как только вы получите всю необходимую информацию от пользователя в профиле настройки. Проверьте это значение в своей активности запуска, если оно ложное, а затем перенаправьте пользователя на страницу настройки профиля на своей целевой странице.

Редактировать

Вам нужны незначительные изменения в разделе кода автоматического входа в систему

 if (auth.getCurrentUser() !=null){
    Intent intent; 
    if(isProfileComplete())
      intent = new Intent(PhoneLoginActivity.this, MainActivity.class);
    else
      intent = new Intent(PhoneLoginActivity.this, SetupProfileActivity.class);
    startActivity(intent);
    finish();
}

private boolean isProfileComplete(){
  //get User object for the logged in user using SharedPreferences or FirebaseDB
  return user.isProfileComplete
}
 

Комментарии:

1. не сработало, это привело к всплеску активности, чтобы сохранить цикл

2. любое другое решение

3. Как происходит зацикливание всплеска?? Вам нужно отредактировать свой код автологина здесь. Отредактирую свой ответ, чтобы вы поняли.

4. теперь возникла проблема, если пользователь закроется, не завершив регистрацию, он будет вынужден находиться внутри активности регистрации или настройки, он не сможет перейти к активности входа, даже кнопка входа не будет работать