I'm making a shopping app and User has to subscribe to the 'Fast-delivery' option if he needs to order it faster. When the User puts a tick to the 'Fast-delivery' Checkbox, the boolean value is being uploaded to the Firebase realtime database -->
database
And I want to see if the User has subscribed to the 'Fast-delivery' option from the Admin Panel. I retrieve all the order information to a RecyclerView in the Admin Panel. I want to set a TextView as "Fast Delivery : On/Off" when the Admin views the order details from the Admin Panel.
This is what I have tried:
#Override
protected void onStart()
{
super.onStart();
ordersRef = FirebaseDatabase.getInstance().getReference().child("Orders");
FirebaseRecyclerOptions<AdminOrders> options =
new FirebaseRecyclerOptions.Builder<AdminOrders>()
.setQuery(ordersRef, AdminOrders.class)
.build();
FirebaseRecyclerAdapter<AdminOrders, AdminOrdersViewHolder> adapter =
new FirebaseRecyclerAdapter<AdminOrders, AdminOrdersViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull final AdminOrdersViewHolder holder, final int position, final #NonNull AdminOrders model)
{
holder.userName.setText("Name: "+ model.getName());
holder.userPhoneNumber.setText("Phone Number: : "+ model.getPhone());
holder.userTotalPrice.setText("Total Amount: $"+ model.getTotalAmount());
holder.userDateTime.setText("Order Time: "+ model.getDate() + model.getTime());
holder.userShippingAddress.setText("Shipping Address: "+ model.getAddress() + "," + model.getCity());
holder.showOrdersBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
String uID = getRef(position).getKey();
Intent intent = new Intent(AdminNewOrdersActivity.this, AdminUserProductsActivity.class);
intent.putExtra("uid", uID);
startActivity(intent);
}
});
ordersRef.child(userID).child("fast_delivery").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
TextView switch1 = (TextView) findViewById(R.id.switch1);
switch1.setText(String.valueOf(this));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
And I'm getting this error
java.lang.NullPointerException: Can't pass null for argument 'pathString' in child()
You have a NullPointerException indicating that userID is not initialized, hence this error:
Can't pass null for argument 'pathString' in child()
To solve this, please add the following line of code:
String userID = FirebaseAuth.getInstance().getCurrentUser().getUid();
Right in front of:
ordersRef.child(userID).child("fast_delivery").addValueEventListener(/* ... */);
i guess if im right.. you have created separate tree for orders where you are getting orders
create model class give name as same as childname are where you're getting boolean value of fast_delivery use that boolean value to convert it to string and hence compare that value if String.valueof(boolean)is="true" then print to textview or vise versa with off
Related
So I created a booking app which sends data into booking collection taking userID as Document Name.
But when the user books again it overwrites the previous booking userID document.
What I want to do is: 1) Implement autoincrement on userID, and also 2) display the autoincremented booking too
(Notice I'm using userID because I want to keep it unique to that user only).
3) I also want to implement a limit on booking if someone can help with that.
Firestore Firebase Image:
The code to send data into BOOKING COLLECTION and creating DOCUMENT with userID:
public class bookingpage extends AppCompatActivity {
EditText mFirstnamelastname,mMobnum,mPincode,mFlatno,mArea,mLandmark,mTown,mState;
Button mBook;
String userID;
FirebaseAuth fAuth;
FirebaseFirestore fstore;
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bookingpage);
//pickup
mFirstnamelastname=findViewById(R.id.firstlastname);
mMobnum=findViewById(R.id.mobnum);
mPincode=findViewById(R.id.pincode);
mFlatno=findViewById(R.id.flatno);
mArea=findViewById(R.id.area);
mLandmark=findViewById(R.id.landmark);
mTown=findViewById(R.id.town);
mState=findViewById(R.id.state);
mBook=findViewById(R.id.editbook);
progressBar=findViewById(R.id.progressBar4);
fAuth=FirebaseAuth.getInstance();
fstore=FirebaseFirestore.getInstance();
mBook.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//pickup
String firstname = mFirstnamelastname.getText().toString().trim();
String phoneno = mMobnum.getText().toString().trim();
String pincode = mPincode.getText().toString().trim();
String flatno = mFlatno.getText().toString().trim();
String area = mArea.getText().toString().trim();
String landmark = mLandmark.getText().toString().trim();
String town = mTown.getText().toString().trim();
String state = mState.getText().toString().trim();
progressBar.setVisibility(View.VISIBLE);
//saving data
userID=fAuth.getCurrentUser().getUid();
//creating a document reference creating a collection booking and making a new doc using user id
DocumentReference documentReference = fstore.collection("Booking").document(userID);
//creating a hashmap to send data
Map<String,Object> book = new HashMap<>();
//setting status
book.put("Status -","Active");
//pickup
book.put("a1 - Fullname",firstname);
book.put("a2 - PhoneNo",phoneno);
book.put("a3 - Pincode",pincode);
book.put("a4 - Flatno",flatno);
book.put("a5 - Area",area);
book.put("a6 - Landmark",landmark);
book.put("a7 - Town",town);
book.put("a8 - State",state);
//using the document reference to set user document
documentReference.set(book).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(bookingpage.this, "Booking Successful", Toast.LENGTH_SHORT).show();
Log.d("Tag","onSuccess: Successfully booked for "+ userID);
startActivity(new Intent(getApplicationContext(),MainActivity2.class));
finish();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(bookingpage.this, "Error!" + e.getMessage(), Toast.LENGTH_LONG).show();
}
});
progressBar.setVisibility(View.INVISIBLE);
}
});
}
}
The code to display the booking collection's document with userID:
final DocumentReference documentReference = fstore.collection("Booking").document(userID);
documentReference.addSnapshotListener(this, new EventListener<DocumentSnapshot>() {
#Override
public void onEvent(#Nullable DocumentSnapshot documentSnapshot, #Nullable FirebaseFirestoreException e) {
//putting if else fixed crashing
if (e != null) {
Log.d("Tag", "Error:" + e.getMessage());
} else {
mStatus.setText(documentSnapshot.getString("Status -"));
mFirstnamelastname.setText(documentSnapshot.getString("a1 - Fullname"));
mMobnum.setText(documentSnapshot.getString("a2 - PhoneNo"));
mPincode.setText(documentSnapshot.getString("a3 - Pincode"));
mFlatno.setText(documentSnapshot.getString("a4 - Flatno"));
mArea.setText(documentSnapshot.getString("a5 - Area"));
mLandmark.setText(documentSnapshot.getString("a6 - Landmark"));
mTown.setText(documentSnapshot.getString("a7 - Town"));
mState.setText(documentSnapshot.getString("a8 - State"));
}
}
});
I'm a beginner please try to explain your answer so that I can understand & learn more :)
Well... you just shouldn't use the UserId's as document names in the Booking collection. It's just goes against logic and best-practices.
You should instead let Firestore create a BookingId. It would be your current booking document + a new field (String) holding the UserId of the user who made the booking.
This would be a more logical (and scalable) way.
To limit the number of bookings, you could add a field in your UserId documents (in users collection), called bookingCount (Integer). Each time a User books, check if the bookingCount >= bookingLimit (arbitrary value of your choosing).
If bookingCount < bookingLimit, then allow them to book and increment the bookingCount by 1.
I have tried className.this.finish and finishActivity() to invoke the finishing of my activity and I have initialised the activity with the following methods - startActivityForResult() or finishAndRemoveTask()
The propose of this activity is to register a device this is done when under Devices/(MAC address of the device)/Users/ it save in fire base up to 4 different notification tokens of 4 users different. So what I'm trying to do but it falling is to check if the number 1 have info, check 2 if have info, check 3 and if this have info, check the 4 if all have info the app show a message saying "you have reached the maximum number of users".But if one number available it suppose to save in that number and only in that number the notification token.
What it is happening is that when I click the button the loop never end. it send the same notification token for the four users show the mensage "you have reached the maximum number of users" and then it come back to the activity before this one but it still executing the registration code. I know this because if I deleted an user in firebase it immediately resend the info and you can see the message "you have reached the maximum number of users" again
this is the code of the activity that send the info:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_cerca);
fAuth = FirebaseAuth.getInstance();
entr = findViewById(R.id.AddButton);
mDatabase = FirebaseDatabase.getInstance().getReference();
sDatabase = FirebaseDatabase.getInstance().getReference();
aDatabase = FirebaseDatabase.getInstance().getReference();
MAC =findViewById(R.id.macCerca);
NOM = findViewById(R.id.momCerca);
configured = false;
getUserProfile();
getNotificationId();
entr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MacCerca = MAC.getText().toString().toUpperCase();
NombreCerca = NOM.getText().toString();
//mDatabase.child("Devices").child(MacCerca).child("Id").setValue("AD:23");
mDatabase.child("Devices").child(MacCerca).child("Users").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String user1 = (String) dataSnapshot.child("1").getValue();
String user2 = (String) dataSnapshot.child("2").getValue();
String user3 = (String) dataSnapshot.child("3").getValue();
String user4 = (String) dataSnapshot.child("4").getValue();
if(user1 == null){
aDatabase.child("Devices").child(MacCerca).child("Users").child("1").setValue(token);
aDatabase.child("Devices").child(MacCerca).child("NombreCerca").setValue(NombreCerca);
aDatabase.child("Users").child(mail).child("Device").setValue(MacCerca);
AddCerca.this.finish();
}else if(user2 ==null){
aDatabase.child("Devices").child(MacCerca).child("Users").child("2").setValue(token);
aDatabase.child("Devices").child(MacCerca).child("NombreCerca").setValue(NombreCerca);
aDatabase.child("Users").child(mail).child("Device").setValue(MacCerca);
AddCerca.this.finish();
}else if(user3 ==null){
aDatabase.child("Devices").child(MacCerca).child("Users").child("3").setValue(token);
aDatabase.child("Devices").child(MacCerca).child("NombreCerca").setValue(NombreCerca);
aDatabase.child("Users").child(mail).child("Device").setValue(MacCerca);
AddCerca.this.finish();
}else if(user4 ==null){
aDatabase.child("Devices").child(MacCerca).child("Users").child("4").setValue(token);
aDatabase.child("Devices").child(MacCerca).child("NombreCerca").setValue(NombreCerca);
aDatabase.child("Users").child(mail).child("Device").setValue(MacCerca);
AddCerca.this.finish();
}else{
Toast.makeText(AddCerca.this, "Límite de usuarios registrados exedidos", Toast.LENGTH_SHORT).show();
AddCerca.this.finish();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
});
}
and I create this activity like this:
startActivity(new Intent(CercaElectrica.this, AddCerca.class));
Firebase look like this:
When it suposed to be only in the user 1, or if user 1 have some data it have to update user 2 and the same with 3 and 4
I found the error. insted of:
mDatabase.child("Devices").child(MacCerca).child("Users").addValueEventListener(new ValueEventListener() {
change for:
mDatabase.child("Devices").child(MacCerca).child("Users").addListenerForSingleValueEvent(new ValueEventListener() {
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
I am using firebase database and want to show data in a listview.When I call onDataChange() of firebase database it shows nullpointer excetion. I find my best on google and many other sites but nothing helps me to get rid of this error, so please help me, I,m stuck on this error from last three hours...
Here is Mainactiviy named as Articles_from_firebase.java:
public class Articles_from_fireabse extends AppCompatActivity {
EditText editTextName;
Spinner spinnerGenre;
Button buttonAddArtist;
ListView listViewArtists;
DatabaseReference databaseArtists;
//a list to store all the artist from firebase database
List<Artist> artists;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_articles_from_fireabse);
databaseArtists = FirebaseDatabase.getInstance().getReference("artists");
editTextName = (EditText) findViewById(R.id.editTextName);
spinnerGenre = (Spinner) findViewById(R.id.spinnerGenres);
listViewArtists = (ListView) findViewById(R.id.listViewArtists);
buttonAddArtist = (Button) findViewById(R.id.buttonAddArtist);
buttonAddArtist.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//calling the method addArtist()
//the method is defined below
//this method is actually performing the write operation
addArtist();
}
});
}
private void addArtist() {
//getting the values to save
String name = editTextName.getText().toString().trim();
String genre = spinnerGenre.getSelectedItem().toString();
//checking if the value is provided
if (!TextUtils.isEmpty(name)) {
//getting a unique id using push().getKey() method
//it will create a unique id and we will use it as the Primary Key for our Artist
String id = databaseArtists.push().getKey();
//creating an Artist Object
Artist artist = new Artist(id, name, genre);
//Saving the Artist
databaseArtists.child(id).setValue(artist);
//setting edittext to blank again
editTextName.setText("");
//displaying a success toast
Toast.makeText(this, "Artist added", Toast.LENGTH_LONG).show();
} else {
//if the value is not given displaying a toast
Toast.makeText(this, "Please enter a name", Toast.LENGTH_LONG).show();
}
}
#Override
protected void onStart() {
super.onStart();
//attaching value event listener
databaseArtists.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//clearing the previous artist list
artists.clear();
//iterating through all the nodes
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
//getting artist
Artist artist = postSnapshot.getValue(Artist.class);
//adding artist to the list
artists.add(artist);
}
//creating adapter
ArtistList artistAdapter = new ArtistList(Articles_from_fireabse.this, artists);
//attaching adapter to the listview
listViewArtists.setAdapter(artistAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
Here is my 2nd class ArtistList.java :
public class ArtistList extends ArrayAdapter<Artist> {
private Activity context;
List<Artist> artists;
public ArtistList(Activity context, List<Artist> artists) {
super(context, R.layout.list_layout, artists);
this.context = context;
this.artists = artists;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View listViewItem = inflater.inflate(R.layout.list_layout, null, true);
TextView textViewName = (TextView) listViewItem.findViewById(R.id.textViewName);
TextView textViewGenre = (TextView) listViewItem.findViewById(R.id.textViewGenre);
Artist artist = artists.get(position);
textViewName.setText(artist.getArtistName());
textViewGenre.setText(artist.getArtistGenre());
return listViewItem;
}
This is my Stacktrace:
java.lang.NullPointerException
at com.example.e_agriculture10.Articles_from_fireabse$2.onDataChange(Articles_from_fireabse.java:92)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database##19.1.0:75)
This is the critical block of my code where error exists.
public void onDataChange(DataSnapshot dataSnapshot) {
//clearing the previous artist list
artists.clear();
//iterating through all the nodes
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
//getting artist
Artist artist = postSnapshot.getValue(Artist.class);
//adding artist to the list
artists.add(artist);
}
//creating adapter
ArtistList artistAdapter = new ArtistList(Articles_from_fireabse.this, artists);
//attaching adapter to the listview
listViewArtists.setAdapter(artistAdapter);
}
According to my opinion in this line [artists.clear()], artists getting the null value. Why artists getting null value?
Easy Solution
Whenever you call artists.clear(); check to make sure it is not null.
if(artists != null)
artists.clear();
else
artists = new ArrayList<>();
Sustainable Solution
You should consider what the role of the artists object arry is. In this case, you have both a database and an array that both store information about artists. The database should store persistent data, that is data that lives after program execution. Whereas, your artists object is just around during runtime.
Therefore, you should have code at the start of your program that loads in data from the database into the artists object. Reference / edit / add to the artist object during runtime. Finally, have cleanup code at the end of runtime that updates the artist table in the database.
yes initialize List artists; inside onCreate(){}
Something like this
artists = new ArrayList<>();
Thanks for helping. I am creating an Android app which is working perfectly well. But I am facing a minor problem. The application contains message functionality for the posted ads. When the user opens an ad he is greeted with two options of call or message, where if the user clicks on the message button then he is sent to the chat screen, at the time of the button press the info gets stored in firebase database but I want the info to get stored only for the first time and if the users clicks the button next time then he should be taken to the pre-generated node, not on the new one.
Below is my code for adding the new nodes on the click of the button. Please lemme know if there is any way through which I can stop nodes from getting generated on every button click:
mChat.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent chatIntent = new Intent(ExpandActivity.this, ChatActivity.class);
chatIntent.putExtra("user_id", mId);
chatIntent.putExtra("user_name", mName);
chatIntent.putExtra("ad_id", user_id);
chatIntent.putExtra("cow", m);
startActivity(chatIntent);
mRootRef.child("Chat").child(uid).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
DatabaseReference user_message_push = mRootRef.child("Chat").child(uid).push();
m = user_message_push.getKey();
if (!dataSnapshot.hasChild(user_id)) {
mRootRef.child("AdvertData").child(user_id).addValueEventListener(new
ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String image = dataSnapshot.child("image").getValue().toString();
String title = dataSnapshot.child("title").getValue().toString();
String price = dataSnapshot.child("price").getValue().toString();
Map chatAddMap = new HashMap();
chatAddMap.put("seen", false);
chatAddMap.put("timestamp", ServerValue.TIMESTAMP);
chatAddMap.put("image", image);
chatAddMap.put("title", title);
chatAddMap.put("price", price);
chatAddMap.put("chatUser", mName);
chatAddMap.put("ads", user_id);
chatAddMap.put("chatUserId", mId);
Map chatAddMap1 = new HashMap();
chatAddMap1.put("seen", false);
chatAddMap1.put("timestamp", ServerValue.TIMESTAMP);
chatAddMap1.put("image", image);
chatAddMap1.put("title", title);
chatAddMap1.put("price", price);
chatAddMap1.put("chatUser", name);
chatAddMap1.put("ads", user_id);
chatAddMap1.put("chatUserId", uid);
Map chatUserMap = new HashMap();
chatUserMap.put("Chats/" + uid + "/" + m, chatAddMap);
chatUserMap.put("Chats/" + mId + "/" + m, chatAddMap1);
mRootRef.updateChildren(chatUserMap, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError != null) {
Log.d("CHAT_LOG", databaseError.getMessage().toString());
}
}
});
Below is the picture of how my database looks like:
Here is the logic..! Use addListenerForSingleValueEvent. It is called only one time. And Get key only if snapshot doesn't exist
DatabaseReference user_message_Ref = mRootRef.child("Chat").child(uid);
// First check if snapshot exist()
user_message_Ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists())
{
// GO TO THE DESIRED ACTIVITY
navigateToYOURActivity();
}else
{
// GET KEY
String key = user_message_Ref.push().getKey();
// & UPDATE DATABASE
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
I want the info to get stored only for the first time and if the
users clicks the button next time then he should be taken to the
pre-generated node
It's probably because of addValueEventListener().
You can try using addListenerForSingleValueEvent() which does this only one time i suppose.
When you are using the following lines of code:
DatabaseReference user_message_push = mRootRef.child("Chat").child(uid).push();
m = user_message_push.getKey();
You are generating a new random id at every button click. This is what push() method does. If you want the second time you click the button to access the same reference, you should store that id in a variable and use the same variable again, not generate another one.
In Firebase database i have a directory called Global_downloads then inside there are a few children.
child.("Casting apps") which i can locate with in my app code using a String value called AppType.
the next child.("All cast") is the child i need. i can get it into firebase by using an onitem click with my listview. which then sends it to firebase in the form of a child.
but how can i locate the name for the child(Allcast) progmatically? so i can then get the number of downloads?
here is my code for my child listener
#Override
public void onChildAdded(final com.firebase.client.DataSnapshot dataSnapshot, String s) {
String counter = dataSnapshot.child("Global_downloads").child(Apptype).
child("I need this child").child("downloads").getValue(String.class);
Downloadscount.add(counter);
String[] arr3 = Downloadscount.toArray(new String[Downloadscount.size()]);
the rest of the items in the constructor are for other items in my listview
///my custom adapter where it returns the info to my listview
apkData = new dataListAdapter(mContext, arr, arr1, arr2, mrootRef, Apptype,arr3);
mlv.setAdapter(apkData);
apkData.notifyDataSetChanged();
mlv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
final Firebase ref = mrootRef.getRef();
//here is where i assign the name to firebase in my counter class which works
apkNames = AppNameList.get(i).toString(); //this is the name i want to send back to the top and use as a Child name.or can i get the child name another way.
gc = new Global_counter(ref,Apptype,apkNames);
gc.App_DownLoadCounter();
this is my listview there are more items on my list other than Allcast.
but all cast is the only item downloaded. if more items are pressed it adds that name to the list too. the text view you can see is the downloads im trying to add
To get the coresponding item that was downloaded, please use the following line of code inside onItemClick() method and then just use it inside your DatabaseReference.
String downloadName = (String) adapterView.getItemAtPosition(i);
Assuming that Global_downloads node is a direct child of your Firebase root and the value of downloads is of type Integer, to get the number of downloads please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference downloadsRef = rootRef.child("Global_downloads").child(Apptype).child(downloadName).child("downloads");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int downloads = dataSnapshot.getValue(Integer.class);
Log.d("TAG", downloads);
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
downloadsRef.addListenerForSingleValueEvent(eventListener);
Your output will be:
0
In your situation, the key is Apptype and the value is downloads.
I'm assuming Global_dowbloads under your root reference.
To get all the downloads with app name, you need to read the data as key->value
Like this
DatabaseReference mRef = FirebaseDatabase.getInstance().getReference();
mRef.child("Global_downloads").child(Apptype)
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot snapshot: dataSnapshot.getChildren()){
Log.v("app_name", snapshot.getKey());
Log.v("app_downloads", snapshot.getValue(String.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});