Updating code to save the state of the clicked items - android

I'm a new developer to android development. I'll like the code below (for querying and displaying images media collection) whose images checkboxes are checked when clicked, to be updated to include onsaveinstancestate to save the state of the clicked/checked items.
public class PhotosFragment extends Fragment {
ArrayList<ImageModel > imageList;
RecyclerView imageRecyclerView;
ImageAdapter imageAdapter;
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_photos, container, false);
runtimePermission();
return view;
}
private void runtimePermission() {
Dexter.withContext(getContext()).withPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
.withListener(new PermissionListener() {
#Override
public void onPermissionGranted(PermissionGrantedResponse permissionGrantedResponse) {
init();
getAllImages();
setImageList();
}
#Override
public void onPermissionDenied(PermissionDeniedResponse permissionDeniedResponse) {
Toast.makeText(getContext(), "Permission is Required!", Toast.LENGTH_SHORT).show();
}
#Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permissionRequest, PermissionToken permissionToken) {
permissionToken.continuePermissionRequest();
}
}).check();
}
public void init() {
imageRecyclerView = (RecyclerView) view.findViewById(R.id.photos_recycler);
imageList = new ArrayList<>();
}
public void setImageList() {
imageRecyclerView.setLayoutManager((new GridLayoutManager(getContext(), 4)));
imageAdapter = new ImageAdapter(getContext(), imageList);
imageRecyclerView.setAdapter(imageAdapter);
/* Here `isSelected` is a boolean variable. It is true when item is checked and false when not checked. When false, the if condition evaluates to true and the `selectImage()` method is called, otherwise the `unSelectImage()` is called */
imageAdapter.setOnItemClickListener(new ImageAdapter.OnItemClickListener() {
#Override
public void onItemViewClick(int position, View v){
try {
if (!imageList.get(position).isSelected) {
selectImage(position);
} else {
unSelectImage(position);
}
} catch (ArrayIndexOutOfBoundsException ed) {
ed.printStackTrace();
}
}
});
};
public void selectImage(int position) {
imageList.get(position).setSelected(true);
imageAdapter.notifyDataSetChanged();
}
public void unSelectImage(int position) {
imageList.get(position).setSelected(false);
imageAdapter.notifyDataSetChanged();
}
}
Querying the mediastore for images collection
public void getAllImages() {
Uri imageCollection;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
imageCollection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
} else {
imageCollection = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
}
String[] projection = new String[] {
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.Media.SIZE
};
String sortOrder = MediaStore.Images.Media.DATE_ADDED + " DESC";
Cursor cursor = getActivity().getContentResolver().query(imageCollection , projection, null, null, sortOrder);
int idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
int nameColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME);
int dateColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED);
int sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE);
while (cursor.moveToNext()) {
long id = cursor.getLong(idColumn);
String name = cursor.getString(nameColumn);
int duration = cursor.getInt(dateColumn);
int size = cursor.getInt(sizeColumn);
Uri uriImage = Uri.withAppendedPath(imageCollection, ""+ id);
ImageModel imageModel = new ImageModel();
imageModel.setImage(uriImage);
imageList.add(imageModel);
}
cursor.close();
}

Related

how do i get single file size in listView

i'am trying to display all files in devices with specific extensions, but problem is i got wrong size on all files, it only display 22 bytes to all files in listView. and i want to get default picture like zip image, ISO image and image of APK.. where i do wrong
public class NotificationsFragment extends Fragment {
ListView listView;
String[] items;
private NotificationsViewModel notificationsViewModel;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
notificationsViewModel =
ViewModelProviders.of(this).get(NotificationsViewModel.class);
View root = inflater.inflate(R.layout.fragment_notifications, container, false);
listView = root.findViewById(R.id.app_list);
runtimePermission();
//final TextView textView = root.findViewById(R.id.text_notifications);
notificationsViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
//textView.setText(s);
}
});
return root;
}
public void runtimePermission() {
Dexter.withContext(getContext()).withPermissions(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO)
.withListener(new MultiplePermissionsListener() {
#Override
public void onPermissionsChecked(MultiplePermissionsReport multiplePermissionsReport) {
showList();
}
#Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> list, PermissionToken permissionToken) {
permissionToken.continuePermissionRequest();
}
}).check();
}
public ArrayList<File> findList(File file) {
ArrayList<File> arrayList = new ArrayList<>();
File[] files = file.listFiles();
for (File singleFile : files) {
if (singleFile.isDirectory() && !singleFile.isHidden()) {
arrayList.addAll(findList(singleFile));
} else {
if (singleFile.getName().endsWith(".apk") || singleFile.getName().endsWith(".iso") || singleFile.getName().endsWith(".exe") || singleFile.getName().endsWith(".rar") || singleFile.getName().endsWith(".zip")) {
arrayList.add(singleFile);
}
}
}
return arrayList;
}
private void showList() {
final ArrayList<File> myApps = findList(Environment.getExternalStorageDirectory());
items = new String[myApps.size()];
for (int i = 0; i<myApps.size(); i++){
items[i] = myApps.get(i).getName().toString();
}
customAdapter customAdapter = new customAdapter();
listView.setAdapter(customAdapter);
}
public String readableFileSize(long size) {
if (size <= 0)
return "0";
final String[] units = new String[] { "byte", "kb", "mb", "gb", "tb" };
int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
}
class customAdapter extends BaseAdapter {
#Override
public int getCount() {
return items.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View myView = getLayoutInflater().inflate(R.layout.download_item, null);
TextView songName = myView.findViewById(R.id.download_name);
ShapeableImageView appImage = myView.findViewById(R.id.download_img);
TextView sizeApp = myView.findViewById(R.id.app_details);
TextView install = myView.findViewById(R.id.install_btn);
songName.setSelected(true);
songName.setText(items[position]);
sizeApp.setText(readableFileSize(items.length));
// it gives 22 bytes to all list, which is not true
//How to get default image of file into listview??
return myView;
}
}
}
items is your list. So items.length is the length of the list, not the length of a file. Try sizeApp.setText(readableFileSize(items[position].length)).

