androidlistviewfirebasefirebase-realtime-databasechatroom

App crashed when click into chat room


I was using the chat room from this link in my app.

https://gist.github.com/puf/f49a1b07e92952b44f2dc36d9af04e3c

My app flow:

Login -> MainActivity -> select a team from listview to join chat -> ChatRoomActivity

My problem is when i clicked on one of the team in my listview, it crashes. My code for the chatroom is exactly the same as the link, except i changed MainActivity to ChatRoomActivity and removed the login popup. The rest stays the same.Can someone help me correct it or identify the cause?

MainActivity:

public class MainActivity extends AppCompatActivity {
public static final String TEAM_NAME = "com.example.user.stfv2.teamname";
public static final String TEAM_ID = "com.example.user.stfv2.teamid";

private FirebaseAuth firebaseAuth;

EditText editTextName;
EditText textDate;
EditText textTime;
Spinner spinnerSport;
Button buttonAddTeam;
ListView listViewTeams;
DatePickerDialog datePickerDialog;

List<Team> teams;

DatabaseReference databaseTeams;

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

    firebaseAuth = FirebaseAuth.getInstance();

    if(firebaseAuth.getCurrentUser() == null){

        finish();

        startActivity(new Intent(this, SignInActivity.class));
    }

    FirebaseUser user = firebaseAuth.getCurrentUser();

    databaseTeams = FirebaseDatabase.getInstance().getReference("teams");

    editTextName = (EditText) findViewById(R.id.editTextName);
    spinnerSport = (Spinner) findViewById(R.id.spinnerSports);
    listViewTeams = (ListView) findViewById(R.id.listViewTeams);
    textDate = (EditText) findViewById(R.id.textDate);
    textTime = (EditText) findViewById(R.id.textTime);


    buttonAddTeam = (Button) findViewById(R.id.buttonAddTeam);

    teams = new ArrayList<>();

    buttonAddTeam.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent myIntent = new Intent(MainActivity.this,
                    AddActivity.class);
            startActivity(myIntent);
        }
    });


    listViewTeams.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {

            Team team = teams.get(i);


            Intent intent = new Intent(getApplicationContext(), ChatRoomActivity.class);

            intent.putExtra(TEAM_ID, team.getTeamId());
            intent.putExtra(TEAM_NAME, team.getTeamName());

            startActivity(intent);
        }
    });

    listViewTeams.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
            Team team = teams.get(i);
            showUpdateDeleteDialog(team.getTeamId(), team.getTeamName());
            return true;
        }
    });

}

private void showUpdateDeleteDialog(final String teamId, String teamName) {

    AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
    LayoutInflater inflater = getLayoutInflater();
    final View dialogView = inflater.inflate(R.layout.update_dialog, null);
    dialogBuilder.setView(dialogView);

    final EditText editTextName = (EditText) dialogView.findViewById(R.id.editTextName);
    final Spinner spinnerSport = (Spinner) dialogView.findViewById(R.id.spinnerSports);
    final Button buttonUpdate = (Button) dialogView.findViewById(R.id.buttonUpdateTeam);
    final Button buttonDelete = (Button) dialogView.findViewById(R.id.buttonDeleteTeam);
    final EditText textDate = (EditText) dialogView.findViewById(R.id.textDate);
    final EditText textTime = (EditText) dialogView.findViewById(R.id.textTime);

    dialogBuilder.setTitle(teamName);
    final AlertDialog b = dialogBuilder.create();
    b.show();

    textDate.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            final Calendar c = Calendar.getInstance();
            int mYear = c.get(Calendar.YEAR); 
            int mMonth = c.get(Calendar.MONTH); 
            int mDay = c.get(Calendar.DAY_OF_MONTH); 

            datePickerDialog = new DatePickerDialog(MainActivity.this,
                    new DatePickerDialog.OnDateSetListener() {

                        @Override
                        public void onDateSet(DatePicker view, int year,
                                              int monthOfYear, int dayOfMonth) {

                            textDate.setText(dayOfMonth + "/"
                                    + (monthOfYear + 1) + "/" + year);

                        }
                    }, mYear, mMonth, mDay);
            datePickerDialog.show();
        }
    });

    textTime.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Calendar mcurrentTime = Calendar.getInstance();
            int hour = mcurrentTime.get(Calendar.HOUR_OF_DAY);
            int minute = mcurrentTime.get(Calendar.MINUTE);
            TimePickerDialog mTimePicker;
            mTimePicker = new TimePickerDialog(MainActivity.this, new TimePickerDialog.OnTimeSetListener() {
                @Override
                public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) {
                    textTime.setText(selectedHour + ":" + selectedMinute);
                }
            }, hour, minute, true);
            mTimePicker.setTitle("Select Time");
            mTimePicker.show();

        }
    });


    buttonUpdate.setOnClickListener(new View.OnClickListener() {

        FirebaseUser user = firebaseAuth.getCurrentUser();

        @Override
        public void onClick(View view) {
            String name = editTextName.getText().toString().trim();
            String sport = spinnerSport.getSelectedItem().toString();
            String owner = user.getUid();
            String date = textDate.getText().toString();
            String time = textTime.getText().toString();
            if (!TextUtils.isEmpty(name)) {
                updateTeam(teamId, name, sport, owner, date, time);
                b.dismiss();
            }
        }
    });


    buttonDelete.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            deleteTeam(teamId);
            b.dismiss();
        }
    });
}

