Android - Firebase - Getting Child of Child Data - java

Aim
To prompt the data of the current user such as name, address, neighbourhood by acquiring them through the Data Tree within Firebase Database
Picture of the Data Tree
Desrciption
The "London" and "Washington" child within the Data Tree are added in by the Admin account, which means that they are not fixed and that an additional child such as "New York" can be added.
Which would mean that the newly edited Data Tree will have under "Users", there will be "London", "Washington", and "New York"
The other childs, such as those shown below are fixed.
Guards
name
neighbourhood
Police
address
name
neighbourhood
Resident
address
image
name
neighbourhood
position
status
Problem
I receive a "java.lang.NullPointerException" after attempting to prompt the data of the current user who is logged in.
The error is showing at the code String stgUserHomeName = dataSnapshot.child("Users").getValue().toString();.
I was able to acquire my desired data such as "name", "address" and etc. before but when I had a problem when I added in a Not-Fixed parent such as "London" and "Washington".
SettingsActivity Class
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import com.squareup.picasso.Callback;
import com.squareup.picasso.NetworkPolicy;
import com.squareup.picasso.Picasso;
import java.io.File;
public class SettingsActivity extends AppCompatActivity {
private DatabaseReference jSettingsDatabase;
private FirebaseUser jFirebaseCurrentUser;
private Toolbar jSettingsToolbar;
private ImageView jSettingsImageView;
private TextView jSettingsDisplayName;
private TextView jSettingsStatus;
private TextView jSettingsAddress;
private TextView jSettingsHomeName;
private Button jSettingsDetailsBtn;
private Button jSettingsImageBtn;
private static final int jSettingsGallerySelect = 1;
private StorageReference jSettingsStorageReference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
jSettingsStorageReference = FirebaseStorage.getInstance().getReference();
jFirebaseCurrentUser = FirebaseAuth.getInstance().getCurrentUser();
String settingsUserID = jFirebaseCurrentUser.getUid();
jSettingsDatabase = FirebaseDatabase.getInstance().getReference().child("Resident").child(settingsUserID);
jSettingsDatabase.keepSynced(true);
jSettingsImageView = (ImageView) findViewById(R.id.settingUserImg);
jSettingsToolbar = (Toolbar) findViewById(R.id.settingsToolBar);
setSupportActionBar(jSettingsToolbar);
getSupportActionBar().setTitle("Settings");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
jSettingsDisplayName = (TextView) findViewById(R.id.settingUserNameTxt);
jSettingsStatus = (TextView) findViewById(R.id.settingUserStatusTxt);
jSettingsAddress = (TextView) findViewById(R.id.settingUserAddressTxt);
jSettingsHomeName = (TextView) findViewById(R.id.settingsUserHomeTxt);
jSettingsDetailsBtn = (Button) findViewById(R.id.settingChangeDetailsBtn);
jSettingsImageBtn = (Button) findViewById(R.id.settingChangeImageBtn);
jSettingsDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String stgUserHomeName = dataSnapshot.child("Users").getValue().toString();
String stgUserName = dataSnapshot.child("Users").child(stgUserHomeName).child("name").getValue().toString();
String stgUserStatus = dataSnapshot.child("Users").child(stgUserHomeName).child("status").getValue().toString();
String stgUserHomeAddress = dataSnapshot.child("Users").child(stgUserHomeName).child("address").getValue().toString();
final String stgUserImage = dataSnapshot.child("Users").child(stgUserHomeName).child("image").getValue().toString();
jSettingsDisplayName.setText(stgUserName);
jSettingsStatus.setText(stgUserStatus);
jSettingsAddress.setText(stgUserHomeAddress);
if(!stgUserImage.equals("default")){
Picasso.with(SettingsActivity.this).load(stgUserImage).networkPolicy(NetworkPolicy.OFFLINE)
.placeholder(R.drawable.avataricon).into(jSettingsImageView, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Picasso.with(SettingsActivity.this).load(stgUserImage).placeholder(R.drawable.avataricon).into(jSettingsImageView);
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
jSettingsDetailsBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String stgUserStatusValue = jSettingsStatus.getText().toString();
String stgUserAddressValue = jSettingsAddress.getText().toString();
String stgUserNameValue = jSettingsDisplayName.getText().toString();
Intent intentDetails = new Intent(SettingsActivity.this, DetailsActivity.class);
intentDetails.putExtra("stgUserNameValue" , stgUserNameValue);
intentDetails.putExtra("stgUserStatusValue", stgUserStatusValue);
intentDetails.putExtra("stgUserAddressValue", stgUserAddressValue);
startActivity(intentDetails);
}
});
jSettingsImageBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intentGallery = new Intent();
intentGallery.setType("image/*");
intentGallery.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intentGallery, "SELECT IMAGE"), jSettingsGallerySelect);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == jSettingsGallerySelect && resultCode == RESULT_OK){
Uri imageUri = data.getData();
String currentUserID = jFirebaseCurrentUser.getUid();
StorageReference imageFilePath = jSettingsStorageReference.child("profileImages").child(currentUserID+".jpg");
imageFilePath.putFile(imageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>(){
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
#SuppressWarnings("VisibleForTests")
String downloadImageUrl = task.getResult().getDownloadUrl().toString();
jSettingsDatabase.child("image").setValue(downloadImageUrl).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
Toast.makeText(SettingsActivity.this, "Upload Successful", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(SettingsActivity.this, "Upload Failed", Toast.LENGTH_SHORT).show();
}
}
});
}
});
}
}
}
Code Explanation
The jSettingsHomeName and stgUserHomeName are meant to be the "London", "Washington", and etc.
Solution to almost Similar Problem
In the link: How to get child of child value from firebase in android? , it shows how a programmer can get the child of a child but the reason as to why I am unable to follow the is because my "London" and "Washington" child tier isn't fixed
Update: Trying Solution given by Ewald B.
jSettingsDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot node : dataSnapshot.getChildren()) {
String stgUserHomeName = node.getKey();
String stgUserName = node.child("Resident").child(settingsUserID).child("name").getValue().toString();
String stgUserStatus = node.child("Resident").child(settingsUserID).child("status").getValue().toString();
String stgUserHomeAddress = node.child("Resident").child(settingsUserID).child("address").getValue().toString();
final String stgUserImage = node.child("Resident").child(settingsUserID).child("image").getValue().toString();
jSettingsHomeName.setText(stgUserHomeName);
jSettingsDisplayName.setText(stgUserName);
jSettingsStatus.setText(stgUserStatus);
jSettingsAddress.setText(stgUserHomeAddress);
if(!stgUserImage.equals("default")){
Picasso.with(SettingsActivity.this).load(stgUserImage).networkPolicy(NetworkPolicy.OFFLINE)
.placeholder(R.drawable.avataricon).into(jSettingsImageView, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Picasso.with(SettingsActivity.this).load(stgUserImage).placeholder(R.drawable.avataricon).into(jSettingsImageView);
}
});
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Error
java.lang.NullPointerException at com.example.task.app.SettingsActivity$1.onDataChange(SettingsActivity.java:91)
Line 91 points to String stgUserName = node.child("Resident").child(settingsUserID).child("name").getValue().toString();

