【问题标题】:Using Firebase phone authentication inside Fragment android在 Fragment android 中使用 Firebase 电话身份验证
【发布时间】:2020-09-29 11:35:12
【问题描述】:

我正在制作一个 android 应用程序,其中唯一的用户登录和注册方法是通过电话身份验证。我有一个活动并使用片段。

我想在 SignInFragment 中添加 Firebase 电话身份验证并使用 Firebase PhoneAuthProvider。但是,这仅适用于我认为的活动,因为我尝试在我的片段中实现并且我的应用程序崩溃了。

这是SignInFragment.java的代码

package com.example.XX;

import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseException;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthProvider;

import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

public class SignInFragment extends Fragment {

    private static final String TAG ="INSIDE_SIGN_IN_FRAGMENT" ;
    FirebaseAuth mAuth;
    EditText xPhone;
    EditText xOTP;
    String codeSent;

    public SignInFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_sign_in, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        Button getOTP=view.findViewById(R.id.button_xOTP);
        Button submitButton=view.findViewById(R.id.signInbutton);
        xPhone=view.findViewById(R.id.editText_xMobile);
        xOTP=view.findViewById(R.id.editText_xOTP);

        mAuth=FirebaseAuth.getInstance();




        getOTP.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendVerificationCode();
            }
        });

        submitButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                verifyOTP();
            }
        });
    }

    private void verifyOTP(){
        String tOTP=xOTP.getText().toString().trim();

        if(tOTP.isEmpty()){
            xOTP.setError("OTP is required!");
            xOTP.requestFocus();
            return;
        }

        if(tOTP.length()<6){
            xOTP.setError("Please enter a valid OTP!");
            xOTP.requestFocus();
            return;
        }
        PhoneAuthCredential credential = PhoneAuthProvider.getCredential(codeSent, tOTP);
        signInWithPhoneAuthCredential(credential);
    }

    private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
        mAuth.signInWithCredential(credential)
                .addOnCompleteListener((Executor) 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.d(TAG, "signInWithCredential:success");

                            FirebaseUser user = task.getResult().getUser();
                            // ...
                        } else {
                            // Sign in failed, display a message and update the UI
                            Log.w(TAG, "signInWithCredential:failure", task.getException());
                            if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                                // The verification code entered was invalid
                            }
                        }
                    }
                });
    }

    private void sendVerificationCode() {

        String xMobileNumber=xPhone.getText().toString().trim();

        if(xMobileNumber.isEmpty()){
            xPhone.setError("Phone number is required!");
            xPhone.requestFocus();
            return;
        }

        if(xMobileNumber.length()<10){
            xPhone.setError("Please enter a valid phone number!");
            xPhone.requestFocus();
            return;
        }
        PhoneAuthProvider.getInstance().verifyPhoneNumber(
                xMobileNumber,        // Phone number to verify
                60,                 // Timeout duration
                TimeUnit.SECONDS,   // Unit of timeout
                (Executor) this,               // Activity (for callback binding) //NOT SURE ABOUT THIS
                mCallbacks);        // OnVerificationStateChangedCallbacks

    }

    PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks=new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
        @Override
        public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) {

        }

        @Override
        public void onVerificationFailed(@NonNull FirebaseException e) {

        }

        @Override
        public void onCodeSent(@NonNull String s, @NonNull PhoneAuthProvider.ForceResendingToken forceResendingToken) {
            super.onCodeSent(s, forceResendingToken);
            codeSent=s;
        }
    };


}

我的日志猫

LOGCAT:2020-06-10 03:59:44.148 16491-16491/com.example.XX
 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.XX, PID: 16491
    java.lang.ClassCastException: com.example.XX.SignInFragment cannot be cast to java.util.concurrent.Executor
        at com.example.XX.SignInFragment.sendVerificationCode(SignInFragment.java:132)
        at com.example.XX.SignInFragment.access$000(SignInFragment.java:29)
        at com.example.XX.SignInFragment$1.onClick(SignInFragment.java:65)
        at android.view.View.performClick(View.java:7201)
        at android.view.View.performClickInternal(View.java:7170)
        at android.view.View.access$3500(View.java:806)
        at android.view.View$PerformClick.run(View.java:27582)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7695)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

我知道问题出在执行程序部分,IDE 建议在两个地方使用执行程序。也许 PhoneAuth 方法不适用于片段。 任何人都可以查看此内容或告诉仅在 Fragment 内实现 Firebase 电话身份验证的替代方法。

【问题讨论】:

    标签: java android firebase android-fragments firebase-realtime-database


    【解决方案1】:

    this关键字用于活动。

    在片段中使用getActivity() 而不是this

    替换

     PhoneAuthProvider.getInstance().verifyPhoneNumber(
                    xMobileNumber,        // Phone number to verify
                    60,                   // Timeout duration
                    TimeUnit.SECONDS,     // Unit of timeout
                    (Executor) this,      // Activity (for callback binding)
                    mCallbacks);          // OnVerificationStateChangedCallbacks
    
     }
    

     PhoneAuthProvider.getInstance().verifyPhoneNumber(
                    xMobileNumber,        // Phone number to verify
                    60,                   // Timeout duration
                    TimeUnit.SECONDS,     // Unit of timeout
                    getActivity(),        // Activity (for callback binding)
                    mCallbacks);          // OnVerificationStateChangedCallbacks
    
     }
    

    更新

    为了避免应用崩溃检查:

    if (codeSent == null || TextUtils.isEmpty(codeSent)) {
        Toast.makeText(this, "Please wait until code received", Toast.LENGTH_SHORT).show();
    
        return;
    }
    
    PhoneAuthCredential credential = PhoneAuthProvider.getCredential(codeSent, tOTP);
    
    signInWithPhoneAuthCredential(credential);
    
    

    【讨论】:

    • 我用 getActivity(), 替换了这两个(Executor)。我没有收到任何编译错误,但我的设备上也没有收到 OTP
    • 另外,如果我不输入手机号码而只是输入任何随机的 OTP 并点击提交,我的应用程序就会崩溃
    • 要获得 OTP,您需要提供带有国家代码和加号的电话号码 (+1 239 239 2390)
    猜你喜欢
    • 1970-01-01
    • 2020-01-24
    • 2021-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    相关资源
    最近更新 更多