Trying to implement firebase auth. It was working before but after refactoring no. So I tried to create authStateListener in a separate class and there I am checking the statement. MainActivity
IMainPresenter iMainPresenter;
iMainPresenter = new MainPresenter();
iMainPresenter.forwardInfoForLoginAuth(MainActivity.this);
In presenter
public class MainPresenter implements IMainPresenter{
AuthStateListenerUtil authStateListenerUtil;
public MainPresenter() {
this.authStateListenerUtil = authStateListenerUtil;
}
@Override
public void forwardInfoForLoginAuth(Activity mainActivity) {
AuthStateListenerUtil authStateListenerUtils = new AuthStateListenerUtil();
authStateListenerUtils.checkForAuthState(mainActivity);
}
}
And the class which has to check the state of the user and in case that user is not logged in it has to show login window
public void checkForAuthState(final Activity mainActivity){
Log.v("==========>", " IN CHECK FOR METHOD");
new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
if (FirebaseUserUtil.currentUser != null) {
//Create new user
final String userName = FirebaseUserUtil.currentUser.getDisplayName();
FirebaseUserUtil.getCurrentUserUid(FirebaseUserUtil.userUid)
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
//the image is still the default one
HashMap<String, String> userMap = new HashMap<>();
userMap.put("name", userName);
userMap.put("image", "default");
userMap.put("thumb_image", "default");
userMap.put("status", "Your status is here...");
FirebaseUserUtil.getCurrentUserUid(FirebaseUserUtil.userUid).setValue(userMap);
}
@Override
public void onCancelled(DatabaseError databaseError) {}
});
} else {
mainActivity.startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(Arrays.asList(
new AuthUI.IdpConfig.EmailBuilder().build(),
new AuthUI.IdpConfig.GoogleBuilder().build()))
.build(),
RC_SIGN_IN);
}
}
};
}
I am trying to initialize all main queries in one class to avoid duplicating on each activity. In future I will refactor it to dagger2 but right now I am using regular classes. So thats the query class
public class FirebaseUserUtil {
public static FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
public static String currentUserUid = currentUser.getUid();
public static DatabaseReference getCurrentUserUid(){
return FirebaseDatabase.getInstance().getReference().child("Users").child(currentUserUid);
}
static String getCurrentUserUidString(String uid){
String currentUid = FirebaseDatabase.getInstance().getReference().child("Users").child(currentUserUid).toString();
return currentUid;
}
}
In logs it shows me tag "IN CHECK FOR METHOD" so I made a conclusion that threw presenter it finds this method but it crashes. Also, I thought that it might be a problem with firebase database. So I removed everything from there. So if I understand right if the table in firebase is empty after user login it has to create a new table with data. Also the problem is that error which I can see in logcat don't give me a link or information where is the mistake.
FATAL EXCEPTION: main
Process: com.borisruzanov.russianwives, PID: 6777
java.lang.NullPointerException: Attempt to invoke interface method 'void com.google.firebase.auth.FirebaseAuth$AuthStateListener.onAuthStateChanged(com.google.firebase.auth.FirebaseAuth)' on a null object reference
at com.google.firebase.auth.zzi.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
My App class
public class App extends Application{
private DatabaseReference mUserDatabase;
private FirebaseAuth mAuth;
@Override
public void onCreate() {
super.onCreate();
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
/* Picasso */
Picasso.Builder builder = new Picasso.Builder(this);
builder.downloader(new OkHttpDownloader(this, Integer.MAX_VALUE));
Picasso built = builder.build();
built.setIndicatorsEnabled(true);
built.setLoggingEnabled(true);
Picasso.setSingletonInstance(built);
mAuth = FirebaseAuth.getInstance();
if(mAuth.getCurrentUser() != null) {
mUserDatabase = FirebaseDatabase.getInstance()
.getReference().child("Users").child(mAuth.getCurrentUser().getUid());
mUserDatabase.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot != null) {
mUserDatabase.child("online").onDisconnect().setValue(ServerValue.TIMESTAMP);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
}
For me it looks like that the error is in Database not in code.
If your behavior it's the same for all user state changes you've to use "addAuthStateListener".
For AuthStateListener works you have to execute some of methods to authenticate ("signInWithEmailAndPassword", "createUserWithEmailAndPassword", ...).
The best way to implement a FirebaseAuth is keeping an instance in your Presenter or Interactor of that object and program the same code block for all:
FirebaseAuth mAuth;
public MainPresenter() {
FirebaseAuth mAuth = FirebaseAuth.getInstance();
mAuth.addAuthStateListener(new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
/*
* put your code here
*/
}
});
}
Or addOnCompleteListener for each method of authentication (in this case signInWithEmailAndPassword).
public void login(String email, String password){
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
Log.d(getClass().getSimpleName(), "signInWithEmail:onComplete:" + task.isSuccessful());
if (task.isSuccessful()) {
Log.w(getClass().getSimpleName(), "signInWithEmail", task.getException());
FirebaseUser user = mAuth.getCurrentUser();
if (user!=null) {
listener.onResult(null, user);
}
} else {
listener.onResult(task.getException(), null);
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
listener.onResult(e, null);
}
});
}
When you are using the floowing line of code:
new FirebaseAuth.AuthStateListener() {/* ... */}
It means that you are creating a new instance of AuthStateListener
class but without assignin it to a variable.
So it gives you a NPE
because you using addAuthStateListener()
on an object that has the value of null
. To solve this, just asign new FirebaseAuth.AuthStateListener()
to you mAuth
field and then use it wherever you want.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.