Hi Please help me to resolve this issue I m getting this error message. The app crashes I have tried almost every solution suggested on Google
I am creating a Notes application for Android and the logic of the app when it starts is to check if there is a user created and logged in or not. if there is a user created then start MainActivity if there is no user created login with Anonymous account
package com.russrezepov.mynotes;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.widget.Toast;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.russrezepov.mynotes.auth.Login;
public class Splash extends AppCompatActivity {
private FirebaseAuth fAuth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
fAuth = FirebaseAuth.getInstance();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (fAuth.getCurrentUser() != null) {
startActivity(new Intent(getApplicationContext(), MainActivity.class));
finish();
} else {
//create a new Anonymous account if a User is not logged in or does not have an account
fAuth.signInAnonymously().addOnSuccessListener(new OnSuccessListener<AuthResult>() {
@Override
public void onSuccess(AuthResult authResult) {
Toast.makeText(Splash.this, "Logged in with Temp Account", Toast.LENGTH_SHORT).show();
startActivity(new Intent(getApplicationContext(),MainActivity.class));
finish();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(Splash.this, "Error" + e.getMessage(), Toast.LENGTH_SHORT).show();
startActivity(new Intent(getApplicationContext(), Login.class));
finish();
}
});
}
}
}, 1000);
}
}
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.russrezepov.mynotes, PID: 5158
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.russrezepov.mynotes/com.russrezepov.mynotes.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean com.google.firebase.auth.FirebaseUser.isAnonymous()' 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 'boolean com.google.firebase.auth.FirebaseUser.isAnonymous()' on a null object reference
at com.russrezepov.mynotes.MainActivity.onCreate(MainActivity.java:97)
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)
I/Process: Sending signal. PID: 5158 SIG: 9
Disconnected from the target VM, address: 'localhost:54989', transport: 'socket'
The Error message shows that if (user.isAnonymous())
is where the code below is stops
package com.russrezepov.mynotes;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.cardview.widget.CardView;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;
import com.firebase.ui.firestore.FirestoreRecyclerAdapter;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.navigation.NavigationView;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.Query;
import com.russrezepov.mynotes.auth.Login;
import com.russrezepov.mynotes.auth.Register;
import com.russrezepov.mynotes.model.Note;
import com.russrezepov.mynotes.note.AddNote;
import com.russrezepov.mynotes.note.EditNote;
import com.russrezepov.mynotes.note.TheNoteDetails;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
DrawerLayout drawerLayout;
ActionBarDrawerToggle toggle;
NavigationView nav_view;
RecyclerView noteList;
FloatingActionButton fab;
FirebaseUser user;
FirebaseAuth fAuth;
private FirebaseFirestore fStore;
//private Adapter adapter;
//private NoteAdapter noteAdapter;
final static String TAG = "Firebase Not Reading";
final static String TAGF = "Firebase CONNECTED";
FirestoreRecyclerAdapter<Note,NoteViewHolder> noteAdapter;
//>>>ON CREATE <<<
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Log.i(TAGF,"onCreate");
drawerLayout = findViewById(R.id.drawer);
nav_view = findViewById(R.id.nav_view);
nav_view.setNavigationItemSelectedListener(this);
toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.open, R.string.close);
drawerLayout.addDrawerListener(toggle);
toggle.setDrawerIndicatorEnabled(true);
toggle.syncState();
noteList = findViewById(R.id.noteList);
fab = findViewById(R.id.addNoteFloat);
View headerView = nav_view.getHeaderView(0);
TextView userDisplayName = headerView.findViewById(R.id.userDisplayName);
TextView userDisplayEmail = headerView.findViewById(R.id.userDisplayEmail);
if (user.isAnonymous()) {
userDisplayName.setText("Temporary Account");
userDisplayEmail.setVisibility(View.GONE);
} else {
userDisplayEmail.setText(user.getEmail());
userDisplayName.setText(user.getDisplayName());
}
setUpRecyclerView();
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(view.getContext(), AddNote.class));
overridePendingTransition(R.anim.slide_up,R.anim.slide_down);
finish();
}
});
}
private void setUpRecyclerView() {
fStore = FirebaseFirestore.getInstance();
fAuth = FirebaseAuth.getInstance();
user = fAuth.getCurrentUser();
//query notes=>UID=>MyNotes=>user all notes
Query query = fStore.collection("notes").document(user.getUid()).collection("myNotes").orderBy("title",Query.Direction.DESCENDING);
//executing the query
FirestoreRecyclerOptions<Note> allNotes;
allNotes = new FirestoreRecyclerOptions.Builder<Note>()
.setQuery(query, Note.class)
.build();
// fStore.collection("notes")
// .get()
// .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
// @Override
// public void onComplete(@NonNull Task<QuerySnapshot> task) {
// if (task.isSuccessful()) {
// Log.i(TAGF,"Firebase Connected Successfully");
// for (QueryDocumentSnapshot document : Objects.requireNonNull(task.getResult())) {
// //titles.add(document.getString("title"));
// //content.add(document.getString("content"));
// Log.i(TAGF,document.getString("title"));
// Log.i(TAGF,document.getString("content"));
// Log.i(TAGF,"Firebase Connected Successfully");
// }
// } else {
// Log.w(TAG,"Error getting documents.", task.getException());
// }
// }
// });
noteAdapter = new FirestoreRecyclerAdapter<Note, NoteViewHolder> (allNotes) {
@RequiresApi(api = Build.VERSION_CODES.M)
protected void onBindViewHolder(@NonNull NoteViewHolder noteViewHolder, final int i, @NonNull final Note note) {
//Binding data from MainActivity, when Adapter object is created, to this View that we have here
noteViewHolder.noteTitle.setText(note.getTitle());
noteViewHolder.noteContent.setText(note.getContent());
final int colorCodes = getRandomColor();
noteViewHolder.mCardView.setBackgroundColor(noteViewHolder.view.getResources().getColor(colorCodes,null));
//getting each doc id to be able to update them in EditNote using i as a position in collections
final String docId = noteAdapter.getSnapshots().getSnapshot(i).getId();
noteViewHolder.view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//getting current context where we are starting the Activity and passing them to another activity
Intent i = new Intent(v.getContext(), TheNoteDetails.class);
//When someone clicks on the first item in the RecyclerView it is going to get the position as Zero -> Position
//passing the title and description to the NoteDetails
i.putExtra("title", note.getTitle());
i.putExtra("content", note.getContent());
i.putExtra("color", colorCodes);
i.putExtra("noteId",docId);
v.getContext().startActivity(i); //Not passing anything yet. Just getting current context and passing current context
}
});
//Adding menu Edit & Delete functionality for each Note in Main Activity
ImageView menuIcon = noteViewHolder.view.findViewById(R.id.menuIcon);
menuIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
final String docId = noteAdapter.getSnapshots().getSnapshot(i).getId();
PopupMenu popupMenu = new PopupMenu(v.getContext(),v);
popupMenu.setGravity(Gravity.END);
popupMenu.getMenu().add("Edit").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
Intent i = new Intent(v.getContext(), EditNote.class);
i.putExtra("title",note.getTitle());
i.putExtra("content",note.getContent());
i.putExtra("noteId",docId);
startActivity(i);
return false;
}
});
popupMenu.getMenu().add("Delete").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
DocumentReference docRef = fStore.collection("notes").document(user.getUid()).collection("myNotes").document(docId);
docRef.delete().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Toast.makeText(MainActivity.this, "Note Deleted", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(MainActivity.this, "Error Deleting Note", Toast.LENGTH_SHORT).show();
}
});
return false;
}
});
popupMenu.show();
}
});
}
@NonNull
@Override
public NoteViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.note_view_layout,parent, false);
return new NoteViewHolder(view);
}
};
//Staggered layout expands based on Context Size
noteList.setLayoutManager(new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL));
noteList.setAdapter(noteAdapter);
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
drawerLayout.closeDrawer(GravityCompat.START);
switch (item.getItemId()) {
case R.id.addNote:
startActivity(new Intent(this, AddNote.class));
overridePendingTransition(R.anim.slide_up,R.anim.slide_down);
break;
case R.id.sync:
// sending Anonymous users only to Sync Activity aka Register New Account
if (user.isAnonymous()) {
startActivity(new Intent(this, Login.class));
overridePendingTransition(R.anim.slide_up,R.anim.slide_down);
} else {
Toast.makeText(this, "You Are Already Connected", Toast.LENGTH_SHORT).show();
}
break;
case R.id.logout:
checkUser();
break;
default:
Toast.makeText(this, "Coming Soon!", Toast.LENGTH_SHORT).show();
}
return false;
}
private void checkUser() {
//Check if the user is real or Anonymous
if (user.isAnonymous()) {
displayAlert();
} else {
FirebaseAuth.getInstance().signOut();
startActivity(new Intent(getApplicationContext(), Splash.class));
overridePendingTransition(R.anim.slide_up,R.anim.slide_down);
}
}
private void displayAlert() {
AlertDialog.Builder warnignAlert = new AlertDialog.Builder(this)
.setTitle("Are you sure?")
.setMessage("you are logged in with Temp account. Logging out will delete all unsaved notes")
.setPositiveButton("Sync Note", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startActivity(new Intent(getApplicationContext(), Register.class));
finish();
}
}).setNegativeButton("Logout", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//TODO: delete all the notes created by the anonymous user
// fStore.collection("notes").document(user.getUid()).document()
// fStore.collection("notes").document(user.getUid())
// .delete()
// .addOnSuccessListener(new OnSuccessListener<Void>() {
// @Override
// public void onSuccess(Void aVoid) {
// Log.d(TAG, "Notes successfully deleted!");
// }
// })
// .addOnFailureListener(new OnFailureListener() {
// @Override
// public void onFailure(@NonNull Exception e) {
// Log.w(TAG, "Error deleting Notes", e);
// }
// });
//TODO: delete the anonymous user
user.delete().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
startActivity(new Intent(getApplicationContext(),Splash.class));
overridePendingTransition(R.anim.slide_up,R.anim.slide_down);
}
});
}
});
warnignAlert.show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.option_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == R.id.settings) {
Toast.makeText(this, "Settings Menu is Clicked!", Toast.LENGTH_SHORT).show();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
@Override
protected void onStart() {
super.onStart();
noteAdapter.startListening();
}
@Override
protected void onStop() {
super.onStop();
noteAdapter.stopListening();
}
public static class NoteViewHolder extends RecyclerView.ViewHolder {
TextView noteTitle, noteContent;
View view;
CardView mCardView;
private NoteViewHolder(@NonNull final View itemView) {
super(itemView);
noteTitle = itemView.findViewById(R.id.titles);
noteContent = itemView.findViewById(R.id.content);
mCardView = itemView.findViewById(R.id.noteCard);
view = itemView; //Handles clicks on Recycle View items. Clicks are redirected to the inside of a Note
}
}
private int getRandomColor() {
List<Integer> colorCode = new ArrayList<>();
colorCode.add(R.color.blue);
colorCode.add(R.color.yellow);
colorCode.add(R.color.skyBlue);
colorCode.add(R.color.lightPurple);
colorCode.add(R.color.lightGreen);
colorCode.add(R.color.greenlight);
colorCode.add(R.color.gray);
colorCode.add(R.color.pink);
colorCode.add(R.color.red);
colorCode.add(R.color.notgreen);
Random randomColor = new Random();
int numberColor = randomColor.nextInt(colorCode.size());
return colorCode.get(numberColor);
}
}
You are initializing the user object after accessing it. You are doing it in setUpRecyclerView
but accessing it before.
setUpRecyclerView();
if (user.isAnonymous()) {
userDisplayName.setText("Temporary Account");
userDisplayEmail.setVisibility(View.GONE);
} else {
userDisplayEmail.setText(user.getEmail());
userDisplayName.setText(user.getDisplayName());
}
This will make sure you have user object before using it.