According to the data model and looking at this statement
jSettingsDatabase = FirebaseDatabase.getInstance().getReference().child("Resident").child(settingsUserID);
there's no node User underneath /Resident/userId. The query needs to start at the database's root which, I assume, is User.
In order to get London, Washington, etc. you need to adapt the code to:
jSettingsDatabase = FirebaseDatabase.getInstance().getReference().child("Users");
...
jSettingsDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot node : dataSnapshot.getChildren()) {
// you will get all cities
String stgUserHomeName = node.getKey();
if(!"Washington".equals(stgUserHomeName)) // or whatever city you need
continue;
// add some more conditional logic to cope with the distinct subtrees that don't have the same properties
// London's Resident has more properties than Washington --> exception is thrown then
// to get the resident's data
node.child("Resident").child(userId).child("address")...
node.child("Resident").child(userId).child("image")...
// or
node.child("Resident").child(userId).getValue(Resident.class);
...
}
....
}
});
There's no user ID in your tree that is needed for this query. But it might be necessary depending on the DB's access rules. Obviously the other queries need to be adapted as well. The city names are also not values but a key (must be unique) so what is important to call DataSnapshot.getKey() method.
In your case the whole database from the User downwards will be fetched and on the client all cities that are not needed will be thrown away. That's a waste of resources.

for testing purposes only set your Firebase Realtime Database rule to allow anyone read and write
eg
{
"rules": {
".write": "true",
".read": "true"
}
}
Check out Firebase Rules documentation
https://firebase.google.com/docs/database/security/