IndexOutOfBoundException while reading from Cursor

I'm trying to use a CursorLoader but keep getting an IndexOutOfBounds error when reading from the Cursor. Relevant error lines from Logcat:
at com.codephillip.app.busticket.SelectRouteFragment.onLoadFinished(SelectRouteFragment.java:96)
at com.codephillip.app.busticket.SelectRouteFragment.onLoadFinished(SelectRouteFragment.java:28)
This is the fragment class:
public class SelectRouteFragment extends Fragment implements MaterialSpinner.OnItemSelectedListener, LoaderManager.LoaderCallbacks {
private static final String TAG = SelectRouteFragment.class.getSimpleName();
private MaterialSpinner destSpinner;
private MaterialSpinner sourceSpinner;
private Button selectButton;
private String destination;
private String source;
public SelectRouteFragment() {
}
public static SelectRouteFragment newInstance() {
return new SelectRouteFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_select_route, container, false);
destSpinner = rootView.findViewById(R.id.dest_spinner);
sourceSpinner = rootView.findViewById(R.id.source_spinner);
destSpinner.setOnItemSelectedListener(this);
sourceSpinner.setOnItemSelectedListener(this);
selectButton = rootView.findViewById(R.id.select_button);
selectButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (source.equals(destination)) {
Toast.makeText(getContext(), "Choose a different Destination", Toast.LENGTH_SHORT).show();
} else {
Intent intent = new Intent(getContext(), BookActivity.class);
intent.putExtra(Utils.SOURCE, source);
intent.putExtra(Utils.DESTINATION, destination);
getActivity().startActivity(intent);
}
}
});
return rootView;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getLoaderManager().initLoader(2, null, this);
}
#Override
public Loader onCreateLoader(int id, Bundle args) {
return new CursorLoader(getContext(), LocationsColumns.CONTENT_URI, null, null, null, null);
}
#Override
public void onLoadFinished(Loader loader, Cursor data) {
Log.d(TAG, "onLoadFinished: started");
LocationsCursor cursor = new LocationsCursor(data);
List locations = new ArrayList<>();
if (cursor.moveToFirst()) {
do {
locations.add(cursor.getName());
} while (cursor.moveToNext());
}
// Set default route values
source = locations.get(0);
destination = locations.get(0);
ArrayAdapter dataAdapter = new ArrayAdapter(getContext(), android.R.layout.simple_expandable_list_item_1, locations);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sourceSpinner.setAdapter(dataAdapter);
destSpinner.setAdapter(dataAdapter);
}
#Override
public void onLoaderReset(Loader loader) {
}
#Override
public void onItemSelected(MaterialSpinner view, int position, long id, Object itemObject) {
Snackbar.make(view, "Clicked " + itemObject.toString(), Snackbar.LENGTH_LONG).show();
String item = itemObject.toString();
Log.d(TAG, "onItemSelected: " + item);
if (view.getId() == destSpinner.getId()) {
Log.d(TAG, "onItemSelected: clicked dest");
destination = item;
} else {
Log.d(TAG, "onItemSelected: clicked source");
source = item;
}
}
}
Any help understanding the issue would be greatly appreciated.
I guess the issue is happening here:
source = locations.get(0);
destination = locations.get(0);
If cursor is empty, locations will also be empty and then, locations.get(0) will throw an exception.
You should check if location is not empty.
if(locations.size() > 0) {
...
}

How to show images in recyclerview with date as a header?

