This is my Service class which is calling to all listener
public class DBService extends Service {
private static final String TAG = DBService.class.getName();
private DatabaseReference reference;
private static final String FIREBASE_EMAIL = "xxxxxxx#workindia.in";
private static final String FIREBASE_PASSWORD = "xxxxxx";
#Override
public void onCreate() {
super.onCreate();
FirebaseDatabase database = FirebaseDatabase.getInstance();
reference = database.getReference();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
FirebaseAuth auth = ((StartApplication) getApplication()).getAuth();
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user == null) {
String email = ObjectGraph.getEmployeeProfile().getEmail();
String password = ObjectGraph.getEmployeeProfile().getMobile_no();
if (password != null && !password.trim().isEmpty()) {
if (email == null || email.trim().isEmpty()) {
email = password + FIREBASE_EMAIL;
}
signIn(auth, email, FIREBASE_PASSWORD);
}
} else {
addListeners();
}
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
addListeners();
return null;
}
private void signIn(final FirebaseAuth auth, final String email, final String password) {
Log.i(TAG, "Login");
auth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
boolean isResetTimeStamp = true;
setTimeStamp(isResetTimeStamp);
addListeners();
} else {
register(auth, email, password);
}
}
});
FirebaseAuth.AuthStateListener authListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
Log.e(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
Log.e(TAG, "onAuthStateChanged:signed_out");
}
}
};
auth.addAuthStateListener(authListener);
}
private void addListeners() {
EmployeeProfile profile = ObjectGraph.getEmployeeProfile();
if (profile != null && profile.getMobile_no() != null && !profile.getMobile_no().trim().isEmpty()) {
reference.child(AppConstants.WORKINDIA_USERS_LAST_TIME).child(profile.getMobile_no().trim()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String, Object> child = (Map<String, Object>) dataSnapshot.getValue();
Log.e(TAG, "DATA " + child);
if (child == null) {
/*Query Listener Other listener*/
Query recentPostsQuery = reference.child(AppConstants.WORKINDIA_JOB_NODE).limitToFirst(1000);//.orderByChild("timestamp");
recentPostsQuery.addValueEventListener(jobBulKDownloadListener);
} else {
long lastSyncTime = (Long) child.get(AppConstants.TIMESTAMP);
Log.e(TAG, "DATA " + lastSyncTime);
/*Query Listener Other listener*/
Query recentPostsQuery = reference.child(AppConstants.WORKINDIA_JOB_NODE)
.orderByChild(AppConstants.TIMESTAMP)
.startAt(lastSyncTime)
.limitToFirst(1000);//.orderByChild("timestamp");
recentPostsQuery.addValueEventListener(jobBulKDownloadListener);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, databaseError.getMessage(), databaseError.toException());
}
});
}
}
private void register(final FirebaseAuth auth, final String email, final String password) {
Log.e(TAG, "register");
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Log.e(TAG, "register true");
signIn(auth, email, password);
} else {
Log.e(TAG, "register fail");
}
}
});
}
ValueEventListener jobBulKDownloadListener = new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot) {
Toast.makeText(getApplicationContext(), "jobBulKDownloadListener+ onDataChange", Toast.LENGTH_SHORT).show();
new Thread(new Runnable() {
#Override
public void run() {
try {
if (dataSnapshot != null) {
long time = System.currentTimeMillis();
Log.d(TAG, "Start Process : " + (System.currentTimeMillis() - time) / 1000 + " Seconds");
List<Job> jobs = new ArrayList<Job>();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
WrapperJob job1 = snapshot.getValue(WrapperJob.class);
Job job = job1.getData();
jobs.add(job);
}
if (jobs.size() > 0) {
parseJobs(jobs);
}
Log.d(TAG, "After Process : " + (System.currentTimeMillis() - time) / 1000 + " Seconds");
}
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
Crashlytics.logException(e);
}
}
}).start();
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, databaseError.getMessage(), databaseError.toException());
}
};
private void parseJobs(List<Job> jobs) {
/* Job Operations*/
}
}
Why it is getting hanged ?? I have kept almost everything on background thread
This may not be the problem, but in your jobBulKDownloadListener it's probably safer to operate on the DataSnapshot on the main thread instead of your worker thread. You could refactor it like this:
ValueEventListener jobBulKDownloadListener = new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot) {
Toast.makeText(getApplicationContext(), "jobBulKDownloadListener+ onDataChange", Toast.LENGTH_SHORT).show();
if (dataSnapshot != null) {
final List<Job> jobs = new ArrayList<Job>();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
WrapperJob job1 = snapshot.getValue(WrapperJob.class);
Job job = job1.getData();
jobs.add(job);
}
if (jobs.size() > 0) {
new Thread(new Runnable() {
#Override
public void run() {
try {
long time = System.currentTimeMillis();
Log.d(TAG, "Start Process : " + (System.currentTimeMillis() - time) / 1000 + " Seconds");
parseJobs(jobs);
Log.d(TAG, "After Process : " + (System.currentTimeMillis() - time) / 1000 + " Seconds");
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
Crashlytics.logException(e);
}
}
}).start();
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, databaseError.getMessage(), databaseError.toException());
}
};
Related
This is the JSON text
{
"User" : {
"E10W6iRbAUOa5XbFnedUuepswsw2" : {
"email" : "jay#gmail,com",
"type" : "Admin"
},
"Od6G6kbPHrScLVYrqmovaFP0gw03" : {
"email" : "gloria#yahoo,com",
"type" : "User"
},
"jCiHZCIThdQi1LhVSonN6UNxRok2" : {
"email" : "clara#yahoo,com",
"type" : "User"
}
}
}
on if (login.getType().equals("Admin") && login.getType() != null)
or if there are any other errors please let me know
public class SignInActivity extends AppCompatActivity {
private EditText memail;
private EditText mpassword;
private Button mlogin;
private Button mregister;
private ProgressBar mpgbar;
private FirebaseAuth mAuth;
FirebaseDatabase database;
DatabaseReference users;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_in);
database = FirebaseDatabase.getInstance();
users = database.getReference("User");
mAuth = FirebaseAuth.getInstance();
memail = findViewById(R.id.emailtv);
mpassword = findViewById(R.id.passwordtv);
mlogin = findViewById(R.id.loginBtn);
mregister = findViewById(R.id.regBtn);
mpgbar = findViewById(R.id.progressBar);
mregister.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(SignInActivity.this, RegisterActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
return;
}
});
mlogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LoginUser(memail.getText().toString(), mpassword.getText().toString());
}
});
}
private void inProgress(boolean x) {
if (x) {
mpgbar.setVisibility(View.VISIBLE);
mlogin.setEnabled(false);
mregister.setEnabled(false);
} else {
mpgbar.setVisibility(View.GONE);
mlogin.setEnabled(true);
mregister.setEnabled(true);
}
}
private boolean isEmpty() {
if (TextUtils.isEmpty(memail.getText().toString())) {
memail.setError("REQUIRED");
return true;
}
if (TextUtils.isEmpty(mpassword.getText().toString())) {
mpassword.setError("REQUIRED");
return true;
}
return false;
}
private void LoginUser(final String email, final String pwd) {
if (isEmpty()) return;
inProgress(true);
users.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (!email.isEmpty()) {
User login = dataSnapshot.child(email).getValue(User.class);
if (login.getType().equals("Admin") && login.getType() != null) {
mAuth.signInWithEmailAndPassword(email.replace(",","."), pwd)
.addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
Toast.makeText(SignInActivity.this, "User signed in", Toast.LENGTH_LONG).show();
Intent intent = new Intent(SignInActivity.this, AdminPage.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
return;
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(SignInActivity.this, "Sign in failed" + e.getMessage(), Toast.LENGTH_LONG).show();
}
});
} else if (login.getType().equals("User") && login.getType() != null) {
if (isEmpty()) return;
inProgress(true);
mAuth.signInWithEmailAndPassword(email.replace(",","."), pwd)
.addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
Toast.makeText(SignInActivity.this, "User signed in", Toast.LENGTH_LONG).show();
Intent intent = new Intent(SignInActivity.this, Home.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
return;
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(SignInActivity.this, "Sign in failed" + e.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
else
{
Toast.makeText(SignInActivity.this, "Sign in failed" , Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
It supposed to redirect user to home and admin to admin page. But it always crash.
You're loading the entire /User node, and then try to read a single User.class from it. That won't work, as /User contains multiple users. But you'll also first want to query the children under /User to only read users with the email address you're looking for.
Something like this:
private void LoginUser(final String email, final String pwd) {
Query query = users.orderByChild("email").equalTo(email)
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot userSnapshot: dataSnapshot.getChildren()) {
User login = userSnapshot.getValue(User.class);
...
}
}
}
});
}
The main differences:
Instead of loading all users, this queries the children under /User for the one(s) matching the email address.
Inside onDataChange there may be multiple matching child nodes, so we loop over those results.
Removed the child("email") inside the onDataChange, since that doesn't work if you're trying to read an entire User object.
I'm having an issue with FireStore offline persistence when getting information from a single document.
The below method of filling form works fine when online, but I'm seeing a long delay (filling data into a simple EditText form) when I test the app offline (sometimes three or four seconds):
private void importFirestoreData() {
dbDocument = dbFirestore.collection("sites").document(siteId);
dbDocument.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
Log.d(TAG, "DocumentSnapshot data: " + document.getData());
companyNameEditText.setText(document.getString("companyName"));
siteLocationEditText.setText(document.getString("siteLocation"));
siteAddressEditText.setText(document.getString("siteAddress"));
companyWebsiteEditText.setText(document.getString("companyWebsite"));
} else {
Log.d(TAG, "No such document");
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
}
});
}
The rest of the code is here:
public class SiteAddEditActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "SiteAddEditActivity";
public static final String KEY_SITE_ID = "key_site_id";
private TextView mainTitleTextView;
private EditText companyNameEditText, siteLocationEditText, siteAddressEditText, companyWebsiteEditText;
private Button saveButton, cancelButton;
private String siteId;
// Database declarations
private FirebaseAuth mAuth;
private FirebaseUser mUser;
private FirebaseFirestore dbFirestore;
private DocumentReference dbDocument;
private Query dbQuery;
private boolean newDoc;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
setContentView(R.layout.site_add_edit_activity);
setUpViews();
setUpListeners();
setUpFirestore();
getIDfromExtras();
}
private void setUpViews() {
mainTitleTextView = findViewById(R.id.textViewMainHeading);
companyNameEditText = findViewById(R.id.editTextCompanyName);
siteLocationEditText = findViewById(R.id.editTextSiteLocation);
siteAddressEditText = findViewById(R.id.editTextSiteAddress);
companyWebsiteEditText = findViewById(R.id.editTextCompanyWebsite);
saveButton = findViewById(R.id.buttonSave);
cancelButton = findViewById(R.id.buttonCancel);
}
private void setUpListeners() {
saveButton.setOnClickListener(this);
cancelButton.setOnClickListener(this);
}
private void setUpFirestore() {
mAuth = FirebaseAuth.getInstance();
mUser = mAuth.getCurrentUser();
dbFirestore = FirebaseFirestore.getInstance();
}
private void getIDfromExtras() {
newDoc = true;
// Get site ID from extras
siteId = getIntent().getExtras().getString(KEY_SITE_ID);
if (siteId == null) {
throw new IllegalArgumentException("Must pass extra " + KEY_SITE_ID);
}
else {
newDoc = false;
mainTitleTextView.setText(R.string.app_edit_site);
importFirestoreData();
}
}
private void importFirestoreData() {
dbDocument = dbFirestore.collection("sites").document(siteId);
dbDocument.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
Log.d(TAG, "DocumentSnapshot data: " + document.getData());
companyNameEditText.setText(document.getString("companyName"));
siteLocationEditText.setText(document.getString("siteLocation"));
siteAddressEditText.setText(document.getString("siteAddress"));
companyWebsiteEditText.setText(document.getString("companyWebsite"));
} else {
Log.d(TAG, "No such document");
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
}
});
}
#Override
public void onClick(View view) {
int i = view.getId();
if(i == R.id.buttonSave){
if (newDoc){
saveSite();
}
else {
updateSite();
}
startActivity(new Intent(SiteAddEditActivity.this, SiteActivity.class));
} else if (i == R.id.buttonCancel) {
FirebaseAuth mAuth = FirebaseAuth.getInstance();
Toast.makeText(this, "User (" + mAuth.getUid() + ") Signed Out!", Toast.LENGTH_LONG).show();
mAuth.signOut();
startActivity(new Intent(SiteAddEditActivity.this,LoginMainActivity.class));
}
}
private void updateSite() {
SitePOJO updateSite = new SitePOJO(
companyNameEditText.getText().toString().trim(),
siteLocationEditText.getText().toString().trim(),
siteAddressEditText.getText().toString(),
companyWebsiteEditText.getText().toString().trim()
);
dbDocument.set(updateSite);
}
private void saveSite() {
SitePOJO newSite = new SitePOJO(
companyNameEditText.getText().toString().trim(),
siteLocationEditText.getText().toString().trim(),
siteAddressEditText.getText().toString(),
companyWebsiteEditText.getText().toString().trim()
);
dbDocument = dbFirestore.collection("sites").document();
String thisDoc = dbDocument.getId();
dbDocument.set(newSite);
Toast.makeText(this, "New site created (document ref: " + thisDoc + ")", Toast.LENGTH_LONG).show();
}
}
I'm guessing it is how I am getting the data - I'm wondering if it is better to handle the data in some sort of adapter (separate to the activities?)..
Thank you to Reaz - yes this post did help..
My simple mind got confused between.get().addOnCompleteListener and .addSnapshotListener..
Correct working code below:
private void importFirestoreData() {
dbDocument = dbFirestore.collection("sites").document(siteId);
dbDocument.addSnapshotListener(new EventListener<DocumentSnapshot>() {
#Override
public void onEvent(#javax.annotation.Nullable DocumentSnapshot documentSnapshot, #javax.annotation.Nullable FirebaseFirestoreException e) {
if (e != null) {
Log.w(TAG, "Listen failed.", e);
return;
}
if (documentSnapshot != null && documentSnapshot.exists()) {
Log.d(TAG, "Current data: " + documentSnapshot.getData());
companyNameEditText.setText(documentSnapshot.getString("companyName"));
siteLocationEditText.setText(documentSnapshot.getString("siteLocation"));
siteAddressEditText.setText(documentSnapshot.getString("siteAddress"));
companyWebsiteEditText.setText(documentSnapshot.getString("companyWebsite"));
} else {
Log.d(TAG, "Current data: null");
}
}
});
}
I'm signing up users using Email/Password and Phone methods.
Signing up procedure is as follows
Sign in user with PhoneAuthCredential > Link created user with EmailCredential from entered email and password > send Email verification > Database entry
public class Sign_Up_page extends AppCompatActivity {
private String TAG = "Sign_Up_page";
// UI Widgets.
private View sign_up_btn;
// Firebase
private FirebaseAuth firebaseAuth;
private DatabaseReference reference;
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
private PhoneAuthProvider.ForceResendingToken mResendToken;
private FirebaseAuth.AuthStateListener authListener;
private UserPojo userPojo;
private String mVerificationId = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign__up_page);
firebaseAuth = FirebaseAuth.getInstance();
authListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() == null) {
Toast.makeText(Sign_Up_page.this, "user is null", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(Sign_Up_page.this, "user not null", Toast.LENGTH_LONG).show();
}
}
};
mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
#Override
public void onVerificationCompleted(PhoneAuthCredential credential) {
signInWithPhoneAuthCredential(credential);
}
#Override
public void onVerificationFailed(FirebaseException e) {
}
#Override
public void onCodeSent(String verificationId,
PhoneAuthProvider.ForceResendingToken token) {
mResendToken = token;
}
};
}
#Override
public void onClick(View v) {
super.onClick(v);
if (v == sign_up_btn) {
firebaseAuth.fetchSignInMethodsForEmail(userEmail).addOnCompleteListener(new OnCompleteListener<SignInMethodQueryResult>() {
#Override
public void onComplete(#NonNull Task<SignInMethodQueryResult> task) {
if (task.isSuccessful()) {
SignInMethodQueryResult result = task.getResult();
List<String> signInMethods = result != null ? result.getSignInMethods() : null;
if (signInMethods != null && signInMethods.size() == 0) {
startPhoneNumberVerification(userPhone);
verifyPhoneDialog();
}
}
}
});
}
}
private void signInWithPhoneAuthCredential(final PhoneAuthCredential credential) {
firebaseAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
if (task.getResult() != null) {
if (task.getResult().getAdditionalUserInfo().isNewUser()) {
AuthCredential emailCredential = EmailAuthProvider.getCredential(userEmail, userPass);
Toast.makeText(Sign_Up_page.this, "Signedin with phone", Toast.LENGTH_LONG).show();
linkUserCredentials(emailCredential);
} else {
firebaseAuth.signOut();
Toast.makeText(THIS, "This Phone no. is already registered with different account", Toast.LENGTH_SHORT).show();
}
}
}
}
});
}
private void linkUserCredentials(final AuthCredential credential) {
firebaseAuth.getCurrentUser().linkWithCredential(credential)
.addOnCompleteListener(Sign_Up_page.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
if (task.getResult() != null) {
FirebaseUser user = task.getResult().getUser();
Toast.makeText(Sign_Up_page.this, "credential linked", Toast.LENGTH_LONG).show();
// null current user was causing the account to create in Firebase Auth
// but no entry in Database so here I'm using user instance returned on
// linkCredentialSuccess for furthur use instead of "firebaseAuth.getCurrentUser()" to prevent that issue
sendVerificationEmail(user);
}
} else {
firebaseAuth.getCurrentUser().delete();
}
}
});
}
private void sendVerificationEmail(final FirebaseUser createdUser) {
if (firebaseAuth.getCurrentUser() != null) {
firebaseAuth.getCurrentUser().sendEmailVerification()
.addOnCompleteListener(this, new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Toast.makeText(Sign_Up_page.this, "email verification Op complete", Toast.LENGTH_LONG).show();
createUser(emailDelivery, createdUser);
}
});
}
}
private void createUser(final boolean emailDelivery, final FirebaseUser createdUser) {
reference = FirebaseDatabase.getInstance().getReference("users");
Toast.makeText(Sign_Up_page.this, "Creating user", Toast.LENGTH_LONG).show();
userPojo = new UserPojo();
userPojo.setValues(...);
String uid = "";
if (createdUser != null) {
uid = createdUser.getUid();
}
if (firebaseAuth.getCurrentUser() == null) {
AuthCredential emailCredential = EmailAuthProvider.getCredential(userEmail, userPass);
if (createdUser != null) {
createdUser.reauthenticate(emailCredential).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(Sign_Up_page.this, "user reAuthenticated", Toast.LENGTH_LONG).show();
}
}
});
}
}
if (!uid.equals("")) {
UserProfileChangeRequest userProfile = new UserProfileChangeRequest.Builder()
.setDisplayName(userName).build();
createdUser.updateProfile(userProfile);
userPojo.setUid(uid);
final String path = "" + FirebaseDatabase.getInstance().getReference("users").child(uid);
reference.child(uid).setValue(userPojo).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
startActivity(new Intent(Sign_Up_page.this, Home_Screen.class));
} else {
createdUser.delete();
AlertDialog.Builder DbEntryFailDialog = new AlertDialog.Builder(Sign_Up_page.this);
DbEntryFailDialog.setTitle("Error")
.setMessage("Error" + task.getException().getMessage()
+ "\n\nentry url is " + path)
.setPositiveButton("Ok", null)
.show();
Toast.makeText(Sign_Up_page.this, "Error occurred creating account when Db entry fail, Please try again", Toast.LENGTH_LONG).show();
}
}
});
} else {
if (createdUser != null) {
createdUser.delete();
}
}
}
#Override
protected void onStart() {
super.onStart();
firebaseAuth.addAuthStateListener(authListener);
}
#Override
protected void onStop() {
super.onStop();
firebaseAuth.addAuthStateListener(authListener);
}
}
now the problem is in 1 out of 10 attempts firebaseAuth.getCurrentUser() becomes null after linking With email credentials
I've added authStateListener to track changes in user Authentication State
here is the screenshot
of steps
here are my DB write rules for users table
"users":{
"$uid":{
".write": "auth.uid != null && newData.exists()",
},
".indexOn": "role"
}
Now I can handle null user or DB failure, But I want to know and prevent what is causing this problem
I did something wrong or is this a firebase bug...?
I don't get the error when i run the app everything works fine, but when i click on the send message button the app crashes but the message still gets sent. below is my code for the chatActivity and logcat message
package com.paddi.paddi.paddi;
public class ChatActivity extends AppCompatActivity
{
private String messageReceiverId;
private String messageReceiverName;
// private Toolbar ChatToolBar;
private TextView userNameTitle;
private TextView userLastSeen;
private CircleImageView userChatProfileImage;
private ImageButton SendMessageButton;
// private ImageButton SelectImageButton;
private EditText InputMessageText;
FirebaseUser fuser;
DatabaseReference rootRef;
private FirebaseAuth mAuth;
private String messageSenderId;
private RecyclerView userMessagesList;
private final List<Messages> messageList = new ArrayList<>();
private LinearLayoutManager linearLayoutManager;
private MessageAdapter messageAdapter;
private static int Gallery_Pick = 1;
private StorageReference MessageImageStorageRef;
private ProgressDialog loadingBar;
private String downloadImageUrl;
Intent intent;
ValueEventListener seenListener;
String userid;
APIServiceFragment apiService;
boolean notify = false;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
rootRef = FirebaseDatabase.getInstance().getReference();
mAuth = FirebaseAuth.getInstance();
messageSenderId = mAuth.getCurrentUser().getUid();
messageReceiverId = getIntent().getExtras().get("visit_user_id").toString();
messageReceiverName = getIntent().getExtras().get("user_name").toString();
MessageImageStorageRef = FirebaseStorage.getInstance().getReference().child("Messages_Pictures");
apiService = Client.getClient("https://fcm.googleapis.com/").create(APIServiceFragment.class);
// ChatToolBar = (Toolbar) findViewById(R.id.chat_bar_layout);
// setSupportActionBar(ChatToolBar);
loadingBar = new ProgressDialog(this);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowCustomEnabled(true);
LayoutInflater layoutInflater = (LayoutInflater)
this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View action_bar_view = layoutInflater.inflate(R.layout.chat_custom_bar, null);
actionBar.setCustomView(action_bar_view);
userNameTitle = (TextView) findViewById(R.id.custom_profile_name);
userLastSeen = (TextView) findViewById(R.id.custom_user_last_seen);
userChatProfileImage = (CircleImageView) findViewById(R.id.custom_profile_image_last_seen);
SendMessageButton = (ImageButton) findViewById(R.id.send_message_btn);
// SelectImageButton = (ImageButton) findViewById(R.id.select_image);
InputMessageText = (EditText) findViewById(R.id.input_message);
messageAdapter = new MessageAdapter(messageList);
userMessagesList = (RecyclerView) findViewById(R.id.messages_list_of_users);
linearLayoutManager = new LinearLayoutManager(this);
userMessagesList.setHasFixedSize(true);
userMessagesList.setLayoutManager(linearLayoutManager);
userMessagesList.setAdapter(messageAdapter);
FetchMessages();
userNameTitle.setText(messageReceiverName);
rootRef.child("Users").child(messageReceiverId).addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
final String online = dataSnapshot.child("online").getValue().toString();
final String userThumb = dataSnapshot.child("user_thumb_image").getValue().toString();
Picasso.with(ChatActivity.this).load(userThumb).fit().centerInside().networkPolicy(NetworkPolicy.OFFLINE).placeholder(R.drawable.default_profile)
.into(userChatProfileImage, new Callback() {
#Override
public void onSuccess()
{
}
#Override
public void onError()
{
Picasso.with(ChatActivity.this).load(userThumb).fit().centerInside().placeholder(R.drawable.default_profile).into(userChatProfileImage);
}
});
if (online != null) {
if (online.equals("true"))
{
userLastSeen.setText("online");
}
else
{
LastSeenTime getTime = new LastSeenTime();
long last_seen = Long.parseLong(online);
//problem with last seen time here
String lastSeenDisplayTime = getTime.getTimeAgo(last_seen, getApplicationContext()).toString();
userLastSeen.setText(lastSeenDisplayTime);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError)
{
}
});
SendMessageButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
SendMessage();
}
});
// SelectImageButton.setOnClickListener(new View.OnClickListener() {
// #Override
// public void onClick(View v)
// {
// Intent galleryIntent = new Intent();
// galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
// galleryIntent.setType("image/*");
// startActivityForResult(galleryIntent, Gallery_Pick);
//}
//});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==Gallery_Pick && resultCode==RESULT_OK &&data!=null)
{
loadingBar.setTitle("Sending Image");
loadingBar.setMessage("Please Wait");
loadingBar.show();
Uri ImageUri = data.getData();
final String message_sender_ref = "Messages/" + messageSenderId + "/" + messageReceiverId;
final String message_receiver_ref = "Messages/" + messageReceiverId + "/" + messageSenderId;
DatabaseReference user_message_key = rootRef.child("Messages").child(messageSenderId)
.child(messageReceiverId).push();
final String message_push_id = user_message_key.getKey();
final StorageReference filePath = MessageImageStorageRef.child(message_push_id + ".jpg");
final StorageTask<UploadTask.TaskSnapshot> taskSnapshotStorageTask = filePath.putFile(ImageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
if (task.isSuccessful()) {
downloadImageUrl = filePath.getDownloadUrl().toString();
// return filePath.getDownloadUrl();
Map messageTextBody = new HashMap();
messageTextBody.put("message", downloadImageUrl);
messageTextBody.put("isseen", true);
messageTextBody.put("type", "image");
messageTextBody.put("time", ServerValue.TIMESTAMP);
messageTextBody.put("from", messageSenderId);
messageTextBody.put("to", messageReceiverId);
Map messageBodyDetails = new HashMap();
messageBodyDetails.put(message_sender_ref + "/" + message_push_id, messageTextBody);
messageBodyDetails.put(message_receiver_ref + "/" + message_push_id, messageTextBody);
rootRef.updateChildren(messageBodyDetails, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError != null) {
Log.d("Chat_Log", databaseError.getMessage().toString());
}
InputMessageText.setText("");
loadingBar.dismiss();
}
});
Toast.makeText(ChatActivity.this, "Picture Sent Successfully.", Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
} else {
Toast.makeText(ChatActivity.this, "Picture not sent, Try again", Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
}
}
});
}
}
private void FetchMessages()
{
rootRef.child("Messages").child(messageSenderId).child(messageReceiverId)
.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s)
{
if (dataSnapshot.exists())
{
Messages messages = dataSnapshot.getValue(Messages.class);
messageList.add(messages);
messageAdapter.notifyDataSetChanged();
userMessagesList.smoothScrollToPosition(userMessagesList.getAdapter().getItemCount());
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s)
{
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot)
{
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s)
{
}
#Override
public void onCancelled(DatabaseError databaseError)
{
}
});
// seenMessage(userid);
}
private void seenMessage(final String userid) //add String and userid
{
rootRef = FirebaseDatabase.getInstance().getReference("Messages");
seenListener = rootRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot)
{
for (DataSnapshot snapshot : dataSnapshot.getChildren())
{
Messages messages = snapshot.getValue(Messages.class);
if (messages.getTo().equals(fuser.getUid()) && messages.getFrom().equals(ChatActivity.this.userid))//change messages to userid
{
Map messageTextBody = new HashMap();
messageTextBody.put("isseen", true);
snapshot.getRef().updateChildren(messageTextBody);
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void SendMessage()
{
notify = true;
String messageText = InputMessageText.getText().toString();
if (TextUtils.isEmpty(messageText))
{
Toast.makeText(ChatActivity.this,
"Input message", Toast.LENGTH_SHORT).show();
}
else
{
String message_sender_ref = "Messages/" + messageSenderId + "/" + messageReceiverId;
final String message_receiver_ref = "Messages/" + messageReceiverId + "/" + messageSenderId;
DatabaseReference user_message_key = rootRef.child("Messages").child(messageSenderId)
.child(messageReceiverId).push();
String message_push_id = user_message_key.getKey();
Map messageTextBody = new HashMap();
messageTextBody.put("message", messageText);
messageTextBody.put("isseen", false);
messageTextBody.put("type", "text");
messageTextBody.put("time", ServerValue.TIMESTAMP);
messageTextBody.put("from", messageSenderId);
messageTextBody.put("to", messageReceiverId);
Map messageBodyDetails = new HashMap();
messageBodyDetails.put(message_sender_ref + "/" + message_push_id, messageTextBody);
messageBodyDetails.put(message_receiver_ref + "/" + message_push_id, messageTextBody);
rootRef.updateChildren(messageBodyDetails).addOnCompleteListener(new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task)
{
if (task.isSuccessful())
{
Toast.makeText(ChatActivity.this, "Message Sent", Toast.LENGTH_SHORT).show();
InputMessageText.setText("");
}
else
{
String message = task.getException().getMessage();
Toast.makeText(ChatActivity.this, "Error:" + message, Toast.LENGTH_SHORT).show();
InputMessageText.setText("");
}
}
});
**i tried sending chat notification with the code below
and that was what triggered the error the messages still get sent but the app crashes and restarts itself.**
final String msg = messageText;
rootRef = FirebaseDatabase.getInstance().getReference("Users").child(fuser.getUid());
rootRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot)
{
User user = dataSnapshot.getValue(User.class);
if (notify) {
sendNotification(message_receiver_ref, user.getUsername(), msg);
}
notify = false;
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
private void sendNotification(String message_receiver_ref, final String username, final String message)
{
DatabaseReference tokens = FirebaseDatabase.getInstance().getReference("Tokens");
Query query = tokens.orderByKey().equalTo(message_receiver_ref);
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot)
{
for (DataSnapshot snapshot: dataSnapshot.getChildren())
{
Token token = snapshot.getValue(Token.class);
Data data = new Data(fuser.getUid(), R.mipmap.app_icon, username+": "+message, "New Message",
userid);
Sender sender = new Sender(data, token.getToken());
apiService.sendNotification(sender)
.enqueue(new retrofit2.Callback<MyResponse>() {
#Override
public void onResponse(Call<MyResponse> call, Response<MyResponse> response)
{
if (response.code() == 200)
{
if (response.body().success != 1)
{
Toast.makeText(ChatActivity.this, "Failed!", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onFailure(Call<MyResponse> call, Throwable t)
{
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError)
{
}
});
}
}
this is the logcat below
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.google.firebase.auth.FirebaseUser.getUid()' on a null object reference
at com.paddi.paddi.paddi.ChatActivity.SendMessage(ChatActivity.java:504)
at com.paddi.paddi.paddi.ChatActivity.access$200(ChatActivity.java:58)
at com.paddi.paddi.paddi.ChatActivity$2.onClick(ChatActivity.java:251)
at android.view.View.performClick(View.java:5274)
at android.view.View$PerformClick.run(View.java:21543)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5765)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
You are getting the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.google.firebase.auth.FirebaseUser.getUid()' on a null object reference
Because your fuser object is not initialized. To solve this, please add the following line of code in your onCreate() method:
fuser = FirebaseAuth.getInstance().getCurrentUser().getUid();
In my application, I have two users--Event Member and Client--they have separate user login and registration. If a client log in he will go to the the client activity; if an event member will log in he will go to the event member activity. How will I make sure that the email is a client or an event member?
Below image shows my firebase structure:
Here is my code:
SignupClient.java
signupClient.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String cemail = clie_email.getText().toString().trim();
final String cpassword = clie_password.getText().toString().trim();
String ccpassword = clie_cpassword.getText().toString().trim();
final String cfname = clie_firstname.getText().toString().trim();
final String clname = clie_lastname.getText().toString().trim();
final String cbday = clie_birthday.getText().toString().trim();
final String ccountry = clie_country.getSelectedItem().toString();
final String cmobile = clie_mobile.getText().toString().trim();
auth.createUserWithEmailAndPassword(cemail, cpassword)
.addOnCompleteListener(_5_SignupClient.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Toast.makeText(_5_SignupClient.this, "createUserWithEmail: onComplete" + task.isSuccessful(), Toast.LENGTH_LONG).show();
if (!task.isSuccessful()){
Toast.makeText(_5_SignupClient.this, "Authentication Failed" + task.getException(),
Toast.LENGTH_LONG).show();
}
else {
AccountInfo accountInfo = new AccountInfo(cfname, clname, cemail, cpassword, cbday, ccountry, cmobile);
mDatabaseReference.child("client").push().setValue(accountInfo);
startActivity(new Intent(_5_SignupClient.this, _7_ViewClient.class));
finish();
}
}
});
}
});
LoginClient.java
loginClient.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String clie_unameemail = clie_emailuname.getText().toString();
final String clie_pass = clie_password.getText().toString();
if(TextUtils.isEmpty(clie_unameemail)){
Toast.makeText(getApplicationContext(), "Field cannot be empty", Toast.LENGTH_LONG).show();
return;
}
if(TextUtils.isEmpty(clie_pass)){
Toast.makeText(getApplicationContext(), "Field cannot be empty", Toast.LENGTH_LONG).show();
return;
}
auth.signInWithEmailAndPassword(clie_unameemail, clie_pass)
.addOnCompleteListener(_3_LoginClient.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
ref = FirebaseDatabase.getInstance().getReference().child("client");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot snapshot : dataSnapshot.getChildren()){
if(FirebaseAuth.getInstance().getCurrentUser().getUid().equals(snapshot.getKey())){
startActivity(new Intent(_3_LoginClient.this, _7_ViewClient.class));
}
}
// startActivity(new Intent(_3_LoginClient.this, Normal_memberActivity.class));
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
} else {
// User is signed out
}
// ...
}
};
if (!task.isSuccessful()) {
// there was an error
if (clie_pass.length() < 8) {
clie_password.setError(getString(R.string.minimum_password));
} else {
Toast.makeText(_3_LoginClient.this, getString(R.string.auth_failed), Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(_3_LoginClient.this, "Successfully Registered", Toast.LENGTH_LONG).show();
Intent intent = new Intent(_3_LoginClient.this, _7_ViewClient.class);
startActivity(intent);
finish();
}
}
});
}
});
I hope you could help me. Thank you!
On your db there should be one more field like we say it USER_TYPE. While registering the user send its USER_TYPE. suppose if you are registering a user as a CLIENT then inser db value USER_TYPE="CLIENT" and if its as an Event member registration then inser db value USER_TYPE="EVENT" and now once you logged in check its USER_TYPE and redirect him based upon his USER_TYPE