0

I'm doing a realtime tracking application from a tutorial online, Here i'm setting the presence system using firebase. But it's crashing with:

/java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Boolean.booleanValue()' on a null object reference

I don't understand what's wrong the guy who coded this has it working perfectly.

The exception is happening at this line :if(dataSnapshot.getValue(Boolean.class)){

When i log this on screen the datasnapshot object has a key but no value

HELP!

ListOnline Class

//firebase
DatabaseReference onlineRef,currentUserRef,counterRef;
FirebaseRecyclerAdapter<User,ListOnlineViewHolder> adapter;

//View
RecyclerView listOnline;
RecyclerView.LayoutManager layoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list_online);

    //setting the recyclerview
    listOnline = (RecyclerView)findViewById(R.id.listOnlineRecyclerview);
    listOnline.setHasFixedSize(true);
    layoutManager = new LinearLayoutManager(this);
    listOnline.setLayoutManager(layoutManager);

    //set toolbar and menu / join,logout
    Toolbar toolbar = (Toolbar)findViewById(R.id.toolbarID);
    toolbar.setTitle("Presence System");
    setSupportActionBar(toolbar);

    //firebase
    onlineRef = FirebaseDatabase.getInstance().getReference().child("info/connected");
    counterRef = FirebaseDatabase.getInstance().getReference("lastOnline"); //create new child name lastOnline
    currentUserRef = FirebaseDatabase.getInstance().getReference().child(FirebaseAuth.getInstance().getCurrentUser().getUid());

    setupSystem();
    //after setup we load all users and display in recyclerview
    //this is online list
    updateList();
}

private void updateList() {
    adapter = new FirebaseRecyclerAdapter<User, ListOnlineViewHolder>(
            User.class,R.layout.user_layout,ListOnlineViewHolder.class,counterRef
    ) {
        @Override
        protected void populateViewHolder(ListOnlineViewHolder viewHolder, User model, int position) {
            viewHolder.emailTextView.setText(model.getEmail());
        }

    };
    adapter.notifyDataSetChanged();
    listOnline.setAdapter(adapter);
}

private void setupSystem() {
    onlineRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
                if(dataSnapshot.getValue(Boolean.class)){
                    currentUserRef.onDisconnect().removeValue();
                    //set online user in list
                    counterRef.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
                            .setValue(FirebaseAuth.getInstance().getCurrentUser().getEmail(),"Online");
                    adapter.notifyDataSetChanged();
                }
            }



        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
    counterRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for(DataSnapshot postSnapshot:dataSnapshot.getChildren()){
                User user = postSnapshot.getValue(User.class);
                Log.d("LOG",""+user.getEmail()+"is "+user.getStatus());
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater menuInflater = getMenuInflater();
    menuInflater.inflate(R.menu.main_menu,menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()){
        case R.id.action_join:
            counterRef.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
                    .setValue(FirebaseAuth.getInstance().getCurrentUser().getEmail(),"Online");
            break;
        case R.id.action_logout:
            currentUserRef.removeValue();

    }
    return super.onOptionsItemSelected(item);
}

}

User Class

public class User {
private String email,status;


public User(String email, String status) {
    this.email = email;
    this.status = status;
}

public User() {

}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

public String getStatus() {
    return status;
}

public void setStatus(String status) {
    this.status = status;
}}

MainActivity

public class MainActivity extends AppCompatActivity {

Button signInButton;
private final static int LOGIN_PERMISSION = 1000;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    signInButton = (Button) findViewById(R.id.signInButton);
    signInButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            startActivityForResult(AuthUI.getInstance().createSignInIntentBuilder().setAllowNewEmailAccounts(true).build(),LOGIN_PERMISSION);

        }

    });
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if(requestCode == LOGIN_PERMISSION){
        startNewActivity(resultCode,data);
    }
}

private void startNewActivity(int resultcode, Intent data) {

    if(resultcode == RESULT_OK){
        Intent intent = new Intent(MainActivity.this,ListOnline.class);
        startActivity(intent);
        finish();

    }
    else{
        Toast.makeText(this,"login failed!!",Toast.LENGTH_SHORT).show();
    }
}}
Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Akay
  • 53
  • 2
  • 9