I am working on an application where I have to display images stored in phone directory.I have implemented the code to get all images in recyclerview, but I want to show the date of the image when it was taken inside header. I have searched for many days but couldn't find any specific answer. The design I am following is in this
Image
Here I am initializing my view
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view= inflater.inflate(R.layout.fragment_list_images,container,false);
ButterKnife.bind(this,view);
context= view.getContext();
adapter= new ImagesAdapter();
LinearLayoutManager linearVertical = new LinearLayoutManager(view.getContext(), LinearLayoutManager.VERTICAL,false);
recyclerView.setLayoutManager(linearVertical);
recyclerView.setAdapter(adapter);
checkboxHeaderVideo.setClickable(false);
adapter.setData(getImages(context));
return view;
}
And here I am getting all pictures from directory
private List<ImagesModel> getImages(Context context) {
ArrayList<ImagesModel> ImagesModels= new ArrayList<>();
int int_position = 0;
Uri uri;
int column_index_data, thum, column_index_gif, thumGif;
String absolutePathOfImage = null;
String duration = null;
uri = MediaStore.Image.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.MediaColumns.DATA, MediaStore.Image.Media.BUCKET_DISPLAY_NAME,MediaStore.Image.Media._ID,MediaStore.Image.Thumbnails.DATA};
final String orderBy = MediaStore.Image.Media.DATE_TAKEN;
cursor = context.getContentResolver().query(uri, projection, null, null, orderBy + " DESC");
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
thum = cursor.getColumnIndexOrThrow(MediaStore.Image.Thumbnails.DATA);
while (cursor.moveToNext()) {
absolutePathOfImage = cursor.getString(column_index_data);
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
File files= new File(absolutePathOfImage);
if (files.exists()){
retriever.setDataSource(absolutePathOfImage);
ArrayList<String> list = AppUtils.fileParsing(absolutePathOfImage);
String path_name =list.get(0);
Log.i("path name",path_name);
ImagesModel obj_model = new ImagesModel();
obj_model.setImageName(path_name);
obj_model.setThumbNail(cursor.getString(thum));
obj_model.setSelected(false);
obj_model.setAbsolutePath(absolutePathOfImage);
ImagesModels.add(obj_model);
}
}
listSize= ImagesModels.size();
return ImagesModels;
}
Image Adapter.
public class ImagesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List<ImagesModel> modelList;
private boolean selection;
OnSelectionChangeListener selectionChangeListener;
int count=0;
public void setSelectionChangeListener(OnSelectionChangeListener selectionChangeListener) {
this.selectionChangeListener = selectionChangeListener;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.li_Images_list,parent,false);
return new ImagesItemHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
int size= modelList.size();
((ImagesItemHolder)holder).bindData(modelList.get(position),position,size);
}
#Override
public int getItemCount() {
return modelList.size();
}
public void setData(List<ImagesModel> list) {
this.modelList= list;
notifyDataSetChanged();
}
public boolean isSelection() {
return selection;
}
public void setSelection(boolean selection) {
this.selection = selection;
if (selectionChangeListener != null)
selectionChangeListener.onSelectionChange(selection);
notifyDataSetChanged();
}
public void clearSelection() {
for (ImagesModel obj : getData()) {
obj.setSelected(false);
}
setSelection(false);
count=0;
}
public interface OnSelectionChangeListener {
void onSelectionChange(boolean selection);
}
public List<ImagesModel> getData() {
return modelList;
}
public void setChecked(int position) {
count++;
getData().get(position).setSelected(!getData().get(position).isSelected());
if (!isAnyItemSelected()) {
setSelection(false);
} else notifyItemChanged(position);
}
boolean isAnyItemSelected() {
for (ImagesModel obj : getData()) {
if (obj.isSelected())
return true;
}
return false;
}
public void setCheckedAll(boolean selection) {
for (ImagesModel object : getData())
object.setSelected(selection);
count= getData().size();
setSelection(selection);
}
public int getSelectedItemCount(){
return count;
}
public ArrayList<ImagesModel> getAllSelectedItems() {
ArrayList<ImagesModel> selectedObjects = new ArrayList<>();
if (getData() != null && !getData().isEmpty()) {
for (ImagesModel item : getData()) {
if (item.isSelected()) selectedObjects.add(item);
}
}
return selectedObjects;
}
Problem is i don't know how to add Date as header in specific format and show related images below that specific date

RecyclerView shows nothing

