为什么 firebase 身份验证返回 null?
Why is firebase authentication returning null?
我正在尝试实施 Firebase 匿名身份验证并从应用程序获取唯一 ID,但它使 运行 变为空 UID 错误。我使用以下代码块进行匿名登录并获取用户的 UID:
// Firebase Anonymous Auth
firebaseAuth = FirebaseAuth.getInstance();
firebaseUser = firebaseAuth.getCurrentUser();
if(firebaseUser == null){
firebaseAuth.signInAnonymously()
.addOnCompleteListener(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
firebaseUser = firebaseAuth.getCurrentUser();
currentUserID = firebaseUser.getUid();
}
}
});
}
我按照 Firebase 文档中给出的说明进行操作,但由于某种原因它不起作用。每当我尝试引用 currentUserID
它 returns 错误时:Attempt to invoke virtual method 'void com.example.rllauncher.TouchData.setUniqueID(java.lang.String)' on a null object reference
我一直在努力缩小问题的范围,但大多数匿名登录的实现都是通过这种方式完成的,所以我无法缩小问题的根源。到底是什么导致了这里的问题?
这是完整的 Activity 代码:
public class ButtonPress extends AppCompatActivity implements View.OnClickListener {
private Button button;
private DisplayMetrics displaymetrics;
private RelativeLayout loOPenArea;
private Handler mHandler = new Handler();
private String currentUSerID;
String TASK_NAME = "ButtonPress";
FirebaseAuth mAuth = FirebaseAuth.getInstance();
FirebaseUser mFirebaseUser = mAuth.getCurrentUser();
String mCurrentUserID = mFirebaseUser != null
? mFirebaseUser.getUid()
: null;
FirebaseAuth.AuthStateListener mAuthListener = new FirebaseAuth.AuthStateListener() {
@NonNull
@Override
public void onAuthStateChanged(FirebaseAuth auth) {
mFirebaseUser = auth.getCurrentUser();
if (mFirebaseUser == null) {
// user has been confirmed to be signed out
// reset state, detach listeners, etc
mCurrentUserID = null;
return;
}
// user has been confirmed to be signed in
mCurrentUserID = mFirebaseUser.getUid();
currentUSerID = mCurrentUserID;
// do something, refresh UI, etc
}
};
private VelocityTracker mVelocityTracker = null;
public static final DatabaseReference databaseReference = FirebaseDatabase.getInstance("https://pragya-datacollector.firebaseio.com").getReference();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.button_press);
button = findViewById(R.id.my_button);
button.setClickable(true);
button.setOnClickListener(this);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Intent i = new Intent(ButtonPress.this, IntermediateActivity.class);
i.putExtra("type", "failure");
if (!ButtonPress.this.isFinishing())
{ ButtonPress.this.startActivity(i);
ButtonPress.this.finish();
}
}
}, 10000);
// Wait until the first layout to get button size and placement to compute x/y placement range.
button.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
button.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// Capture width and x/y placement ranges here
final Button button = (Button) findViewById(R.id.my_button);
displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
loOPenArea = (RelativeLayout) findViewById(R.id.open_area_press);
// Button will have a horizontal margin from zero to the width of its parent less
// the width of the button less the initial left side of the button which is likely
// to be the initial margin.
int buttonMaxXMargin = loOPenArea.getWidth() - button.getWidth() - button.getLeft();
// Similar for the vertical placement.
int buttonMaxYMargin = loOPenArea.getHeight() - button.getHeight() - button.getTop();
int leftMargin = new Random().nextInt(buttonMaxXMargin);
int topMargin = new Random().nextInt(buttonMaxYMargin);
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) button.getLayoutParams();
p.setMargins(leftMargin, topMargin, 0, 0);
button.setLayoutParams(p);
}
});
}
@Override
public void onClick(View v) {
Vibrator x = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
x.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
x.vibrate(500);
}
Intent i = null;
switch (v.getId()) {
case R.id.my_button:
i = new Intent(ButtonPress.this, IntermediateActivity.class);
i.putExtra("type", "null");
if (!ButtonPress.this.isFinishing())
{ ButtonPress.this.startActivity(i);
ButtonPress.this.finish();
}
break;
}
}
public boolean dispatchTouchEvent(MotionEvent event) {
TouchData touchData = null;
int index = event.getActionIndex();
int pointerId = event.getPointerId(index);
List<Float> xTraj = new ArrayList<Float>();
List<Float> yTraj = new ArrayList<Float>();
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
xTraj.add(event.getX());
yTraj.add(event.getY());
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
xTraj.add(event.getX());
yTraj.add(event.getY());
if(mVelocityTracker == null) {
// Retrieve a new VelocityTracker object to watch the velocity of a motion.
mVelocityTracker = VelocityTracker.obtain();
}
else {
// Reset the velocity tracker back to its initial state.
mVelocityTracker.clear();
}
// Add a user's movement to the tracker.
mVelocityTracker.addMovement(event);
break;
case MotionEvent.ACTION_UP:
mVelocityTracker.recycle();
float centreX = button.getX() + button.getWidth() / 2;
float centreY = button.getY() + button.getHeight() / 2;
long eventDuration = event.getEventTime() - event.getDownTime();
touchData.setUniqueID(currentUSerID);
touchData.setTaskName(TASK_NAME);
touchData.setTouchDuration(eventDuration);
touchData.setxTrajectory(xTraj);
touchData.setyTrajectory(yTraj);
touchData.setxVelocity(VelocityTrackerCompat.getXVelocity(mVelocityTracker, pointerId));
touchData.setyVelocity(VelocityTrackerCompat.getYVelocity(mVelocityTracker, pointerId));
touchData.setTargetX(centreX);
touchData.setTargetY(centreY);
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
databaseReference.setValue(touchData);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
break;
case MotionEvent.ACTION_MOVE:
xTraj.add(event.getX());
yTraj.add(event.getY());
mVelocityTracker.addMovement(event);
mVelocityTracker.computeCurrentVelocity(1);
break;
case MotionEvent.ACTION_CANCEL:
mVelocityTracker.recycle();
break;
}
return super.dispatchTouchEvent(event);
}
@Override
public void onBackPressed() {
finish();
IntermediateActivity.visitCount = 0;
Intent k = new Intent(ButtonPress.this, MainActivity.class);
k.putExtra("type", "null");
startActivity(k);
}
@Override
protected void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
if (mFirebaseUser == null) {
mAuth.signInAnonymously()
.addOnFailureListener(new OnFailureListener() {
@NonNull
@Override
public void onFailure(Exception ex) {
// TODO: Handle exceptions!
Log.e("TAG", "Failed to sign in anonymously: " + ex.getMessage());
}
});
}
}
@Override
protected void onStop() {
super.onStop();
mAuth.removeAuthStateListener(mAuthListener);
}
}
我认为你应该初始化一次 task.isSuccessful()
。
firebaseAuth = FirebaseAuth.getInstance();
if(firebaseAuth.getCurrentUser() == null){
firebaseAuth.signInAnonymously().addOnCompleteListener(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
final FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
currentUserID = firebaseUser.getUid();
}
}
});
}
更新:
您不能在方法外初始化它们。
public class ButtonPress extends AppCompatActivity implements View.OnClickListener {
private Button button;
private DisplayMetrics displaymetrics;
private RelativeLayout loOPenArea;
private Handler mHandler = new Handler();
private String currentUSerID;
String TASK_NAME = "ButtonPress";
FirebaseAuth mAuth; //Just variable, dont do anything
FirebaseUser mFirebaseUser;//Just variable, dont do anything
String mCurrentUserID;//Just variable, dont do anything
问题是由竞争条件引起的。身份验证是一种异步操作,这意味着某些数据可能尚未准备好使用。重要的是,在 onStart
/onCreate
中使用全局状态(如 firebaseUser
)会给你带来麻烦,如果该用户注销,他们的令牌被撤销或活动登录用户更改将指向过时的信息。
在你的问题中,我假设你的代码类似于:
// top of file
FirebaseAuth firebaseAuth;
FirebaseUser firebaseUser;
String currentUserID;
// ...
// Firebase Anonymous Auth
firebaseAuth = FirebaseAuth.getInstance();
firebaseUser = firebaseAuth.getCurrentUser();
if (firebaseUser == null) {
firebaseAuth.signInAnonymously()
.addOnCompleteListener(/* ... */)
} else {
currentUserId = firebaseUser.getCurrentUser().getUid();
}
TouchData data = new TouchData();
data.setUniqueID(currentUserID); // <-- `null` exception here
这是因为 signInAnonymously
进程是异步的。当调用 TouchData.setUniqueID(currentUserID)
时,在登录过程完成之前它仍将是 null
。
您还应确保正确处理任何异常,不要只是静静地忽略它们。
if (firebaseUser == null) {
firebaseAuth.signInAnonymously()
.addOnCompleteListener(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
firebaseUser = task.getResult().getUser();
currentUserID = firebaseUser.getUid();
} else {
// TODO: Handle exceptions!
Exception ex = task.getException();
Log.e(TAG, "Failed to sign in anonymously: " + ex.getMessage());
}
}
});
}
如果您的代码依赖于有效的用户会话,则应改用 AuthStateListener
。此侦听器将在许多情况下触发,例如在用户登录后。使用它来附加点击处理程序、更新 UI 等
FirebaseAuth mAuth = FirebaseAuth.getInstance();
FirebaseUser mFirebaseUser = mAuth.getCurrentUser();
String mCurrentUserID = mFirebaseUser != null
? mFirebaseUser.getUid()
: null;
AuthStateListener mAuthListener = new AuthStateListener() {
@NonNull
@Override
public void onAuthStateChanged(FirebaseAuth auth) {
mFirebaseUser = auth.getCurrentUser();
if (user == null) {
// user has been confirmed to be signed out
// reset state, detach listeners, etc
mCurrentUserID = null;
return;
}
// user has been confirmed to be signed in
mCurrentUserID = user.getUid();
// do something, refresh UI, etc
}
}
// in onStart
mAuth.addAuthStateListener(mAuthListener);
if (mFirebaseUser == null) {
mAuth.signInAnonymously()
.addOnFailureListener(new OnFailureListener() {
@NonNull
@Override
public void onFailure(Exception ex) {
// TODO: Handle exceptions!
Log.e(TAG, "Failed to sign in anonymously: " + ex.getMessage());
}
});
}
// in onStop
mAuth.removeAuthStateListener(mAuthListener);
如果您的 onAuthStateChanged
逻辑开始失控,请将其逻辑拆分为 onAuthSignedIn
和 onAuthSignedOut
方法:
AuthStateListener mAuthListener = new AuthStateListener() {
@NonNull
@Override
public void onAuthStateChanged(FirebaseAuth auth) {
if (auth.getCurrentUser() != null) {
onAuthSignedIn(auth);
} else {
onAuthSignedOut(auth);
}
}
}
public void onAuthSignedIn(FirebaseAuth auth) {
}
public void onAuthSignedOut(FirebaseAuth auth) {
}
我正在尝试实施 Firebase 匿名身份验证并从应用程序获取唯一 ID,但它使 运行 变为空 UID 错误。我使用以下代码块进行匿名登录并获取用户的 UID:
// Firebase Anonymous Auth
firebaseAuth = FirebaseAuth.getInstance();
firebaseUser = firebaseAuth.getCurrentUser();
if(firebaseUser == null){
firebaseAuth.signInAnonymously()
.addOnCompleteListener(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
firebaseUser = firebaseAuth.getCurrentUser();
currentUserID = firebaseUser.getUid();
}
}
});
}
我按照 Firebase 文档中给出的说明进行操作,但由于某种原因它不起作用。每当我尝试引用 currentUserID
它 returns 错误时:Attempt to invoke virtual method 'void com.example.rllauncher.TouchData.setUniqueID(java.lang.String)' on a null object reference
我一直在努力缩小问题的范围,但大多数匿名登录的实现都是通过这种方式完成的,所以我无法缩小问题的根源。到底是什么导致了这里的问题?
这是完整的 Activity 代码:
public class ButtonPress extends AppCompatActivity implements View.OnClickListener {
private Button button;
private DisplayMetrics displaymetrics;
private RelativeLayout loOPenArea;
private Handler mHandler = new Handler();
private String currentUSerID;
String TASK_NAME = "ButtonPress";
FirebaseAuth mAuth = FirebaseAuth.getInstance();
FirebaseUser mFirebaseUser = mAuth.getCurrentUser();
String mCurrentUserID = mFirebaseUser != null
? mFirebaseUser.getUid()
: null;
FirebaseAuth.AuthStateListener mAuthListener = new FirebaseAuth.AuthStateListener() {
@NonNull
@Override
public void onAuthStateChanged(FirebaseAuth auth) {
mFirebaseUser = auth.getCurrentUser();
if (mFirebaseUser == null) {
// user has been confirmed to be signed out
// reset state, detach listeners, etc
mCurrentUserID = null;
return;
}
// user has been confirmed to be signed in
mCurrentUserID = mFirebaseUser.getUid();
currentUSerID = mCurrentUserID;
// do something, refresh UI, etc
}
};
private VelocityTracker mVelocityTracker = null;
public static final DatabaseReference databaseReference = FirebaseDatabase.getInstance("https://pragya-datacollector.firebaseio.com").getReference();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.button_press);
button = findViewById(R.id.my_button);
button.setClickable(true);
button.setOnClickListener(this);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Intent i = new Intent(ButtonPress.this, IntermediateActivity.class);
i.putExtra("type", "failure");
if (!ButtonPress.this.isFinishing())
{ ButtonPress.this.startActivity(i);
ButtonPress.this.finish();
}
}
}, 10000);
// Wait until the first layout to get button size and placement to compute x/y placement range.
button.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
button.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// Capture width and x/y placement ranges here
final Button button = (Button) findViewById(R.id.my_button);
displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
loOPenArea = (RelativeLayout) findViewById(R.id.open_area_press);
// Button will have a horizontal margin from zero to the width of its parent less
// the width of the button less the initial left side of the button which is likely
// to be the initial margin.
int buttonMaxXMargin = loOPenArea.getWidth() - button.getWidth() - button.getLeft();
// Similar for the vertical placement.
int buttonMaxYMargin = loOPenArea.getHeight() - button.getHeight() - button.getTop();
int leftMargin = new Random().nextInt(buttonMaxXMargin);
int topMargin = new Random().nextInt(buttonMaxYMargin);
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) button.getLayoutParams();
p.setMargins(leftMargin, topMargin, 0, 0);
button.setLayoutParams(p);
}
});
}
@Override
public void onClick(View v) {
Vibrator x = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
x.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
x.vibrate(500);
}
Intent i = null;
switch (v.getId()) {
case R.id.my_button:
i = new Intent(ButtonPress.this, IntermediateActivity.class);
i.putExtra("type", "null");
if (!ButtonPress.this.isFinishing())
{ ButtonPress.this.startActivity(i);
ButtonPress.this.finish();
}
break;
}
}
public boolean dispatchTouchEvent(MotionEvent event) {
TouchData touchData = null;
int index = event.getActionIndex();
int pointerId = event.getPointerId(index);
List<Float> xTraj = new ArrayList<Float>();
List<Float> yTraj = new ArrayList<Float>();
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
xTraj.add(event.getX());
yTraj.add(event.getY());
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
xTraj.add(event.getX());
yTraj.add(event.getY());
if(mVelocityTracker == null) {
// Retrieve a new VelocityTracker object to watch the velocity of a motion.
mVelocityTracker = VelocityTracker.obtain();
}
else {
// Reset the velocity tracker back to its initial state.
mVelocityTracker.clear();
}
// Add a user's movement to the tracker.
mVelocityTracker.addMovement(event);
break;
case MotionEvent.ACTION_UP:
mVelocityTracker.recycle();
float centreX = button.getX() + button.getWidth() / 2;
float centreY = button.getY() + button.getHeight() / 2;
long eventDuration = event.getEventTime() - event.getDownTime();
touchData.setUniqueID(currentUSerID);
touchData.setTaskName(TASK_NAME);
touchData.setTouchDuration(eventDuration);
touchData.setxTrajectory(xTraj);
touchData.setyTrajectory(yTraj);
touchData.setxVelocity(VelocityTrackerCompat.getXVelocity(mVelocityTracker, pointerId));
touchData.setyVelocity(VelocityTrackerCompat.getYVelocity(mVelocityTracker, pointerId));
touchData.setTargetX(centreX);
touchData.setTargetY(centreY);
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
databaseReference.setValue(touchData);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
break;
case MotionEvent.ACTION_MOVE:
xTraj.add(event.getX());
yTraj.add(event.getY());
mVelocityTracker.addMovement(event);
mVelocityTracker.computeCurrentVelocity(1);
break;
case MotionEvent.ACTION_CANCEL:
mVelocityTracker.recycle();
break;
}
return super.dispatchTouchEvent(event);
}
@Override
public void onBackPressed() {
finish();
IntermediateActivity.visitCount = 0;
Intent k = new Intent(ButtonPress.this, MainActivity.class);
k.putExtra("type", "null");
startActivity(k);
}
@Override
protected void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
if (mFirebaseUser == null) {
mAuth.signInAnonymously()
.addOnFailureListener(new OnFailureListener() {
@NonNull
@Override
public void onFailure(Exception ex) {
// TODO: Handle exceptions!
Log.e("TAG", "Failed to sign in anonymously: " + ex.getMessage());
}
});
}
}
@Override
protected void onStop() {
super.onStop();
mAuth.removeAuthStateListener(mAuthListener);
}
}
我认为你应该初始化一次 task.isSuccessful()
。
firebaseAuth = FirebaseAuth.getInstance();
if(firebaseAuth.getCurrentUser() == null){
firebaseAuth.signInAnonymously().addOnCompleteListener(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
final FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
currentUserID = firebaseUser.getUid();
}
}
});
}
更新:
您不能在方法外初始化它们。
public class ButtonPress extends AppCompatActivity implements View.OnClickListener {
private Button button;
private DisplayMetrics displaymetrics;
private RelativeLayout loOPenArea;
private Handler mHandler = new Handler();
private String currentUSerID;
String TASK_NAME = "ButtonPress";
FirebaseAuth mAuth; //Just variable, dont do anything
FirebaseUser mFirebaseUser;//Just variable, dont do anything
String mCurrentUserID;//Just variable, dont do anything
问题是由竞争条件引起的。身份验证是一种异步操作,这意味着某些数据可能尚未准备好使用。重要的是,在 onStart
/onCreate
中使用全局状态(如 firebaseUser
)会给你带来麻烦,如果该用户注销,他们的令牌被撤销或活动登录用户更改将指向过时的信息。
在你的问题中,我假设你的代码类似于:
// top of file
FirebaseAuth firebaseAuth;
FirebaseUser firebaseUser;
String currentUserID;
// ...
// Firebase Anonymous Auth
firebaseAuth = FirebaseAuth.getInstance();
firebaseUser = firebaseAuth.getCurrentUser();
if (firebaseUser == null) {
firebaseAuth.signInAnonymously()
.addOnCompleteListener(/* ... */)
} else {
currentUserId = firebaseUser.getCurrentUser().getUid();
}
TouchData data = new TouchData();
data.setUniqueID(currentUserID); // <-- `null` exception here
这是因为 signInAnonymously
进程是异步的。当调用 TouchData.setUniqueID(currentUserID)
时,在登录过程完成之前它仍将是 null
。
您还应确保正确处理任何异常,不要只是静静地忽略它们。
if (firebaseUser == null) {
firebaseAuth.signInAnonymously()
.addOnCompleteListener(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
firebaseUser = task.getResult().getUser();
currentUserID = firebaseUser.getUid();
} else {
// TODO: Handle exceptions!
Exception ex = task.getException();
Log.e(TAG, "Failed to sign in anonymously: " + ex.getMessage());
}
}
});
}
如果您的代码依赖于有效的用户会话,则应改用 AuthStateListener
。此侦听器将在许多情况下触发,例如在用户登录后。使用它来附加点击处理程序、更新 UI 等
FirebaseAuth mAuth = FirebaseAuth.getInstance();
FirebaseUser mFirebaseUser = mAuth.getCurrentUser();
String mCurrentUserID = mFirebaseUser != null
? mFirebaseUser.getUid()
: null;
AuthStateListener mAuthListener = new AuthStateListener() {
@NonNull
@Override
public void onAuthStateChanged(FirebaseAuth auth) {
mFirebaseUser = auth.getCurrentUser();
if (user == null) {
// user has been confirmed to be signed out
// reset state, detach listeners, etc
mCurrentUserID = null;
return;
}
// user has been confirmed to be signed in
mCurrentUserID = user.getUid();
// do something, refresh UI, etc
}
}
// in onStart
mAuth.addAuthStateListener(mAuthListener);
if (mFirebaseUser == null) {
mAuth.signInAnonymously()
.addOnFailureListener(new OnFailureListener() {
@NonNull
@Override
public void onFailure(Exception ex) {
// TODO: Handle exceptions!
Log.e(TAG, "Failed to sign in anonymously: " + ex.getMessage());
}
});
}
// in onStop
mAuth.removeAuthStateListener(mAuthListener);
如果您的 onAuthStateChanged
逻辑开始失控,请将其逻辑拆分为 onAuthSignedIn
和 onAuthSignedOut
方法:
AuthStateListener mAuthListener = new AuthStateListener() {
@NonNull
@Override
public void onAuthStateChanged(FirebaseAuth auth) {
if (auth.getCurrentUser() != null) {
onAuthSignedIn(auth);
} else {
onAuthSignedOut(auth);
}
}
}
public void onAuthSignedIn(FirebaseAuth auth) {
}
public void onAuthSignedOut(FirebaseAuth auth) {
}