3 Answers3

0

its null since it does not exist in the database..

 onlineRef = FirebaseDatabase.getInstance().getReference().child("info/connected");

you are querying on the above location. So dataSnapshot is a snapshot of the above..

if(dataSnapshot.getValue(Boolean.class)){

This does not exist in the database.. Thus you get that error

Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
0

It seems that you do not have a value in database. This will handle the error

if(dataSnapshot.getValue(Boolean.class) != null && dataSnapshot.getValue(Boolean.class)){
npk
  • 1,512
  • 1
  • 13
  • 26
0

In your setupSystem() method, you are attaching a listener to onlineRef (the info/connected node) and then marshalling the returned value to a Boolean value.

However, DataSnapshot#getValue() will return null if there is no data at the specified location in the database. If this happens, the dataSnapshot.getValue(Boolean.class) call will create a Boolean variable with the value of null, which then cannot be checked for a true value in your current if statement (see Check if null Boolean is true results in exception).

You could check that getValue() does not return null first by adding a null-check to your if statement:

if(dataSnapshot.getValue() != null && dataSnapshot.getValue(Boolean.class)){
    // ...
}

Or check that the location exists using DataSnapshot#exists():

if(dataSnapshot.exists() && dataSnapshot.getValue(Boolean.class)){
    // ...
}

However, if you're trying to detect connection state, did you mean to attach the listener to the .info/connected node instead? As from the documentation:

For many presence-related features, it is useful for your app to know when it is online or offline. Firebase Realtime Database provides a special location at /.info/connected which is updated every time the Firebase Realtime Database client's connection state changes. Here is an example:

DatabaseReference connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected");
connectedRef.addValueEventListener(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot snapshot) {
    boolean connected = snapshot.getValue(Boolean.class);
    if (connected) {
      System.out.println("connected");
    } else {
      System.out.println("not connected");
    }
  }

  @Override
  public void onCancelled(DatabaseError error) {
    System.err.println("Listener was cancelled");
  }
});
Grimthorr
  • 6,856
  • 5
  • 41
  • 53
  • I fixed it it was a small "." missing from the info/connected line i have a new crash though – Akay Oct 29 '17 at 14:00
  • com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String on : User user = postSnapshot.getValue(User.class); – Akay Oct 29 '17 at 14:00
  • This would be from the `/lastOnline` location which you're trying to marshal to a `User` instance. Can you share your database structure? It's likely that the value(s) at this location don't match your `User` class. – Grimthorr Oct 29 '17 at 20:12
  • Im a noob in firebase how can i share my structure ? :| – Akay Oct 30 '17 at 09:37
  • @Akay The quickest way would be to take a screenshot from the Firebase Console & edit it into your question. Also, as your question has changed from the original, it might be worth accepting an answer here (tick under the upvote buttons) & posting this as a new question to attract more attention & answers. – Grimthorr Oct 30 '17 at 09:47
  • Okay i've edited my post and accepted your answer, you can check the images now. – Akay Oct 30 '17 at 09:54
  • @Akay Ok, thanks. You can try changing the `User user = postSnapshot.getValue(User.class);` line to: `String userEmail = postSnapshot.getValue(String.class);` which will give you the only value available at the `/lastOnline/$id` location. If you need to store/retrieve a `User` object, you'll need to take a look at [using custom Java objects with Firebase](https://firebase.google.com/docs/database/android/read-and-write#basic_write). If you have any further issues or questions, I'd suggest creating a new question. – Grimthorr Oct 30 '17 at 10:18
  • The thing is i was using this tutorial mentioned above in the question to learn about presence system and the guy runs this code and it works perfectly, i don't get what i'm missing, is it something in my database, im still new to this. But anyway thank you for the help i'll look deeper into firebase and try to understand this before asking next time – Akay Oct 30 '17 at 10:50
  • @Akay Ok, no problem. I think you're right: it's likely a difference between your database structure and the structure that the tutorial is using. Let me know if you do post another question & I'll see if I can help out. – Grimthorr Oct 30 '17 at 10:51