0

I am having a problem working my app with the new changes the tutorial demanded. I followed the coding rules exactly (with exception of the new 'snapshot' entries as per the new version) and yet my 'MainActivity' keeps crashing. Users are still being registered in the authentication but the database and isn't registering them as I would have liked. My current database setup

The error console points towards 'DatabaseReference userDb = usersDb.child(user.getUid());' as the reason for crashing. I reckon there might be something wrong with the database, as it wasn't entirely clear how to set it up. Do let me know if there are new coding suggestions to get around this or whether I have missed something in the database setup. Please help.

Here is a link also to the tutorial I am following: https://www.youtube.com/watch?v=RagA8g9A5Qc&list=PLxabZQCAe5fio9dm1Vd0peIY6HLfo5MCf&index=17

    private String userSex;
private String notUserSex;
public void checkUserSex() {
    final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
    DatabaseReference userDb = usersDb.child(user.getUid());
    userDb.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
                if (snapshot.exists()) {
                    if (snapshot.child("sex").getValue() != null) {
                        userSex = snapshot.child("sex").getValue().toString();
                        switch (userSex) {
                            case "Male":
                                notUserSex = "Female";
                                break;
                            case "Female":
                                notUserSex = "Male";
                                break;
                        }
                        getOppositeSexUsers();
                    }
                }
            }
        @Override
        public void onCancelled(@NonNull DatabaseError error) {

        }
    });
}

public void getOppositeSexUsers(){
    usersDb.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
            if (snapshot.exists() && !snapshot.child("connections").child("no").hasChild(currentUId) && !snapshot.child("connections").child("yes").hasChild(currentUId) && snapshot.child("sex").getValue().toString().equals(notUserSex)){
                String profileImageUrl = "default";
                if(snapshot.child("profileImageUrl").getValue()!=null) {
                    if (!snapshot.child("profileImageUrl").getValue().equals("default")) {
                        profileImageUrl = snapshot.child("profileImageUrl").getValue().toString();
                    }
                }
                cards item = new cards(snapshot.getKey(), snapshot.child("name").getValue().toString(), profileImageUrl);
                rowItems.add(item);
                arrayAdapter.notifyDataSetChanged();
            }
        }

Logcat

2021-03-10 15:48:00.372 9915-9915/com.bendes.tinder2 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.bendes.tinder2, PID: 9915
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.bendes.tinder2/com.bendes.tinder2.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.firebase.database.DatabaseReference com.google.firebase.database.DatabaseReference.child(java.lang.String)' on a null object reference
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:223)
    at android.app.ActivityThread.main(ActivityThread.java:7656)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.firebase.database.DatabaseReference com.google.firebase.database.DatabaseReference.child(java.lang.String)' on a null object reference
    at com.bendes.tinder2.MainActivity.checkUserSex(MainActivity.java:141)
    at com.bendes.tinder2.MainActivity.onCreate(MainActivity.java:48)
    at android.app.Activity.performCreate(Activity.java:8000)
    at android.app.Activity.performCreate(Activity.java:7984)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loop(Looper.java:223) 
    at android.app.ActivityThread.main(ActivityThread.java:7656) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 

2021-03-10 15:48:00.438 9915-9915/com.bendes.tinder2 I/Process: Sending signal. PID: 9915 SIG: 9

public class MainActivity extends AppCompatActivity {
private cards cards_data[];
private arrayAdapter arrayAdapter;
private int i;

private Button logout;
private FirebaseAuth mAuth;
private String currentUId;
private DatabaseReference usersDb;

ListView listView;
List<cards> rowItems;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    checkUserSex();

    usersDb = FirebaseDatabase.getInstance().getReference().child("Users");
    mAuth = FirebaseAuth.getInstance();
    currentUId = mAuth.getCurrentUser().getUid();

    logout = (Button) findViewById(R.id.signout);
    logout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            FirebaseAuth.getInstance().signOut();
            startActivity(new Intent(MainActivity.this, ChooseLoginOrRegistrationActivity.class));
        }
    });