As soon as you have multiple children at the node, it's needed to scan them at the loop. The event indicates that "some" child was changed. Also, try to change the event to onChildAdded. Like below:
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if (dataSnapshot.getChildrenCount() > 0) {
for (DataSnapshot ds1 : dataSnapshot.getChildren()) {
String stgUserHomeName = ds1.getValue.toString();
.....

Related

Invalid GmsCore APK, remote loading disabledrequires the Google Play Store but it is missing Firebase object access showing null pointer exception

I am writing a sign-in page but the problem here is that every time I click on signin button it doesn't show my homepage but the words "please waiting" keep showing up. I am a newbie to java and firebase, I also searched a lot of websites but didn't find a solution. Does anyone, please help me?
Realtime database :
here is code
package com.example.eatit_new;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import com.example.eatit_new.Common.Common;
import com.example.eatit_new.Model.User;
import com.google.android.material.snackbar.Snackbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.example.eatit_new.databinding.ActivitySignInBinding;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.rengwuxian.materialedittext.MaterialEditText;
public class SignIn extends AppCompatActivity {
EditText editPhone, editPassword;
Button btnSignIn;
#Override
protected void onCreate (Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_sign_in);
editPassword=(MaterialEditText)findViewById(R.id.editPassword);
editPhone= (MaterialEditText)findViewById(R.id.editPhone);
btnSignIn = (Button) findViewById(R.id.btnSignIn);
//init Database
final FirebaseDatabase database= FirebaseDatabase.getInstance();
final DatabaseReference table_user=database.getReference("User");
btnSignIn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final ProgressDialog mDialog = new ProgressDialog(SignIn.this);
mDialog.setMessage("Please waiting....");
mDialog.show();
table_user.addValueEventListener( new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
//Check if user not exist in database
if (dataSnapshot.child(editPhone.getText().toString()).exists()) {
//Get User Information
mDialog.dismiss();
User user = dataSnapshot.child(editPhone.getText().toString()).getValue(User.class);
if (user.getPassword().equals(editPassword.getText().toString())) {
Intent homeIntent= new Intent(SignIn.this,Home.class);
Common.currentUser= user;
startActivity(homeIntent);
finish();
} else {
Toast.makeText(SignIn.this, "Wrong password!", Toast.LENGTH_SHORT).show();
}
} else {
mDialog.dismiss();
Toast.makeText(SignIn.this, "User not exists!", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
});
}
}
in User class :
package com.example.eatit_new.Model;
public class User {
String name;
String password;
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User(String name, String password) {
this.name = name;
this.password = password;
}
}
and I am getting "nullpointerException"
When you create a reference that points to the User node and when you attach a listener to it:
DatabaseReference table_user=database.getReference("User");
It means that you reading (downloading) all the data beneath that node. This is considered an antipattern, since downloading the entire node of users is definitely a waste of resources and bandwidth. If you want to check some data against a specific user, then you should consider adding the typed phone number to the reference. This means that you'll always read a single user, rather than all users. Assuming that the user types in the editPhone EditText one of the numbers that exist in your screenshot, the code should look like this:
String phone = editPhone.getText().toString().trim();
String password = editPassword.getText().toString();
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference phoneRef = db.child("User").child(phone);
phoneRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
DataSnapshot snapshot = task.getResult();
User user = snapshot.getValue(User.class);
if(user.getPassword().equals(password)) {
//Go to next activity
} else {
Toast.makeText(SignIn.this, "Wrong password!", Toast.LENGTH_SHORT).show();
}
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});

How do we get name of child nodes of root or any node using Android code?

