Android Firebase 注销应用程序在我注销后崩溃
Posted
技术标签:
【中文标题】Android Firebase 注销应用程序在我注销后崩溃【英文标题】:Android Firebase logout app crashes AFTER I logout 【发布时间】:2021-08-03 17:13:08 【问题描述】:我有我在其中处理注销的 MainActivity。问题是我注销后,应用程序在verifyUserExistance()
处崩溃:
String userID = Objects.requireNonNull(mAuth.getCurrentUser()).getUid();
这给出了:
E/androidRuntime: 致命异常: main 进程:com.google.firebase.quickstart.auth,PID:8459 java.lang.NullPointerException 在 java.util.Objects.requireNonNull(Objects.java:203) 在 com.google.firebase.quickstart.auth.social.Main_Chat_Activity$3.lambda$null$1$Main_Chat_Activity$3(Main_Chat_Activity.java:372) 在 com.google.firebase.quickstart.auth.social.-$$Lambda$Main_Chat_Activity$3$87CwjFnoJAhucBGNsLP_MxK833o.onComplete(未知来源:2) 在 com.google.android.gms.tasks.zzj.run(com.google.android.gms:play-services-tasks@@17.2.0:4) 在 android.os.Handler.handleCallback(Handler.java:873) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:214) 在 android.app.ActivityThread.main(ActivityThread.java:7050) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
下面是我使用的代码:
@Override
protected void onStart()
super.onStart();
usersRef.child(mAuth.getCurrentUser().getUid()).addListenerForSingleValueEvent(new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot snapshot)
if (!snapshot.hasChild("name"))
sendUserToLoginActivity();
@Override
public void onCancelled(@NonNull DatabaseError error)
);
if (mAuth == null || currentUser == null || mAuth.getCurrentUser().getUid() == null )
finish();
sendUserToLoginActivity();
else
if(mAuth.getCurrentUser().getProviderId() == "google.com")
user.setmGoogleSignInClient(mGoogleSignInClient);
user.setMauth(mAuth);
if (loginOutFlag>-1)
verifyUserExistence();
checkLocation();
if (isNew!=null)
if (isNew.equals("true"))
sendUserToSettingsActivity();
方法verifyUserExistance是;
private void verifyUserExistence()
if (!verified && loginOutFlag > -1)
String currentUserID = mAuth.getCurrentUser().getUid();
try
rootRef.child("Users").child(currentUserID).addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot)
if (dataSnapshot.child("name").exists())
loginOutFlag = 1;
Toast.makeText(Main_Chat_Activity.this, "Welcome" + dataSnapshot.child("name").getValue().toString(), Toast.LENGTH_SHORT).show();
Log.w("Reportname:", dataSnapshot.child("name").getValue().toString());
Calendar cal = Calendar.getInstance();
final String timeNDate = cal.getTime().toString();
HashMap<String, Object> profileMap = new HashMap<>();
profileMap.put("connection", timeNDate);
rootRef.child("Users").child(currentUserID).updateChildren(profileMap)
.addOnCompleteListener(task ->
if (task.isSuccessful())
Toast.makeText(Main_Chat_Activity.this, "Success ", Toast.LENGTH_SHORT).show();
verified = true;
FirebaseMessaging.getInstance().getToken()
.addOnCompleteListener(task13 ->
String userID = Objects.requireNonNull(mAuth.getCurrentUser()).getUid();
if (!task13.isSuccessful())
Log.w("FCM", "Fetching FCM registration token failed", task13.getException());
return;
// Get new FCM registration token
String deviceToken = task13.getResult();
// Log and toast
Log.d("FCM", deviceToken);
Toast.makeText(Main_Chat_Activity.this, deviceToken, Toast.LENGTH_SHORT).show();
final int[] no = 0;
DatabaseReference tokens = usersRef.child(userID).child("device_tokens");
ValueEventListener valueEventListener = new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot snapshot)
no[0] = (int) snapshot.getChildrenCount();
@Override
public void onCancelled(@NonNull DatabaseError error)
;
tokens.addListenerForSingleValueEvent(valueEventListener);
String devName = "device" + no[0];
String token = deviceToken.split(":")[1];
usersRef.child(userID).child("device_tokens").child(devName)
.setValue(token)
.addOnCompleteListener(task12 ->
if (task12.isSuccessful())
Toast.makeText(Main_Chat_Activity.this, "Token updated succesfully.", Toast.LENGTH_LONG).show();
);
);
else
String errorMSG = Objects.requireNonNull(task.getException()).toString();
//user.setMauth(null);
Toast.makeText(Main_Chat_Activity.this, "Error : " + errorMSG, Toast.LENGTH_SHORT).show();
);
@Override
public void onCancelled(@NonNull DatabaseError databaseError)
);
catch (Exception e)
Log.d("EXCEPTION", e.toString());
这就是我处理注销的方式;
@Override
public boolean onOptionsItemSelected(MenuItem item)
super.onOptionsItemSelected(item);
if (item.getItemId() == R.id.main_logout_option)
updateUserStatus("offline");
String currentUserID = mAuth.getCurrentUser().getUid();
rootRef.child("Users").child(currentUserID).addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot)
if (dataSnapshot.child("name").exists())
Calendar cal = Calendar.getInstance();
final String timeNDate = cal.getTime().toString();
HashMap<String, Object> profileMap = new HashMap<>();
profileMap.put("connection", timeNDate);
rootRef.child("Users").child(currentUserID).updateChildren(profileMap)
.addOnCompleteListener(task ->
if (task.isSuccessful())
loginOutFlag = -1;
else
String errorMSG = Objects.requireNonNull(task.getException()).toString();
Toast.makeText(Main_Chat_Activity.this, "This error : " + errorMSG, Toast.LENGTH_SHORT).show();
mGoogleSignInClient.signOut().addOnCompleteListener(task1 ->
if (task1.isSuccessful())
mAuth.signOut(); // very important if you are using firebase.
LoginManager.getInstance().logOut();
sendUserToLoginActivity();
finish();
);
);
@Override
public void onCancelled(@NonNull DatabaseError databaseError)
);
sendUserToLoginActivity();
if (item.getItemId() == R.id.main_settings_option)
sendUserToSettingsActivity();
if (item.getItemId() == R.id.main_find_friends_option)
sendUserToFindFriendsActivity();
return true;
【问题讨论】:
【参考方案1】:问题是我注销后,应用程序崩溃:
at line String userID = Objects.requireNonNull(mAuth.getCurrentUser()).getUid()
当您注销时,mAuth
对象变为null
。因此在这样的对象上调用getCurrentUser(),而不是返回FirebaseUser 对象,它将返回null
,因此存在NullPointerExcepetion。
返回当前登录的 FirebaseUser,如果没有则返回 null。
因此,解决您的问题的方法是等待异步操作完成,然后立即退出,否则,您将始终得到 NullPointerExcepetion。
这是一个示例,您可以等到从实时数据库中加载完数据:
How to return DataSnapshot value as a result of a method?【讨论】:
看到问题是如果 mAuth 为空,那么在 onStart() 方法中它应该将我发送到 loginActivity,因为我使用了if (mAuth == null || currentUser == null || mAuth.getCurrentUser().getUid() == null ) finish(); sendUserToLoginActivity(); else if(mAuth.getCurrentUser().getProviderId() == "google.com") user.setmGoogleSignInClient(mGoogleSignInClient); user.setMauth(mAuth); if (loginOutFlag>-1) verifyUserExistence();
,但它没有。问题真的出自这里。还有其他选择吗?
如果mAuth
在onStart()中为null,则表示用户未登录。在对此类对象进行进一步操作之前,您应该检查这一点。不幸的是,除了等待数据之外,没有其他选择。尝试等待数据并告诉我它是否有效。
但 mAuth 为空(或应该为空),因为我退出了。然而在onStart
中,它似乎不是,这就是它错误地调用verifyUserExistance
的原因。
您是否尝试在异步操作完成后退出?
我认为可能还有更多。看,当我单击注销时,UI 更改为 LoginActivity,然后它才会崩溃。但这没有意义。我称为finish()
的活动如何在另一个活动开始后崩溃??以上是关于Android Firebase 注销应用程序在我注销后崩溃的主要内容,如果未能解决你的问题,请参考以下文章
注销Firebase经过身份验证的用户后写入Firestore
当我使用重新加载功能时,Firebase Auth 会注销我吗?
Firebase Auth - 更新用户的电子邮件后,Firebase Auth 会注销用户