BenDeS
  • 21
  • 3
  • 2
    If the app crashes, there is a stack trace. Please look that up on logcat, and add it to your question. – Alex Mamo Mar 10 '21 at 15:26
  • Hi @AlexMamo. I added the Logcat. If you can detect the problem with my code or database please do let me know. Thanks again for your help – BenDeS Mar 10 '21 at 15:53
  • Show us how is `usersDb` instantiated? – Alex Mamo Mar 10 '21 at 15:55
  • Hi @AlexMamo I have edited the question to show usersDb in depth. Do let me know what else you need to see. Thanks again – BenDeS Mar 10 '21 at 15:58
  • Is your `usersDb` object defined in the same class in which is used? – Alex Mamo Mar 10 '21 at 16:33
  • @AlexMamo I'm not entirely sure what you mean by that – BenDeS Mar 10 '21 at 16:49
  • Your `usersDb` is null. You cannot call `.child()` on a null object. That's why I have asked you if `usersDb` object is defined in the same class in which is used? – Alex Mamo Mar 10 '21 at 17:12
  • The userDb that has been declared and the one used in checkUserSex are both used in the class 'MainActivity' which is where it is showing the errors. The first part of the code shows where it is used and the second part shows where it is first declared – BenDeS Mar 10 '21 at 19:23

2 Answers2

1

I know where I went wrong, it was my coding structure. Two errors occurred in the logcat: The checkUserSex();' declaration (line 48) and the database reference (line 141). It was merely a case of placing my 'checkUserSex();' underneath the other declarations of my 'onCreate' (so underneath usersDb, mAuth & currentUId.

enter image description here

enter image description here

enter image description here

BenDeS
  • 21
  • 3
0

You are getting Null Pointer Exception because user.getUid() returns NULL. So whenever user.getUid() is NULL, your application must prompt the user to login. After the login is successful, your application must follow your regular workflow such as checkUserSex()

The below solution might help you (Sample code shows Firebase Google authentication)

Declare the following additional variables in your activity

private static final int RC_SIGN_IN = 1;
private FirebaseAuth mAuth;
private GoogleSignInClient mGoogleSignInClient;

Modify your onCreate() method as follows

@Override
protected void onCreate ( Bundle savedInstanceState ) {
    super.onCreate ( savedInstanceState );
    setContentView ( R.layout.activity_main2 );
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder ( GoogleSignInOptions.DEFAULT_SIGN_IN )
            .requestIdToken ( getString ( R.string.default_web_client_id ) )
            .requestEmail ()
            .build ();
    mGoogleSignInClient = GoogleSignIn.getClient ( this, gso );
    mAuth = FirebaseAuth.getInstance();
    checkFirebaseUser ( mAuth.getCurrentUser () );
}

Add the following additional methods to your activity (For authentication)

private void checkFirebaseUser ( FirebaseUser currentUser ) {
    if (currentUser != null) {
        //Continue with your regular flow
        checkUserSex ();
    } else {
        //Sign In flow
        Intent signInIntent = mGoogleSignInClient.getSignInIntent ();
        startActivityForResult ( signInIntent, RC_SIGN_IN );
    }
}

@Override
public void onActivityResult ( int requestCode, int resultCode, Intent data ) {
    super.onActivityResult ( requestCode, resultCode, data );
    if (requestCode == RC_SIGN_IN) {
        Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent ( data );
        try {
            GoogleSignInAccount account = task.getResult ( ApiException.class );
            assert account != null;
            firebaseAuthWithGoogle ( account.getIdToken () );
        } catch (Exception e) {
            Toast.makeText ( this, "login failed", Toast.LENGTH_SHORT ).show ();
        }
    }
}

private void firebaseAuthWithGoogle ( String idToken ) {
    AuthCredential credential = GoogleAuthProvider.getCredential ( idToken, null );
    mAuth.signInWithCredential ( credential )
            .addOnCompleteListener ( this, task -> {
                if (task.isSuccessful ()) {
                    Toast.makeText ( this, "login success", Toast.LENGTH_SHORT ).show ();
                    FirebaseUser user = mAuth.getCurrentUser ();
                    checkFirebaseUser ( user );
                } else {
                    Toast.makeText ( this, "login failed", Toast.LENGTH_SHORT ).show ();
                }
            } );
}

Make sure you add the following dependencies in build.gradle for authentication to take place

implementation 'com.google.android.gms:play-services-auth:19.0.0'
implementation 'com.google.firebase:firebase-auth:20.0.3'

Enable Google authentication in your Firebase console

niranj1997
  • 719
  • 8
  • 16