From the following code, I am able to get the number of children of the root node but I also want to get the name of them. How could I get it? And what should I make the change in the following code?
package com.example.application_for_curd;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.android.gms.tasks.*;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
printChildrenCount(rootRef);
}
private static final String TAG = "MainActivity";
public void printChildrenCount(DatabaseReference ref) {
ref.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
long childrenCount = task.getResult().getChildrenCount();
Log.d(TAG, "childrenCount: " + childrenCount);
for (int i=0;i<childrenCount;i++)
{
// Log.d(TAG, "childrenName: " + childrenname); // need to involve code here to get children name
}
} else {
Log.d(TAG, task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
}
}
According to database schema that exists in a previous question of yours, to get the name of the children that exist within your root node, please use the following lines of code:
public void printChildrenCount(DatabaseReference ref) {
ref.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
long childrenCount = task.getResult().getChildrenCount();
Log.d(TAG, "childrenCount: " + childrenCount);
for (DataSnapshot child : task.getResult().getChildren()) {
String childName = child.getKey();
Log.d(TAG, "childName: " + childName);
}
} else {
Log.d(TAG, task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
}
And call this method using:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
printChildrenCount(rootRef);
The result in the logcat will be:
Company
GodDepartments
students
Things to notice, to be able to get the name of the children, which are actually the key of the nodes, you need to loop through the "DataSnapshot" object using a call to ".getChildren()" method.
To get the name of the children under "students" ref, for example, kick it of with:
DatabaseReference studentsRef = FirebaseDatabase.getInstance().getReference().child("students");
printChildrenCount(studentsRef);

Android: Trying to fetch the push() key id and extract the rating value from the child element

I am making a feedback app where the customer has to submit a rating (1-5) and that data pushes onto Firebase realtime database. The database in Firebase which looks like this -
{
"Users" : {
"-MCHoOShwgxPE3u2drjz" : {
"Arpit Mundra" : {
"name" : "Arpit Mundra",
"rating" : 5
}
},
"-MCHqbF4UvX02OYJNuPv" : {
"Ankit Mundra" : {
"name" : "Ankit Mundra",
"rating" : 5
}
},
"-MCHr-q_amx1vBJkyq2S" : {
"Harsh Chauhan" : {
"name" : "Harsh Chauhan",
"rating" : 5
}
}
}
}
Now I want to calculated the average of the rating of all the users which falls under user which again falls under the push() id. My question is how do I fetch the unique push() id to extract the rating value from it?
Here is the code -
package com.example.feedback;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AppCompatActivity;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
public class Score extends AppCompatActivity {
TextView avgScore;
DatabaseReference dbRef;
String mGroupID
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //will hide the title
getSupportActionBar().hide(); // hide the title bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); //enable full screen
setContentView(R.layout.score);
avgScore = findViewById(R.id.textView2);
dbRef = FirebaseDatabase.getInstance().getReference().child(mGroupID);
mGroupID = dbRef.push().getKey();
scoreRealTime();
}
public void scoreRealTime() {
dbRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
double total = 0;
for (DataSnapshot ds : snapshot.getChildren()){
double values = Double.parseDouble(ds.child("rating").getValue().toString());
total = total + values;
}
double average = (double) total / snapshot.getChildrenCount();
avgScore.setText(String.format("%.2f", average));
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
}
It is throwing a NullPointerException error at String double values = Double.parseDouble(ds.child("rating").getValue().toString()); line.
Thanks for any help in advance.
EDIT - MainActivity.java -
public class MainActivity extends AppCompatActivity {
EditText name;
ImageView oneStar, twoStar, threeStar, fourStar, fiveStar;
Intent intent;
FirebaseDatabase rootNode;
DatabaseReference reference;
public void displayScore() {
intent = new Intent(getApplicationContext(), Score.class);
startActivity(intent);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //will hide the title
getSupportActionBar().hide(); // hide the title bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); //enable full screen
setContentView(R.layout.activity_main);
name = findViewById(R.id.editTextPersonName);
oneStar = findViewById(R.id.imageView1);
twoStar = findViewById(R.id.imageView2);
threeStar = findViewById(R.id.imageView3);
fourStar = findViewById(R.id.imageView4);
fiveStar = findViewById(R.id.imageView5);
oneStar.setTag(1);
twoStar.setTag(2);
threeStar.setTag(3);
fourStar.setTag(4);
fiveStar.setTag(5);
oneStar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (name.length() == 0){
name.setError("Please enter your full name.");
}
else {
name.setError(null);
rootNode = FirebaseDatabase.getInstance();
reference = rootNode.getReference().child("Users");
//Fetch all values
String username = name.getText().toString();
String value = view.getTag().toString();
int rating = Integer.parseInt(value);
UserHelper helper = new UserHelper(username,rating);
reference.push().child(username).setValue(helper);
Toast.makeText(MainActivity.this, "Feedback submitted successfully!", Toast.LENGTH_SHORT).show();
sleep(2500);
displayScore();
}
}
});
yu do not need to get the pushid. just get the snapshot of user. and then fetch the data from the user object like this.`
databaseReference = FirebaseDatabase.getInstance().getReference().child("Users");
databaseReference .addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
double total = 0;
for (DataSnapshot ds : snapshot.getChildren()){
UserHelper helper = ds.getValue(UserHelper.class);
double values =
Double.parseDouble(helper.rating);
total = total + values;
}
double average = (double) total / snapshot.getChildrenCount();
avgScore.setText(String.format("%.2f", average));
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});`