I'm new in this android world. I'm currently working on android project i.e., music player but i got stopped at one point since my recycler view doesn't display anything which is supposed to be a list of songs.
I even checked my logcat but cannot figured out whether the data is binding or not.Any kind of help will be grateful.
SongListAdapter.java
public class SongListAdapter extends RecyclerView.Adapter<SongListAdapter.MyViewHolder> {
ArrayList<SongDetailsJDO> mSongDetailsJDOs;
LayoutInflater mLayoutInflater;
Context mContext;
private static final String TAG = "SongListAdapter";
private boolean mIsSongPlaying = false;
private String mCurrentSongId = "-1";
public SongListAdapter(Context context, ArrayList<SongDetailsJDO> pSongDetailsJDOs) {
mContext = context;
mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mSongDetailsJDOs = pSongDetailsJDOs;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View lView = mLayoutInflater.inflate(R.layout.recycler_view_item, parent, false);
return new MyViewHolder(lView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Uri lUri = null;
if (mSongDetailsJDOs.get(position).getAlbumId() != null && !mSongDetailsJDOs.get(position).getAlbumId().equals("")) {
lUri = ContentUris.withAppendedId(Uri.parse("content://media/external/audio/albumart"), Long.parseLong(mSongDetailsJDOs.get(position).getAlbumId()));
Picasso.with(mContext).load(lUri).resize(100, 100).placeholder(R.drawable.placeholder).into(holder.albumImageIV);
} else
holder.albumImageIV.setImageResource(R.drawable.placeholder);
String lTrackName = mSongDetailsJDOs.get(position).getTitle();
if (lTrackName != null)
holder.trackNameTV.setText(lTrackName.trim());
else
holder.trackNameTV.setText("<Unknown>");
String lAlbumName = mSongDetailsJDOs.get(position).getAlbumName();
if (lAlbumName != null)
holder.albumAndArtistDetailsTV.setText(lAlbumName.trim());
else
holder.albumAndArtistDetailsTV.setText("<Unknown>");
if (mSongDetailsJDOs.get(position).getFavouriteStatus() == 1)
holder.favouriteIV.setImageResource(R.drawable.fav);
else
holder.favouriteIV.setImageResource(R.drawable.fav_u);
// TODO: #holder.animationDrawable use it change Visibility and start (Animation)
if (mIsSongPlaying && mSongDetailsJDOs.get(position).getSongId().equals(mCurrentSongId)) {
holder.eqIv.setVisibility(View.VISIBLE);
holder.animationDrawable = (AnimationDrawable) holder.eqIv.getBackground();
holder.animationDrawable.start();
} else {
holder.eqIv.setVisibility(View.INVISIBLE);
}
}
#Override
public int getItemCount() {
if (mSongDetailsJDOs != null)
return mSongDetailsJDOs.size();
else
return 0;
}
/**
* Called when data is being updated in DB
*/
public void favChanged(int pPosition, int pFavStatus) {
mSongDetailsJDOs.get(pPosition).setFavouriteStatus(pFavStatus);
notifyItemChanged(pPosition);
}
/**
* View Holder class for Rec view
*/
class MyViewHolder extends RecyclerView.ViewHolder {
ImageView albumImageIV;
TextView trackNameTV;
TextView albumAndArtistDetailsTV;
ImageView favouriteIV;
ImageView eqIv;
AnimationDrawable animationDrawable;
MyViewHolder(View itemView) {
super(itemView);
albumImageIV = (ImageView) itemView.findViewById(R.id.album_artwork_iv);
trackNameTV = (TextView) itemView.findViewById(R.id.title_name_tv);
albumAndArtistDetailsTV = (TextView) itemView.findViewById(R.id.artist_author_name_tv);
favouriteIV = (ImageView) itemView.findViewById(R.id.fav_iv);
eqIv = (ImageView) itemView.findViewById(R.id.eq_iv);
}
}
/**
* Swap the data with the new JDO list
*
* #param pSongDetailsJDOs
*/
public void swapData(ArrayList<SongDetailsJDO> pSongDetailsJDOs) {
mSongDetailsJDOs = pSongDetailsJDOs;
notifyDataSetChanged();
}
/**
* Returns the list of currently loaded JDO's
* #return
*/
public List<SongDetailsJDO> getData() {
return mSongDetailsJDOs;
}
/**
* Gets the #{#link SongDetailsJDO} object at the specified position
* #param pPosition
* #return the {#link SongDetailsJDO} object
*/
public SongDetailsJDO getItemAtPosition(int pPosition) {
return mSongDetailsJDOs.get(pPosition);
}
/**
* Update Song Play status
* #param pStatus the status weather is playing or not
* #param lSongId the song id the playing song
*/
public void updateSongPlayStatus(boolean pStatus, String lSongId) {
mIsSongPlaying = pStatus;
mCurrentSongId = lSongId;
notifyDataSetChanged();
}
}
SongListActivity.java
public class SongsListActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>, SharedPreferences.OnSharedPreferenceChangeListener {
private RecyclerView mRecyclerView;
private SongListAdapter mAdapter;
private ArrayList<SongDetailsJDO> mSongDetailsJDOs;
private TextView mNoSongTV;
private static final int LOADER_ID = 101;
private int REQUEST_CODE = 102;
private static final String TAG = "SongsListActivity";
private SharedPreferences mSharedPreferences;
private SharedPreferences.Editor mPrefEditor;
private SharedPreferences.OnSharedPreferenceChangeListener mOnSharedPreferenceChangeListener;
private FirebaseAnalytics mFirebaseAnalytics;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.rec_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(SongsListActivity.this));
mNoSongTV = (TextView) findViewById(R.id.no_song_tv);
mSongDetailsJDOs = new ArrayList<>();
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
mPrefEditor = mSharedPreferences.edit();
mSharedPreferences.registerOnSharedPreferenceChangeListener(this);
FirebaseApp.initializeApp(this);
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
loadData();
}
private void loadData() {
FirebaseCrash.report(new Exception("OMG An Exception"));
boolean lIsAppLoadingFirstTime = mSharedPreferences.getBoolean(getString(R.string.is_app_loading_first_time), true);
if (lIsAppLoadingFirstTime) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
} else {
mPrefEditor.putBoolean(getString(R.string.is_app_loading_first_time), false);
mPrefEditor.apply();
new LoadDataToDbBackground().execute();
// TODO: Create Loader here
}
} else {
loadDataToRecyclerView();
if (mSharedPreferences.getBoolean(getString(R.string.is_song_playing), false)) {
// TODO: Create Loader here
SongDetailsJDO lJDO = getSongJDO(mSharedPreferences.getString(getString(R.string.song_id), ""));
startActivityForResult(new Intent(SongsListActivity.this, PlayerActivity.class)
.putExtra(getString(R.string.song_jdo), lJDO), REQUEST_CODE);
}
}
}
private class LoadDataToDbBackground extends AsyncTask<Void, Integer, Void> {
ProgressDialog mProgressDialog;
#Override
protected void onPreExecute() {
mProgressDialog = new ProgressDialog(SongsListActivity.this);
mProgressDialog.setMessage("Please Wait");
mProgressDialog.setTitle("Loading");
mProgressDialog.show();
super.onPreExecute();
}
#Override
protected void onPostExecute(Void aVoid) {
mProgressDialog.dismiss();
super.onPostExecute(aVoid);
}
#Override
protected Void doInBackground(Void... params) {
CommonHelper lHelper = new CommonHelper();
lHelper.loadSongToDB(SongsListActivity.this);
runOnUiThread(new Runnable() {
#Override
public void run() {
loadDataToRecyclerView();
}
});
return null;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == 0) {
boolean lGranted = true;
for (int lResult : grantResults) {
if (lResult == PackageManager.PERMISSION_DENIED)
lGranted = false;
}
if (lGranted)
loadData();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
if (data != null && data.getExtras() != null && resultCode == PlayerActivity.RESULT_CODE) {
//if data changed reload the recyclerView
if (data.getBooleanExtra(getString(R.string.is_data_changed), false)) {
mSongDetailsJDOs = new SongDetailTable(this).getAllSongs();
mAdapter.swapData(mSongDetailsJDOs);
}
}
}
// updateCurrentSongIndication();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater lMenuInflater = getMenuInflater();
lMenuInflater.inflate(R.menu.menu_song_list, menu);
SearchManager lSearchManager = (SearchManager) getSystemService(SEARCH_SERVICE);
SearchView lSearchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
lSearchView.setSearchableInfo(lSearchManager.getSearchableInfo(getComponentName()));
lSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
filterRecView(newText);
return true;
}
});
return true;
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(this, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, MediaStore.Audio.Media.TITLE + " ASC");
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
ArrayList<SongDetailsJDO> lSongDetailsNew = new ArrayList<>();
if (data.moveToFirst()) {
do {
lSongDetailsNew.add(new SongDetailsJDO(data.getString(data.getColumnIndex(MediaStore.Audio.Media.TITLE)),
data.getString(data.getColumnIndex(MediaStore.Audio.Media.ALBUM)),
data.getString(data.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID)),
data.getString(data.getColumnIndex(MediaStore.Audio.Media._ID)),
data.getInt(data.getColumnIndex(MediaStore.Audio.Media.DURATION)), 0));
} while (data.moveToNext());
}
compareDataAndMakeChangesToDB(lSongDetailsNew);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
#Override
protected void onResume() {
super.onResume();
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
Log.d(TAG, "onWindowFocusChanged: ");
updateCurrentSongIndication();
}
private void updateCurrentSongIndication() {
if (mSharedPreferences.getBoolean(getString(R.string.is_song_playing), false)) {
mAdapter.updateSongPlayStatus(true, mSharedPreferences.getString(getString(R.string.song_id), ""));
mRecyclerView.smoothScrollToPosition(getPositionOfSongId(mSharedPreferences.getString(getString(R.string.song_id), "")));
} else {
if(mAdapter!=null)
mAdapter.updateSongPlayStatus(false, "-1");
}
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
updateCurrentSongIndication();
}
private void compareDataAndMakeChangesToDB(ArrayList<SongDetailsJDO> pSongDetailsNew) {
Log.d(TAG, "compareDataAndMakeChangesToDB: Called ============");
ArrayList<String> lSongIdsToBeDeleted = new ArrayList<>();
for (SongDetailsJDO lSongDetailsJDO : mSongDetailsJDOs) {
lSongIdsToBeDeleted.add(lSongDetailsJDO.getSongId());
}
ArrayList<SongDetailsJDO> lNewSongsToBeAdded = new ArrayList<>();
for (SongDetailsJDO lSongDetailsJDO : pSongDetailsNew) {
if (lSongIdsToBeDeleted.contains(lSongDetailsJDO.getSongId())) {
lSongIdsToBeDeleted.remove(lSongDetailsJDO.getSongId());
} else
lNewSongsToBeAdded.add(lSongDetailsJDO);
}
if (lSongIdsToBeDeleted.size() > 0 || lNewSongsToBeAdded.size() > 0) {
SongDetailTable lSongDetailTable = new SongDetailTable(this);
lSongDetailTable.removeSongsForIds(lSongIdsToBeDeleted);
lSongDetailTable.insertSongs(lNewSongsToBeAdded);
loadDataToRecyclerView();
//
// SongPlayerService lSongPlayerService = SongPlayerService.getRunningInstance();
// if (lSongPlayerService != null)
// lSongPlayerService.dataChanged();
}
}
public void onFavClick(View pView) {
//Firebase Logging
Bundle lBundle = new Bundle();
lBundle.putString(FirebaseAnalytics.Param.ITEM_CATEGORY,"Favourite Clicked");
mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.VIEW_ITEM,lBundle);
int lPosition = mRecyclerView.getChildLayoutPosition((View) pView.getParent());
SongDetailsJDO lSongDetailsJDO = mAdapter.getItemAtPosition(lPosition);
String lSongId = lSongDetailsJDO.getSongId();
SongDetailTable lSongDetailTable = new SongDetailTable(this);
int lNewFavStatus = lSongDetailsJDO.getFavouriteStatus() == 0 ? 1 : 0;
lSongDetailTable.setFavouriteStatus(lSongId, lNewFavStatus);
mAdapter.favChanged(lPosition, lNewFavStatus);
SongPlayerService mSongPlayerService = SongPlayerService.getRunningInstance();
if (mSongPlayerService != null)
mSongPlayerService.favChanged(lPosition, lNewFavStatus);
}
public void onRowClick(View pView) {
int lPosition = mRecyclerView.getChildLayoutPosition(pView);
SongDetailsJDO lJDO = mAdapter.getItemAtPosition(lPosition);
startActivityForResult(new Intent(SongsListActivity.this, PlayerActivity.class)
.putExtra(getString(R.string.song_jdo), lJDO), REQUEST_CODE);
overridePendingTransition(R.anim.from_right, R.anim.scale_down);
}
private SongDetailsJDO getSongJDO(String pSongId) {
SongDetailsJDO lJDO = null;
for (SongDetailsJDO lSongDetailsJDO : mSongDetailsJDOs) {
if (lSongDetailsJDO.getSongId().equals(pSongId)) {
lJDO = lSongDetailsJDO;
break;
}
}
return lJDO;
}
private void filterRecView(String pText) {
if (pText != null) {
if (pText.equals("")) {
mAdapter.swapData(mSongDetailsJDOs);
toggleVisibilityForNoResult(mSongDetailsJDOs.size(), pText);
} else {
ArrayList<SongDetailsJDO> lSongDetailsJDOs = new ArrayList<>();
pText = pText.toLowerCase();
for (SongDetailsJDO lDetailsJDO : mSongDetailsJDOs) {
if (lDetailsJDO.getTitle().toLowerCase().contains(pText) || lDetailsJDO.getAlbumName() != null && lDetailsJDO.getAlbumName().toLowerCase().contains(pText))
lSongDetailsJDOs.add(lDetailsJDO);
}
toggleVisibilityForNoResult(lSongDetailsJDOs.size(), pText);
mAdapter.swapData(lSongDetailsJDOs);
}
}
}
public void toggleVisibilityForNoResult(int pNumberOfSongs, String query) {
if (pNumberOfSongs == 0) {
mNoSongTV.setVisibility(View.VISIBLE);
mNoSongTV.setText(getString(R.string.nosong) + " " + query);
} else
mNoSongTV.setVisibility(View.INVISIBLE);
}
public void loadDataToRecyclerView() {
//Loading data to RecyclerView
mSongDetailsJDOs = new SongDetailTable(this).getAllSongs();
mAdapter = new SongListAdapter(SongsListActivity.this, mSongDetailsJDOs);
mRecyclerView.setAdapter(mAdapter);
}
public int getPositionOfSongId(String pSongId) {
int lPostion = -1;
for (int i = 0; i < mSongDetailsJDOs.size(); i++) {
if (mSongDetailsJDOs.get(i).getSongId().equals(pSongId)) {
lPostion = i;
break;
}
}
return lPostion;
}
}
Looking at your problem its not possible to tell exact cause of an issue.
But still i will give some hint over issue.
Check your code inside
mSongDetailsJDOs.size(); what is size of the list, it should be > 0. If not then check inside your activity how you are passing list.
#Override
public int getItemCount() {
if (mSongDetailsJDOs != null)
return mSongDetailsJDOs.size();
else
return 0;
}
If above list is > 0 then check it inside onBindViewHolder() that you are getting position one by one and try to render one item a time.
let me know if above works for you.

