I'm trying to make a feature in my Android studio app which allows users to book appointment with a fixed list of doctors through Firebase realtime database. The problem is that FirebaseAuth.getInstance().getCurrentUser().getUid() is always pointing to same ID and so instead of new appointment details being added via children nodes in the parent node, the existing details in children nodes are being overwritten. Here's my code-
DoctorList.java-
public class DoctorList extends AppCompatActivity {
TextView doc1,doc2,doc3,doc4;
FirebaseAuth mAuth;
DatabaseReference patUser;
ProgressDialog loader;
FirebaseDatabase database= FirebaseDatabase.getInstance();
String Date;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_doctor_list);
Intent intent = getIntent();
// receive the value by getStringExtra() method
// and key must be same which is send by first
// activity
String email = intent.getStringExtra("message_key");//patient email
doc1=findViewById(R.id.doc1);
doc2=findViewById(R.id.doc2);
doc3=findViewById(R.id.doc3);
doc4=findViewById(R.id.doc4);
loader = new ProgressDialog(this);
mAuth = FirebaseAuth.getInstance();
FirebaseUser user= mAuth.getInstance().getCurrentUser();
patUser= database.getReference().child("Patient Appointments");
doc1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
loader.setMessage("Please wait....");
loader.setCanceledOnTouchOutside(false);
loader.show();
Intent intent= new Intent( DoctorList.this, Book.class);
intent.putExtra("message_key1", "elise#doc.com");
intent.putExtra("message_key2", email);
startActivity(intent);
// create the get Intent object
Intent intent1 = getIntent();
// receive the value by getStringExtra() method
// and key must be same which is send by first
// activity
Date = intent1.getStringExtra("message");
//Toast.makeText(PatientPage.this, str, Toast.LENGTH_SHORT).show();
String currentUserId = mAuth.getCurrentUser().getUid();
patUser= database.getReference().child("Patient Appointments").child(currentUserId);
//HashMap userInfo = new HashMap();
HashMap userInfo = new HashMap();
userInfo.put("Date",Date);
userInfo.put("Patient",email);
userInfo.put("Doctor","Dr.Elise Heather");
userInfo.put("Phone","5925866");
userInfo.put("Status","Pending");
patUser.updateChildren(userInfo).addOnCompleteListener(new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
if (task.isSuccessful()){
Toast.makeText(DoctorList.this, "Little more to go....", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(DoctorList.this, task.getException().toString(), Toast.LENGTH_SHORT).show();
}
}
});
loader.dismiss();
//Intent intent2= new Intent( DoctorList.this, PatientPage.class);
//startActivity(intent2);
}
});
}
}
Book.java-
public class Book extends AppCompatActivity {
TextView selectedDate;
Button calenderButton,ok;
FirebaseAuth mAuth;
DatabaseReference docUser;
ProgressDialog loader;
FirebaseDatabase database= FirebaseDatabase.getInstance();
String Date;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_book);
Intent intent = getIntent();
// receive the value by getStringExtra() method
// and key must be same which is send by first
// activity
String docEmail = intent.getStringExtra("message_key1");
String patEmail = intent.getStringExtra("message_key2");
selectedDate=findViewById(R.id.text);
calenderButton=findViewById(R.id.calender);
ok=findViewById(R.id.ok);
loader = new ProgressDialog(this);
mAuth = FirebaseAuth.getInstance();
FirebaseUser user= mAuth.getInstance().getCurrentUser();
docUser= database.getReference().child("Doctor Schedule");
MaterialDatePicker materialDatePicker=MaterialDatePicker.Builder.datePicker().
setTitleText("Select date").setSelection(MaterialDatePicker.todayInUtcMilliseconds()).build();
calenderButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
materialDatePicker.show(getSupportFragmentManager(),"Tag_Picker");
materialDatePicker.addOnPositiveButtonClickListener(new MaterialPickerOnPositiveButtonClickListener() {
#Override
public void onPositiveButtonClick(Object selection) {
selectedDate.setText(materialDatePicker.getHeaderText());
Date=materialDatePicker.getHeaderText();
}
});
}
});
ok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (Date != null) {
String currentUserId = mAuth.getCurrentUser().getUid();
docUser = database.getReference().child("Doctor Schedule").child(currentUserId);
//HashMap userInfo = new HashMap();
HashMap userInfo = new HashMap();
userInfo.put("Date", Date);
userInfo.put("Patient", patEmail);
userInfo.put("Doctor", docEmail);
userInfo.put("Status", "Pending");
docUser.updateChildren(userInfo).addOnCompleteListener(new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
if (task.isSuccessful()) {
Toast.makeText(Book.this, "Appointment booked", Toast.LENGTH_SHORT).show();
Intent intent= new Intent( Book.this, DoctorList.class);
intent.putExtra("message", Date);
startActivity(intent);
} else {
Toast.makeText(Book.this, task.getException().toString(), Toast.LENGTH_SHORT).show();
}
}
});
}
else {
Toast.makeText(Book.this, "Select date!", Toast.LENGTH_SHORT).show();
}
}
});
}
}
Suppose a user with email athy#gmail.com books appointment and in Firebase database there's already details of booking by another user nivi#gm.com . Then the details of the latter user in the parent node (ID) gets overwritten by user athy#gmail.com and it looks like this. I don't think I've written code for overwriting instead of updating since it works fine in other Android studio projects, so I'm guessing FirebaseAuth.getInstance().getCurrentUser().getUid() is the one always pointing to same ID which I've circled in the image.
How do I fix this?
Related
String uid;
FirebaseUser user;
TextView BalanceTV;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_miner);
fAuth = FirebaseAuth.getInstance();
BalanceTV = (TextView)findViewById(R.id.BalanceTV);
uid = FirebaseAuth.getInstance().getCurrentUser().getUid()
final String Balance = BalanceTV.getText().toString();
BalanceTV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
databaseReference = FirebaseDatabase.getInstance().getReference("users");
databaseReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot snapshot, #Nullable String previousChildName) {
if(snapshot.getKey().matches("HKAD9FBFfqalSeXCliGTNHPp6Bf1")) {
Map map = (Map) snapshot.getValue();
BalanceTV.setText(map.get("Balance").toString());
}
}
like why when i change "HKAD9FBFfqalSeXCliGTNHPp6Bf1" which is the user id of the user in firebase to uid which is user id i don't retrieve the info of balance, but when i set it to "HKAD9FBFfqalSeXCliGTNHPp6Bf1" i get the balance?
https://i.stack.imgur.com/uXn7n.png
I'm trying to send a value to the server when the connection doesn't exist, when it connects to the internet it runs fine and is saved to the server and sqlite. but the problem arises when switching state from offline to online. I send one value to the server when the connection is offline but when the state moves to online the value I sent earlier becomes multiple on the server while in the sqlite database only one value is stored.
this is my network state checker class
public class NetworkStateCheckerNama extends BroadcastReceiver {
//context and database helper object
private Context context;
private Database db;
ApiRequestData apiRequestData;
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
apiRequestData = ServiceGenerator.createBaseService(this.context, ApiRequestData.class);
db = new Database(context);
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
//if there is a network
if (activeNetwork != null) {
//if connected to wifi or mobile data plan
if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI || activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
//getting all the unsynced user
Cursor cursor2 = db.getUnsyncedNama();
if (cursor2.moveToFirst()) {
do {
//calling the method to save the unsynced name to MySQL
Nama(
cursor2.getString(cursor2.getColumnIndexOrThrow(Database.KOLOM_NAMA_COBA)),
cursor2.getString(cursor2.getColumnIndexOrThrow(Database.KOLOM_NIP_COBA))
);
} while (cursor2.moveToNext());
}
}
}
}
private void Nama(final String nama,final String nip) {
//Call call = retrofit.create(APIInterface.class).saveName(name);
Call call = apiRequestData.nama_query(nama,nip);
call.enqueue(new Callback<Responses>() {
#Override
public void onResponse(Call<Responses> call, Response<Responses> response) {
if (response.code() == 200){
db.updateNamaStatus(nip, MainActivity.NAME_SYNCED_WITH_SERVER);
//sending the broadcast to refresh the list
context.sendBroadcast(new Intent(MainActivity.DATA_SAVED_BROADCAST_MAIN));
}
}
#Override
public void onFailure(Call<Responses> call, Throwable t) {
}
});
}
this is my MainActivity Class
public class MainActivity extends AppCompatActivity {
Session session;
Button buttonLogout,buttonKirim;
TextView textViewNamaMain, textViewNipMain;
EditText editTextNamaMain;
Database database;
private AdapterNama mAdapter;
private RecyclerView listviewNama;
ApiRequestData apiRequestData;
//1 means data is synced and 0 means data is not synced
public static final int NAME_SYNCED_WITH_SERVER = 1;
public static final int NAME_NOT_SYNCED_WITH_SERVER = 0;
//a broadcast to know weather the data is synced or not
public static final String DATA_SAVED_BROADCAST_MAIN = "com.example.myapplication.datasave2";
ArrayList<Nama> namaArray;
ArrayList<User> users;
BroadcastReceiver broadcastReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
session = new Session(this);
buttonLogout = findViewById(R.id.buttonLogout);
buttonKirim = findViewById(R.id.buttonKirim);
textViewNipMain = findViewById(R.id.textViewNipMain);
textViewNamaMain = findViewById(R.id.textViewNamaMain);
editTextNamaMain = findViewById(R.id.editTextTextNamaMain);
String nip = getIntent().getStringExtra("nip");
listviewNama = findViewById(R.id.lv_nama);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
listviewNama.setLayoutManager(layoutManager);
listviewNama.setItemAnimator(new DefaultItemAnimator());
database = new Database(this);
namaArray = new ArrayList<>();
users = new ArrayList<>();
apiRequestData = ServiceGenerator.createBaseService(this, ApiRequestData.class);
textViewNipMain.setText(nip);
registerReceiver(new NetworkStateCheckerNama(), new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
loadDaftarNama(nip);
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//loading the names again
loadDaftarNama(nip);
}
};
registerReceiver(broadcastReceiver, new IntentFilter(DATA_SAVED_BROADCAST_MAIN));
if(!session.isUserLogin()){
logout();
}
buttonKirim.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SimpanKeServer();
}
});
buttonLogout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
logout();
}
});
users.clear();
Cursor cursor = database.getUsersWhereNip(nip);
if (cursor.moveToFirst()) {
do {
User user = new User(
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_NIP)),
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_NAMA)),
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_PASSWORD)),
cursor.getInt(cursor.getColumnIndexOrThrow(Database.KOLOM_STATUS))
);
users.add(user);
textViewNamaMain.setText(user.getNama());
} while (cursor.moveToNext());
}
}
private void SimpanKeServer(){
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Saving Name...");
progressDialog.show();
String nama = editTextNamaMain.getText().toString();
String nip = textViewNipMain.getText().toString();
Call call = apiRequestData.nama_query(nama,nip);
call.enqueue(new Callback<Responses>() {
#Override
public void onResponse(Call<Responses> call, Response<Responses> response) {
progressDialog.dismiss();
if(response.code() == 200){
//if there is a success
//storing the name to sqlite with status synced
SaveNamaToLocal(nama,nip,NAME_SYNCED_WITH_SERVER);
Toast.makeText(MainActivity.this, "Berhasil", Toast.LENGTH_SHORT).show();
}else {
progressDialog.dismiss();
//if there is some error
//saving the name to sqlite with status unsynced
SaveNamaToLocal(nama,nip,NAME_NOT_SYNCED_WITH_SERVER);
Toast.makeText(MainActivity.this, "Gagal", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<Responses> call, Throwable t) {
progressDialog.dismiss();
SaveNamaToLocal(nama,nip,NAME_NOT_SYNCED_WITH_SERVER);
Toast.makeText(MainActivity.this, "Gagal", Toast.LENGTH_SHORT).show();
}
});
}
private void SaveNamaToLocal(String nama, String nip, int status){
database.Nama(nama,nip,status);
Nama namas = new Nama(nama,nip,status);
namaArray.add(namas);
refreshList();
}
private void loadDaftarNama(String nip) {
namaArray.clear();
Cursor cursor = database.getNama(nip);
if (cursor.moveToFirst()) {
do {
Nama nama = new Nama(
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_NAMA_COBA)),
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_NIP_COBA)),
cursor.getInt(cursor.getColumnIndexOrThrow(Database.KOLOM_STATUS_NAMA_COBA))
);
namaArray.add(nama);
} while (cursor.moveToNext());
}
mAdapter = new AdapterNama(this, namaArray);
listviewNama.setAdapter(mAdapter);
}
#SuppressLint("NotifyDataSetChanged")
private void refreshList() {
mAdapter.notifyDataSetChanged();
}
private void logout(){
session.updateUserLoginStatus(false);
finish();
startActivity(new Intent(MainActivity.this,LoginActivity.class));
}
}
this when online
enter image description here
enter image description here
this the problem when state internet switch from offline to online
enter image description here
enter image description here
Even in server send 3 same values
I'm sorry for my english and my question structure im new in programmer, and thank you for the answer
I want to make a login without input form, just use a button that authenticates to the custom field firebase, help me
TextView var_text;
private DatabaseReference ref;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
var_text = (TextView) findViewById(R.id.infoText);
ref = FirebaseDatabase.getInstance().getReference().child("karyawan");
}
String phoneID;
public void btnLogin_Click(View view) {
phoneID = phoneID.getBytes().toString();
ref.child(phoneID).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot)
{
karyawan karyawan = dataSnapshot.getValue(karyawan.class);
if (phoneID.equals(karyawan.getPhoneID())){
Toast.makeText(MainActivity.this, "login sukses", Toast.LENGTH_SHORT).show();
Intent i = new Intent(MainActivity.this, MenuActivity.class);
startActivity(i);
}else {
Toast.makeText(MainActivity.this, "Anda belum terdaftar" , Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError)
{
}
});
}
}
enter image description here
enter image description here
So you want your login information stored on the mobile device? If so just store it as strings and pass those in when you login. Not secure obviously. Something like this:
You will also need to add the credentials to your firebase database. There are also some rules about email and pass words they have to be value e.g. email needs an # with something after it like .com. And I think the passwords needs to be at least length 6.
private void login(String email, String password)
{
String my_username = test;
String my_password = test;
mAuth.signInWithEmailAndPassword(my_username, my_password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {//This is the logging in api
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) //Logged in successfully to firebase
{
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithEmail:success");
FirebaseUser user = mAuth.getCurrentUser();//Identify who is logged in
logged_in_user_string = mAuth.getCurrentUser().getEmail();//Store the logged in user's email address to be displayed
//You are logged in here stare next activity
}
else
{
// If sign in fails, display a message to the user.
Log.w(TAG, "signInWithEmail:failure", task.getException());
Log.d(TAG, "Login failed");
}
}
});
}
I am trying to update my user profile (specifically the photo) by making intent for choosepicker to select image from my gallery and upload it to my firebase authenticated storage. It's working almost fine: pics are getting uploaded to the path I describe.
The problem is I cannot retreive it back as I want. I want to update user profile pic and use UpdateProfileRequest but it's just not updating anything, nor can I retrieve anything.
Here's the code:
final ImageView photo = (ImageView) findViewById(R.id.photoURI);
if (photoUri == null) {
photo.setImageResource(R.drawable.user);
Toast.makeText(LoginActivity.this,"DP is Empty",Toast.LENGTH_SHORT).show();
} else {
photo.setImageURI(photoUri);
}
Button editPhoto = (Button) findViewById(R.id.edit_photo);
editPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/jpeg");
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
startActivityForResult(Intent.createChooser(intent, "Complete action using"), RC_PHOTO_PICKER);
}
});
Here is my activity result code
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_PHOTO_PICKER && resultCode == RESULT_OK) {
final Uri selectedImageUri = data.getData();
// Get a reference to store file at User_photos/<FILENAME>
StorageReference photoRef = storageReference.child(userID).child(selectedImageUri.getLastPathSegment());
// Upload file to firebase Storage
photoRef.putFile(selectedImageUri).addOnSuccessListener(this, new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Uri downloadUrl = taskSnapshot.getDownloadUrl();
String imageUrl = downloadUrl.toString();
User user = new User(imageUrl);
databaseReferencenew.child(userID).child("Profile_Pic_URL").setValue(user);
FirebaseUser user2 = FirebaseAuth.getInstance().getCurrentUser();
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setDisplayName(mName)
.setPhotoUri(selectedImageUri)
.build();
user2.updateProfile(profileUpdates).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Log.d(TAG, "User profile updated.");
Toast.makeText(LoginActivity.this,"User profile updated.",Toast.LENGTH_SHORT).show();
}
});
}
});
}
}
I am using Retrofit 2.0 to retrieve data from my api and using a recyclerView to display it.
My main activity has a tab layout and one of those tabs has the recyclerView and the fragment class for that tab is being used to retrieve the data and update the layout.
In my main layout I have a fab which makes a post (all posts are being retrieved in fragment class) and this fab has it's function of making the post in main activity.
So how can I refresh the layout when the fab's function is over and the post is successfully saved in my database?
Basically
User clicks fab > Makes his post > Alert dialog closes > recyclerView should be refreshed with new data added.
My Fragment Class :
public class PostsRecentTab extends Fragment {
private static final String TAG = MainActivity.class.getSimpleName();
private RecyclerView feedView;
private ProgressDialog pDialog = MainActivity.pDialog;
LinearLayoutManager layoutManager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.tab_recent_posts, container, false);
pDialog.setCancelable(false);
layoutManager = new LinearLayoutManager(this.getContext());
feedView = (RecyclerView) v.findViewById(R.id.feedView);
requestData();
return v;
}
public void requestData() {
SocialHubAPI apiService = ApiClient.getClient().create(SocialHubAPI.class);
pDialog.setMessage("Refreshing...");
showDialog();
Call<StatusResponse> call = apiService.getStatuses();
call.enqueue(new Callback<StatusResponse>() {
#Override
public void onResponse(Call<StatusResponse> call, Response<StatusResponse> response) {
int statusCode = response.code();
List<Status> statuses = response.body().getStatuses();
Log.d(TAG, "Status Code: " + statusCode);
hideDialog();
updateView(statuses);
}
#Override
public void onFailure(Call<StatusResponse> call, Throwable t) {
Log.e(TAG, t.toString());
}
});
}
private void updateView(List<Status> statuses) {
StatusesAdapter adapter = new StatusesAdapter(statuses, R.layout.feed_item, getContext());
feedView.setLayoutManager(layoutManager);
feedView.setAdapter(adapter);
}
private void showDialog() {
if (!pDialog.isShowing())
pDialog.show();
}
private void hideDialog() {
if (pDialog.isShowing())
pDialog.dismiss();
}
}
My Fab On Click :
FloatingActionButton postStatus = (FloatingActionButton) findViewById(R.id.postStatus);
postStatus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Post Status");
// Set up the input
final EditText input = new EditText(MainActivity.this);
// Specify the type of input expected; this, for example, sets the input as a password, and will mask the text
input.setInputType(InputType.TYPE_CLASS_TEXT);
builder.setView(input);
// Set up the buttons
builder.setPositiveButton("Post", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
postText = input.getText().toString();
processPost(postText, sessionManager.getToken());
Snackbar.make(view, "Status posted!", Snackbar.LENGTH_LONG).show();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
}
});
Fab onClick calls this method :
protected void processPost(String postText, String token) {
SocialHubAPI apiService = ApiClient.getClient().create(SocialHubAPI.class);
pDialog.setMessage("Posting...");
showDialog();
final PostRequest postRequest = new PostRequest();
postRequest.setStatus(postText);
Call<PostResponse> call = apiService.postStatus(postRequest, token);
call.enqueue(new Callback<PostResponse>() {
#Override
public void onResponse(Call<PostResponse> call, Response<PostResponse> response) {
hideDialog();
Toast.makeText(getApplicationContext(), "Status Posted Successfully!", Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(Call<PostResponse> call, Throwable t) {
Log.e(TAG, t.toString());
}
});
}
You should invalidate your list in updateView(List<Status> statuses) instead of setting the adapter again. Instantiate adapter only in onCreate().
This function should be like this:
adapter.addNewStatutes(statuses)
in Adapter class
public void addNewStatutes(List<Status> statuses)
{
this.statuses.addAll(statuses);
notifyDataSetChanged();
}
Also in onResponse use EventBus or Rx, because your view can be destroyed and this method can crash your app.
Added notifyDataSetChanged as per docs.