private boolean updateTeam(String id, String name, String sport, String owner, String date, String time) {

    DatabaseReference dR = FirebaseDatabase.getInstance().getReference("teams").child(id);

    Team team = new Team(id, name, sport, owner, date, time);
    dR.setValue(team);
    Toast.makeText(getApplicationContext(), "Team Updated", Toast.LENGTH_LONG).show();
    return true;
}

private boolean deleteTeam(String id) {

    DatabaseReference dR = FirebaseDatabase.getInstance().getReference("teams").child(id);


    dR.removeValue();


    DatabaseReference drTracks = FirebaseDatabase.getInstance().getReference("tracks").child(id);

    drTracks.removeValue();
    Toast.makeText(getApplicationContext(), "Team Deleted", Toast.LENGTH_LONG).show();

    return true;
}

@Override
protected void onStart() {
    super.onStart();

    databaseTeams.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {


            teams.clear();


            for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {

                Team team = postSnapshot.getValue(Team.class);

                teams.add(team);
            }

            TeamList teamAdapter = new TeamList(MainActivity.this, teams);

            listViewTeams.setAdapter(teamAdapter);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
}

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {
        case R.id.action_logout:

            firebaseAuth.signOut();

            finish();

            startActivity(new Intent(this, SignInActivity.class));
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}
}

Logcat:

03-19 01:40:25.709 2995-2995/? E/AndroidRuntime: FATAL EXCEPTION: main
                                             Process: com.example.user.stfv2, PID: 2995
                                             java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.user.stfv2/com.example.user.stfv2.ChatRoomActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
                                                 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
                                                 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
                                                 at android.app.ActivityThread.-wrap11(ActivityThread.java)
                                                 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
                                                 at android.os.Handler.dispatchMessage(Handler.java:102)
                                                 at android.os.Looper.loop(Looper.java:148)
                                                 at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                              Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
                                                 at com.example.user.stfv2.ChatRoomActivity.setUsername(ChatRoomActivity.java:58)
                                                 at com.example.user.stfv2.ChatRoomActivity.onCreate(ChatRoomActivity.java:73)
                                                 at android.app.Activity.performCreate(Activity.java:6237)
                                                 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
                                                 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
                                                 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
                                                 at android.app.ActivityThread.-wrap11(ActivityThread.java) 
                                                 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
                                                 at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                 at android.os.Looper.loop(Looper.java:148) 
                                                 at android.app.ActivityThread.main(ActivityThread.java:5417) 
                                                 at java.lang.reflect.Method.invoke(Native Method) 
                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

Edit 1:

layout_chat_room:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.user.stfv2.MainActivity">

<RelativeLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/header"
    android:gravity="end">

    <ImageView
        android:layout_width="36dp"
        android:layout_height="36dp"
        android:id="@+id/userIcon"
        android:foregroundGravity="center"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true" />

    <TextView
        android:layout_width="141dp"
        android:layout_height="wrap_content"
        android:id="@+id/usernameTxt"
        android:layout_toRightOf="@+id/userIcon"
        android:layout_alignTop="@+id/userIcon"
        android:layout_alignBottom="@+id/userIcon"
        android:gravity="center_vertical"
        tools:text="Username"
        android:layout_weight="0" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Sign in"
        android:id="@+id/loginBtn"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Sign out"
        android:id="@+id/logoutBtn"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true" />
</RelativeLayout>

<android.support.v7.widget.RecyclerView
    android:id="@+id/messagesList"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    tools:listitem="@android:layout/two_line_list_item"
    android:layout_above="@+id/footer"
    android:layout_below="@+id/header" />

<LinearLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:id="@+id/footer">

    <ImageButton
        android:layout_width="36dp"
        android:layout_height="36dp"
        android:id="@+id/imageBtn"
        android:background="@android:drawable/ic_menu_gallery" />

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/messageTxt"
        android:layout_gravity="bottom"
        android:layout_weight="1"
        android:inputType="textShortMessage|textAutoCorrect" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send"
        android:id="@+id/sendBtn"
        android:layout_gravity="bottom" />
</LinearLayout>
</RelativeLayout>

ChatRoomActivity:

public class ChatRoomActivity extends AppCompatActivity {
private static final String TAG = "ChatRoomActivity";

static final int RC_PHOTO_PICKER = 1;

private Button sendBtn;
private EditText messageTxt;
private RecyclerView messagesList;
private ChatMessageAdapter adapter;
private ImageButton imageBtn;
private TextView usernameTxt;
private View loginBtn;
private View logoutBtn;

private FirebaseApp app;
private FirebaseDatabase database;
private FirebaseAuth auth;
private FirebaseStorage storage;

private DatabaseReference databaseRef;
private StorageReference storageRef;

private String username;

private void setUsername(String username) {
    Log.d(TAG, "setUsername("+String.valueOf(username)+")");
    if (username == null) {
        username = "Android";
    }
    boolean isLoggedIn = !username.equals("Android");
    this.username = username;
    this.usernameTxt.setText(username);
    this.logoutBtn.setVisibility(isLoggedIn ? View.VISIBLE : View.GONE);
    this.loginBtn .setVisibility(isLoggedIn ? View.GONE    : View.VISIBLE);
}

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

    sendBtn = (Button) findViewById(R.id.sendBtn);
    messageTxt = (EditText) findViewById(R.id.messageTxt);
    messagesList = (RecyclerView) findViewById(R.id.messagesList);
    imageBtn = (ImageButton) findViewById(R.id.imageBtn);
    loginBtn = findViewById(R.id.loginBtn);
    logoutBtn = findViewById(R.id.logoutBtn);
    usernameTxt = (TextView) findViewById(R.id.usernameTxt);
    setUsername("Android");

    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    messagesList.setHasFixedSize(false);
    messagesList.setLayoutManager(layoutManager);

    // Show an image picker when the user wants to upload an imasge
    imageBtn.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("image/jpeg");
            intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
            startActivityForResult(Intent.createChooser(intent, "Complete action using"), RC_PHOTO_PICKER);
        }
    });
    // Show a popup when the user asks to sign in
    loginBtn.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            LoginDialog.showLoginPrompt(ChatRoomActivity.this, app);
        }
    });
    // Allow the user to sign out
    logoutBtn.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            auth.signOut();
        }
    });

    adapter = new ChatMessageAdapter(this);
    messagesList.setAdapter(adapter);
    adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
        public void onItemRangeInserted(int positionStart, int itemCount) {
            messagesList.smoothScrollToPosition(adapter.getItemCount());
        }
    });

    // Get the Firebase app and all primitives we'll use
    app = FirebaseApp.getInstance();
    database = FirebaseDatabase.getInstance(app);
    auth = FirebaseAuth.getInstance(app);
    storage = FirebaseStorage.getInstance(app);

    // Get a reference to our chat "room" in the database
    databaseRef = database.getReference("chat");

    sendBtn.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            ChatMessage chat = new ChatMessage(username, messageTxt.getText().toString());
            // Push the chat message to the database
            databaseRef.push().setValue(chat);
            messageTxt.setText("");
        }
    });
    // Listen for when child nodes get added to the collection
    databaseRef.addChildEventListener(new ChildEventListener() {
        public void onChildAdded(DataSnapshot snapshot, String s) {
            // Get the chat message from the snapshot and add it to the UI
            ChatMessage chat = snapshot.getValue(ChatMessage.class);
            adapter.addMessage(chat);
        }

        public void onChildChanged(DataSnapshot dataSnapshot, String s) { }
        public void onChildRemoved(DataSnapshot dataSnapshot) { }
        public void onChildMoved(DataSnapshot dataSnapshot, String s) { }
        public void onCancelled(DatabaseError databaseError) { }
    });

    // When the user has entered credentials in the login dialog
    LoginDialog.onCredentials(new OnSuccessListener<LoginDialog.EmailPasswordResult>() {
        public void onSuccess(LoginDialog.EmailPasswordResult result) {
            // Sign the user in with the email address and password they entered
            auth.signInWithEmailAndPassword(result.email, result.password);
        }
    });

    // When the user signs in or out, update the username we keep for them
    auth.addAuthStateListener(new FirebaseAuth.AuthStateListener() {
        public void onAuthStateChanged(FirebaseAuth firebaseAuth) {
            if (firebaseAuth.getCurrentUser() != null) {
                // User signed in, set their email address as the user name
                setUsername(firebaseAuth.getCurrentUser().getEmail());
            }
            else {
                // User signed out, set a default username
                setUsername("Android");
            }
        }
    });
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == RC_PHOTO_PICKER && resultCode == RESULT_OK) {
        Uri selectedImageUri = data.getData();

        // Get a reference to the location where we'll store our photos
        storageRef = storage.getReference("chat_photos");
        // Get a reference to store file at chat_photos/<FILENAME>
        final StorageReference photoRef = storageRef.child(selectedImageUri.getLastPathSegment());

        // Upload file to Firebase Storage
        photoRef.putFile(selectedImageUri)
                .addOnSuccessListener(this, new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        // When the image has successfully uploaded, we get its download URL
                        Uri downloadUrl = taskSnapshot.getDownloadUrl();
                        // Set the download URL to the message box, so that the user can send it to the database
                        messageTxt.setText(downloadUrl.toString());
                    }
                });
    }
}
}

Solution

  • Your problem is that you are defining the wrong XML file. When you used the code from ChatroomActivity, you forgot to change the XML file. It is currently set to setContentView(R.layout.activity_main), but it should be setContentView(R.layout.layout_chat_room).