Recycle view keep loading deleted items

I have the codes below to load and filter the data from Firebase Firestore to a recycle view that Loads all the Filtered data, everything is working fine , but , when I go delete the selected item from the searched list, it does delete from the Firestore data on the web but still loaded by the Search recycle view after been deleted , looks like the Adatper still have the Data and didn't remove it after been deleted , please take a look to the codes Below in both deletenote() and getnotes() methods :-
package com.example.boc.main;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.blogspot.atifsoftwares.animatoolib.Animatoo;
import com.example.boc.PhoneNumbers.NoteRecyclerViewAdapter;
import com.example.boc.PhoneNumbers.ViewNoteDialog;
import com.example.boc.models.Search;
import com.example.boc.search.SearchRecyclerViewAdapter;
import com.example.boc.R;
import com.example.boc.Interface.IMainActivity;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.Query;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;
import java.util.ArrayList;
import com.example.boc.models.Note;
/**
* Created by User on 5/14/2018.
*/
public class Search_test extends AppCompatActivity implements
View.OnClickListener,
IMainActivity,
SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "MainActivity";
//Firebase
private FirebaseAuth.AuthStateListener mAuthListener;
//widgets
private FloatingActionButton mFab, mFab2;
private RecyclerView mRecyclerView;
private SwipeRefreshLayout mSwipeRefreshLayout;
public FirebaseFirestore db = FirebaseFirestore.getInstance();
//vars
private View mParentLayout;
private ArrayList<Search> mSearch = new ArrayList<>();
private ArrayList<Note> mNotes = new ArrayList<>();
private DocumentReference noteRef = db.collection("notes").document();
private CollectionReference notesCollectionRef = db.collection("notes");
private NoteRecyclerViewAdapter mNoteRecyclerViewAdapter;
private SearchRecyclerViewAdapter mSearchRecyclerViewAdapter;
private DocumentSnapshot mLastQueriedDocument;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.search_recycler);
mParentLayout = findViewById(android.R.id.content);
mRecyclerView = findViewById(R.id.recycler_view_search);
EditText userinput = findViewById(R.id.userInputtxt);
initRecyclerView();
getNotes();
}
#Override
public void onBackPressed() {
super.onBackPressed();
Animatoo.animateFade(Search_test.this); //fire the slide left animation
}
#Override
public boolean onCreatOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar, menu);
return true;
}
#Override
public void deleteNote(final Note note) {
FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference noteRef = db
.collection("notes").document(note.getNote_id());
noteRef.delete().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
makeSnackBarMessage("Deleted note");
mRecyclerView.setAdapter(null);// trying to make the recycle view remove the adapter but still loading the old list //
} else {
makeSnackBarMessage("Failed. Check log.");
}
}
});
}
#Override
public void onRefresh() {
}
private void getNotes() {
FirebaseFirestore db = FirebaseFirestore.getInstance();
final EditText userinput = findViewById(R.id.userInputtxt);
CollectionReference notesCollectionRef = db
.collection("notes");
Query notesQuery = null;
if (mLastQueriedDocument != null) {
notesQuery = notesCollectionRef
.orderBy("timestamp", Query.Direction.ASCENDING);
} else {
notesQuery = notesCollectionRef
.orderBy("timestamp", Query.Direction.ASCENDING);
}
notesQuery.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
String data = "";
for (final QueryDocumentSnapshot document : task.getResult()) {
Note note = document.toObject(Note.class);
mNotes.add(note);
if (userinput == null) {
mRecyclerView.setAdapter(null);
}
if (userinput != null) {
userinput.addTextChangedListener(
new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
final String userinputString = userinput.getText().toString();
mSearch.clear();
for (Note note : mNotes) {
if (note.getTitle().contains(userinputString)) {
if (note != null) {
mSearch.add(note);
mSearchRecyclerViewAdapter = new SearchRecyclerViewAdapter(Search_test.this, mSearch);
mRecyclerView.setLayoutManager(new LinearLayoutManager(Search_test.this));
mRecyclerView.setAdapter(mSearchRecyclerViewAdapter);
mSearchRecyclerViewAdapter.notifyDataSetChanged();
}
}
}
}
}
);
}
}
if (task.getResult().size() != 0) {
mLastQueriedDocument = task.getResult().getDocuments()
.get(task.getResult().size() - 1);
}
mSearchRecyclerViewAdapter.notifyDataSetChanged();
} else {
makeSnackBarMessage("Query Failed. Check Logs.");
}
}
});
}
private void initRecyclerView() {
if (mNoteRecyclerViewAdapter == null) {
mSearchRecyclerViewAdapter = new SearchRecyclerViewAdapter(this, mSearch);
}
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setAdapter(mSearchRecyclerViewAdapter);
}
#Override
public void updateNote(final Note note) {
FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference noteRef = db
.collection("notes")
.document(note.getNote_id());
noteRef.update(
"title", note.getTitle(),
"content", note.getContent(), "pos", note.getpos()
).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
makeSnackBarMessage(" تم تحديث المعلومات");
} else {
makeSnackBarMessage("حدث خطأ , يرجى اعادة المحاولة");
}
}
});
}
#Override
public void onNoteSelected(Note note) {
ViewNoteDialog dialog = ViewNoteDialog.newInstance(note);
dialog.show(getSupportFragmentManager(), getString(R.string.dialog_view_note));
}
#Override
public void createNewNote(String title, String content, String pos) {
FirebaseFirestore db = FirebaseFirestore.getInstance();
String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
DocumentReference newNoteRef = db
.collection("notes")
.document();
Note note = new Note();
note.setTitle(title);
note.setContent(content);
note.setPos(pos);
note.setNote_id(newNoteRef.getId());
note.setUser_id(userId);
newNoteRef.set(note).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
makeSnackBarMessage("تمت اضافة رقم الهاتف للسجل");
getNotes();
} else {
makeSnackBarMessage(" يوجد خطأ , يرجى اعادة المحاولة");
}
}
});
}
private void makeSnackBarMessage(String message) {
Snackbar.make(mParentLayout, message, Snackbar.LENGTH_SHORT).show();
}
#Override
public void onClick(View view) {
{
}
}
}
From what i can tell you never removed the element from the list(mNotes or mSearch i think) that the adapter uses it as data source.
So even if it's deleted from Firebase it's still in your list.
To update the list either you have to delete the note from mNotes with the position of the note selected followed by calling adapter notifyDatasetChanged().
Or you have to load the list again from DB calling getNotes().
ANSWER 2
Iliked this one more as long as it doesnot load the data again , as getnotes() will add the data back every time the user input a char.
noteRef.delete().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
makeSnackBarMessage("Deleted fgfff");
mNotes.remove(note);
mSearch.remove(note);
mSearchRecyclerViewAdapter.notifyDataSetChanged();
}
else{
makeSnackBarMessage("Failed. Check log.");
}
}
});
}
ANSWER 1
I got it, thanks for you all for your time, the solution was by clearing both array lists that is loaded with old data and filtered data, then notify the adapter, after that recall the get notes() method to reload the new data from the firebase firestore which does not contain the deleted ones anymore :-
#Override
public void deleteNote(final Note note){
FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference noteRef = db
.collection("notes").document(note.getNote_id());
noteRef.delete().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
makeSnackBarMessage("Deleted fgfff");
mNotes.clear();
mSearch.clear();
mSearchRecyclerViewAdapter.notifyDataSetChanged();
getNotes();
}
else{
makeSnackBarMessage("Failed. Check log.");
}
}
});
}