RecyclerView filtering updates recycler view error

I have a recycler view in which I display phone contacts. You can select or deselect a contact in the list thanks to a checkbox. The recycler view is displayed on an activity. Navigating to that activity, I transfer all contacts that have been selected before and when I'm displaying the list, I compare the phone contacts to the selected ones in order to select them by default in the list. So I have two lists passed to the adapter: phone contacts list and selected contacts list. I let the user filter the contacts list by display name so I bind a TextWatcher event on the EditText, which reload the recyclerview after the text has changed. But the problem is when the user starts to filter, the selected contacts list is being populated from nowhere and I got all the phone contacts in the selected contacts list.... Very strange...
Here is the adapter:
public class ContactsChooserAdapter extends RecyclerView.Adapter<ContactChooserViewHolder> {
private ArrayList<Contact> mContacts;
private ArrayList<Contact> mSelectedContacts;
private OnContactSelectionListener mContactListener;
public ContactsChooserAdapter(ArrayList<Contact> contacts, ArrayList<Contact> selectedContacts)
{
mContacts = contacts;
mSelectedContacts = selectedContacts;
}
public void setOnContactSelectionListener(OnContactSelectionListener listener)
{
mContactListener = listener;
}
#Override
public ContactChooserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.contacts_chooser_list_item, parent, false);
ContactChooserViewHolder holder = new ContactChooserViewHolder(v);
return holder;
}
#Override
public void onBindViewHolder(ContactChooserViewHolder holder, int position) {
Contact contact = getContacts().get(position);
if(isAlreadySelected(contact)){
holder.mChoosed.setChecked(true);
}else{
holder.mChoosed.setChecked(false);
}
holder.mContactDisplayName.setText(contact.getDisplayName());
holder.mContactPhoneNumber.setText(contact.getPhoneNumbers().get(0));
if(mContactListener != null) {
holder.bind(contact, mContactListener);
}
}
#Override
public int getItemCount() {
return getContacts().size();
}
/**
* Method which allows to check whenever a contact is already selected in a list or not.
* #param contact
* #return
*/
private boolean isAlreadySelected(Contact contact){
boolean alreadySelected = false;
if(getAlreadySelectedContacts() != null){
System.out.println("ALready selected contact list: "+ getAlreadySelectedContacts().size());
for(Contact c : getAlreadySelectedContacts()){
if(c.getId() == contact.getId()){
alreadySelected = true;
break;
}
}
}
return alreadySelected;
}
public ArrayList<Contact> getContacts() {
return mContacts;
}
public void setContacts(ArrayList<Contact> mContacts) {
this.mContacts = mContacts;
}
public ArrayList<Contact> getAlreadySelectedContacts() {
return mSelectedContacts;
}
public void setAlreadySelectedContacts(ArrayList<Contact> selectedContacts) {
this.mSelectedContacts = selectedContacts;
}
}
Here is the activity:
public class ContactsActivity extends AppCompatActivity {
private ArrayList<Contact> mSelectedContacts;
private ArrayList<Contact> mPhoneContacts;
private RecyclerView mContactsList;
private BatifyTextViewBold mContactsNbLabel;
private BatifyEditText mSearchEditText;
private ContactsChooserAdapter mContactsChooserAdapter;
private LinearLayoutManager mLinearLayoutManager;
private RelativeLayout mCancelBtn;
private RelativeLayout mFinishBtn;
private ImageView mSearchIcon;
private RelativeLayout mListHeader;
private RelativeLayout mSearchLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contacts);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = this.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.setStatusBarColor(ContextCompat.getColor(this, R.color.batifyGreen));
}
Bundle bundle = getIntent().getExtras();
ArrayList<Contact> transmittedContacts = bundle.getParcelableArrayList(GlobalVariables.CONTACTS_SELECTED_CONTACTS_LABEL);
mSelectedContacts = new ArrayList<>();
if(transmittedContacts != null) {
mSelectedContacts.addAll(transmittedContacts);
}
mContactsList = (RecyclerView)findViewById(R.id.contactsList);
mContactsNbLabel = (BatifyTextViewBold)findViewById(R.id.contactNbSelectedTv);
if(getSelectedContacts() == null){
mContactsNbLabel.setText("0 contact ");
}else{
mContactsNbLabel.setText(getSelectedContacts().size() + (getSelectedContacts().size() > 1 ? " contacts " : " contact "));
}
mFinishBtn = (RelativeLayout)findViewById(R.id.finishContactsBtn);
mFinishBtn.setOnClickListener(finishChoosingContactsListener);
mCancelBtn = (RelativeLayout)findViewById(R.id.cancelContactsBtn);
mCancelBtn.setOnClickListener(cancelChoosingContactsListener);
mSearchIcon = (ImageView)findViewById(R.id.searchBtn);
mSearchIcon.setOnClickListener(searchListener);
mListHeader = (RelativeLayout)findViewById(R.id.listHeader);
mListHeader.setVisibility(View.VISIBLE);
mSearchLayout = (RelativeLayout)findViewById(R.id.searchLayout);
mSearchLayout.setVisibility(View.GONE);
mSearchEditText = (BatifyEditText)findViewById(R.id.searchContactsEditText);
mSearchEditText.addTextChangedListener(searchViewWatcher);
requestPermissionForContactsAndProcess();
}
/**
* Method that requests the permission to access contacts.
*/
public void requestPermissionForContactsAndProcess() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED)
{
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CONTACTS)) {
Tools.showPopUpCallBack(this, "Information", getString(R.string.contactRationalMessage), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE)
{
requestPermissionForContactsAndProcess();
}
}
});
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, GlobalVariables.CONTACTS_PERMISSIONS);
}
}else{
getAllContactsAndDisplay();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case GlobalVariables.CONTACTS_PERMISSIONS: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getAllContactsAndDisplay();
}
return;
}
}
}
/**
* Method which allows to display a contacts list
*/
public void displayContactList(){
mContactsChooserAdapter = new ContactsChooserAdapter(getPhoneContacts(), getSelectedContacts());
mContactsChooserAdapter.setOnContactSelectionListener(contactSelectionListener);
mLinearLayoutManager = new LinearLayoutManager(this);
mContactsList.setLayoutManager(mLinearLayoutManager);
mContactsList.setAdapter(mContactsChooserAdapter);
}
/**
* Method that will retrieve all contacts.
*/
private void getAllContactsAndDisplay()
{
mPhoneContacts = new ArrayList<>();
Contact contact;
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
if (hasPhoneNumber > 0) {
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
contact = new Contact();
contact.setId(Integer.parseInt(id));
contact.setDisplayName(displayName);
Cursor phoneCursor = contentResolver.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id},
null);
if (phoneCursor.moveToNext()) {
String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contact.getPhoneNumbers().add(phoneNumber);
}
phoneCursor.close();
getPhoneContacts().add(contact);
}
}
}
displayContactList();
}
/**
* Method which allow to finish and close the activity. It returns a result.
*/
public void finishedChoosingContacts()
{
Intent intent= new Intent();
intent.putParcelableArrayListExtra(GlobalVariables.CONTACTS_SELECTED_CONTACTS_LABEL, getSelectedContacts());
setResult(Activity.RESULT_OK, intent);
finish();
}
/**
* Listener which allows to select and deselect a contact in a list.
*/
private OnContactSelectionListener contactSelectionListener = new OnContactSelectionListener() {
#Override
public void onContactSelected(Contact contact) {
if(getSelectedContacts() == null){
setSelectedContacts(new ArrayList<Contact>());
}
getSelectedContacts().add(contact);
mContactsNbLabel.setText(getSelectedContacts().size() + (getSelectedContacts().size() > 1 ? " contacts " : " contact "));
}
#Override
public void onContactDeSelected(Contact contact) {
int indexToDelete = -1;
for(Contact c : getSelectedContacts()){
if(c.getId() == contact.getId()){
indexToDelete = getSelectedContacts().indexOf(c);
break;
}
}
if(indexToDelete > -1) {
getSelectedContacts().remove(indexToDelete);
mContactsNbLabel.setText(getSelectedContacts().size() + (getSelectedContacts().size() > 1 ? " contacts " : " contact "));
}
}
};
/**
* Listener which is fired when the search edit text value is changing.
*/
private TextWatcher searchViewWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
filterListAndUpdate(s.toString());
}
};
/**
* method used to filter and update the list
* #param searchedValue
*/
private void filterListAndUpdate(String searchedValue)
{
ArrayList<Contact> associatedSearch = new ArrayList<>();
if(!"".equals(searchedValue) && searchedValue != null) {
for (Contact c : getPhoneContacts()) {
if (c.getDisplayName().toUpperCase().startsWith(searchedValue.toUpperCase())) {
associatedSearch.add(c);
}
}
((ContactsChooserAdapter)mContactsList.getAdapter()).setContacts(associatedSearch);
}else{
((ContactsChooserAdapter)mContactsList.getAdapter()).setContacts(getPhoneContacts());
}
mContactsList.getAdapter().notifyDataSetChanged();
}
/**
* Listener that allows to fire the search listener.
*/
private View.OnClickListener searchListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
mListHeader.setVisibility(View.GONE);
mSearchLayout.setVisibility(View.VISIBLE);
}
};
/**
* Listener which is fired when the user cancels the contacts selection.
*/
private View.OnClickListener cancelChoosingContactsListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
};
/**
* Listener which id fired when the user finishes selecting contacts.
*/
private View.OnClickListener finishChoosingContactsListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
finishedChoosingContacts();
}
};
public ArrayList<Contact> getSelectedContacts() {
return mSelectedContacts;
}
public void setSelectedContacts(ArrayList<Contact> mSelectedContacts) {
this.mSelectedContacts = mSelectedContacts;
}
public ArrayList<Contact> getPhoneContacts() {
return mPhoneContacts;
}
}

Categories

Resources