issues connecting with the firebase database (app keeps crashing whenever i attempt to save to the database)

so i am making a diary application where users log in and then start writing on a diary app that anyone who has the application can access , the application was working fine but after integrating a second layout (the login layout) and the firebase authentication, the application crashes whenever i try to save or view anything from the database. moreover nothing seems to be saved in the database
the second issue is that i would like the userId under which the notes will be saved to be the email the user entered when signing up not the key that firebase can generate
I have tried checking both build gradles and they seem to be working just fine, i also tried just setting the user ID to be 123 to make sure it isn't null
i also tried different versions of android to test it but nothing seems to be working
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference mDatabase = database.getReference("diary");
saveBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String diaryTitle = titleText.getText().toString();
String diaryContent = diaryText.getText().toString();
if(diaryTitle.length()==0||diaryContent.length()==0)
{
Toast.makeText(getApplication().getBaseContext(), "FIELD(S) CANNOT BE EMPTY", Toast.LENGTH_SHORT).show();
}
else {
String userId = "123";
diaryclass userDiary = new diaryclass(diaryTitle, diaryContent);
mDatabase.child(userId).setValue(userDiary);
titleText.setText("");
diaryText.setText("");
Toast.makeText(getApplication().getBaseContext(), "text saved", Toast.LENGTH_SHORT).show();
}
}
});
and below the the class that has the diaryclass constructor
public class diaryclass extends diary{
public String Title;
public String Diary;
public diaryclass(){
}
public diaryclass(String Title,String Diary){
this.Title=Title;
this.Diary=Diary;
}
}
this is what the data base looked like before when it worked
please feel free to ask any questions as i would appreciate any kind of help
below is a link to the entire project if that would help
click here for the android studio project in zip format
for those intrested in the entire code
package ir.mhkz.loginandsignup;
import android.content.Intent;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
public class MainActivity extends AppCompatActivity {
EditText password, reg_password,
reg_email, reg_confirmemail;
Button login, signUp, reg_register;
TextInputLayout txtInLayoutUsername, txtInLayoutPassword, txtInLayoutRegPassword;
CheckBox rememberMe;
private FirebaseAuth mAuth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
reg_email = findViewById(R.id.username);
password = findViewById(R.id.password);
login = findViewById(R.id.login);
signUp = findViewById(R.id.signUp);
txtInLayoutUsername = findViewById(R.id.txtInLayoutUsername);
txtInLayoutPassword = findViewById(R.id.txtInLayoutPassword);
rememberMe = findViewById(R.id.rememberMe);
mAuth = FirebaseAuth.getInstance();
ClickLogin();
//SignUp's Button for showing registration page
signUp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ClickSignUp();
}
});
}
//This is method for doing operation of check login
private void ClickLogin() {
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (reg_email.getText().toString().trim().isEmpty()) {
Snackbar snackbar = Snackbar.make(view, "Please fill out these fields",
Snackbar.LENGTH_LONG);
View snackbarView = snackbar.getView();
snackbarView.setBackgroundColor(getResources().getColor(R.color.red));
snackbar.show();
txtInLayoutUsername.setError("Username should not be empty");
} else {
//Here you can write the codes for checking username
}
if (password.getText().toString().trim().isEmpty()) {
Snackbar snackbar = Snackbar.make(view, "Please fill out these fields",
Snackbar.LENGTH_LONG);
View snackbarView = snackbar.getView();
snackbarView.setBackgroundColor(getResources().getColor(R.color.red));
snackbar.show();
txtInLayoutPassword.setError("Password should not be empty");
} else {
//Here you can write the codes for checking password
}
if (rememberMe.isChecked()) {
//Here you can write the codes if box is checked
} else {
//Here you can write the codes if box is not checked
}
mAuth.signInWithEmailAndPassword(reg_email.getText().toString(),password.getText().toString());
}
});
}
//The method for opening the registration page and another processes or checks for registering
private void ClickSignUp() {
final Intent intent;
intent = new Intent(this,diary.class);
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
View dialogView = inflater.inflate(R.layout.register, null);
dialog.setView(dialogView);
reg_password = dialogView.findViewById(R.id.reg_password);
reg_email = dialogView.findViewById(R.id.reg_email);
reg_confirmemail = dialogView.findViewById(R.id.reg_confirmemail);
reg_register = dialogView.findViewById(R.id.reg_register);
txtInLayoutRegPassword = dialogView.findViewById(R.id.txtInLayoutRegPassword);
reg_register.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (reg_password.getText().toString().trim().isEmpty()) {
txtInLayoutRegPassword.setPasswordVisibilityToggleEnabled(false);
reg_password.setError("Please fill out this field");
} else {
txtInLayoutRegPassword.setPasswordVisibilityToggleEnabled(true);
startActivity(intent);
}
if (reg_email.getText().toString().trim().isEmpty()) {
reg_email.setError("Please fill out this field");
} else {
//Here you can write the codes for checking email
}
if (reg_confirmemail.getText().toString().trim().isEmpty()) {
reg_confirmemail.setError("Please fill out this field");
} else {
//Here you can write the codes for checking confirmemail
}
mAuth.createUserWithEmailAndPassword(reg_email.getText().toString(),reg_password.getText().toString());
}
});
dialog.show();
}
}
and this is the part that the user uses to save and view the diary
package ir.mhkz.loginandsignup;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.constraint.solver.widgets.Snapshot;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
public class diary extends MainActivity {
EditText titleText;
EditText diaryText;
Button saveBtn;
Button viewdata;
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference mDatabase = database.getReference().child("diary");
TextView dtitle;
TextView ddiary;
Button clear;
#Override
protected void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.diary_layout);
titleText=findViewById(R.id.editTextTitle);
diaryText=findViewById(R.id.editTextDiary);
saveBtn = findViewById(R.id.buttonSaveDiary);
viewdata= findViewById(R.id.viewbutton);
dtitle = findViewById(R.id.displaytitle);
ddiary = findViewById(R.id.displaydiary);
clear = findViewById(R.id.buttoncln);
dtitle.setMovementMethod(new ScrollingMovementMethod());
ddiary.setMovementMethod(new ScrollingMovementMethod());
final FirebaseAuth mAuth = null;
final String userId;
if (mAuth.getCurrentUser() != null){
userId = mAuth.getCurrentUser().getUid();
}
viewdata.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dtitle.setText("");
ddiary.setText("");
Toast.makeText(getApplication().getBaseContext(), "text updated", Toast.LENGTH_SHORT).show();
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
List<diaryclass> DiaryList = new ArrayList<diaryclass>();
dtitle.setText("");
ddiary.setText("");
for (DataSnapshot diarySnapshot: dataSnapshot.getChildren()) {
diaryclass thediary = diarySnapshot.getValue(diaryclass.class);
DiaryList.add(thediary);
}
for (int i=0 ; i<DiaryList.size();i++) {
diaryclass listofstuff = DiaryList.get(i);
String titlelist=listofstuff.Title;
String diarylist = listofstuff.Diary;
dtitle.append(i+ "\n" ) ;
dtitle.append(titlelist + "\n" ) ;
dtitle.append("\n" ) ;
dtitle.append("\n" ) ;
dtitle.append(diarylist + "\n" ) ;
dtitle.append("\n" ) ;
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
});
saveBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String diaryTitle = titleText.getText().toString();
String diaryContent = diaryText.getText().toString();
if (mAuth.getCurrentUser() != null) {
mDatabase.child(userId).setValue(diaryTitle, diaryContent)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(getApplication().getBaseContext(), "Saved...", Toast.LENGTH_SHORT).show();
titleText.setText("");
diaryText.setText("");
}
}
});
}
clear.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
titleText.setText("");
diaryText.setText("");
dtitle.setText("");
ddiary.setText("");
Toast.makeText(getApplication().getBaseContext(), "text cleared ", Toast.LENGTH_SHORT).show();
}
});
}
});
}
}
and the gradle is working just fine so i dont think it is needed and the other class is already available up there
logcat below
2019-04-15 04:00:01.684 1778-1803/? E/storaged: getDiskStats failed with result NOT_SUPPORTED and size 0
2019-04-15 04:00:57.777 1869-1869/? E/netmgr: Failed to open QEMU pipe 'qemud:network': Invalid argument
2019-04-15 04:00:57.777 1869-1869/? E/netmgr: WifiForwarder unable to open QEMU pipe: Invalid argument
2019-04-15 04:01:00.007 1926-1940/? E/memtrack: Couldn't load memtrack module
2019-04-15 04:01:00.032 1926-1940/? E/memtrack: Couldn't load memtrack module
2019-04-15 04:01:00.049 1926-1940/? E/memtrack: Couldn't load memtrack module
2019-04-15 04:01:01.687 1778-1803/? E/storaged: getDiskStats failed with result NOT_SUPPORTED and size 0
I did not download your complete code but try to save data on firebase like this
First change DatabaseReference mDatabase = database.getReference("diary"); if diary is the direct child of your database to DatabaseReference mDatabase = database.getReference().child("diary");
2nd you have to get the id of the current user for that
FirebaseAuth mAuth;
String userId;
if (mAuth.getCurrentUser() != null){
userId = mAuth.getCurrentUser().getUid();
}
3rd to save data on Firebase DataBase make sure current user is loged in
if (mAuth.getCurrentUser() != null){
mDatabase.child(userId).setValue(userDiary)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Toast.makeText(getActivity(),"Saved...",Toast.LENGTH_SHORT).show();
titleText.setText("");
diaryText.setText("");
}
});
}
4th be sure in your diaryclass make GETTER and SETTER for all your variabels.
Sorry but symbols like # cannot be use as a name for a firebase database path that's why they generate unique key.

Categories

Resources