I have implemented gridview in recyclerview to display image and videos with thumbnails.
I have used following code to fetch images in onBindView method
Getting images thumbnails using below code:
bitmap = MediaStore.Images.Thumbnails.getThumbnail(context
.getApplicationContext().getContentResolver(), item.getImgId(),
MediaStore.Images.Thumbnails.MICRO_KIND, null);
Getting video thumbnails using below code:
bitmap = MediaStore.Video.Thumbnails.getThumbnail(context
.getApplicationContext().getContentResolver(), item.getImgId(),
MediaStore.Images.Thumbnails.MICRO_KIND, null);
but every time i scroll view sticks(it takes some time to scroll down or up). i think it is because i am loading thumbnails in onBindView method.
help me improve this code so that it can be scrolled smoothly.
or any API to do it easily.
Put below code into the onCreate:
imageAdapter = new ImageAdapter();
imageAdapter.initialize();
and here is the Adapter for fetching images and video from the local storage check it out:
public class ImageAdapter extends BaseAdapter {
private LayoutInflater mInflater;
public ArrayList<ImageItem> images = new ArrayList<ImageItem>();
public ImageAdapter() {
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void initialize() {
images.clear();
final String[] columns = {MediaStore.Images.Thumbnails._ID};
final String orderBy = MediaStore.Images.Media._ID;
Cursor imagecursor = managedQuery(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns,
null, null, orderBy);
int int_position = 0;
Uri uri;
Cursor cursor;
int column_index_data, column_index_folder_name, column_id, thum;
String absolutePathOfImage = null;
uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.MediaColumns.DATA, MediaStore.Video.Media.BUCKET_DISPLAY_NAME, MediaStore.Video.Media._ID, MediaStore.Video.Thumbnails.DATA};
cursor = getApplicationContext().getContentResolver().query(uri, projection, null, null, orderBy + " DESC");
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
column_index_folder_name = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_DISPLAY_NAME);
column_id = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);
thum = cursor.getColumnIndexOrThrow(MediaStore.Video.Thumbnails.DATA);
while (cursor.moveToNext()) {
int id = cursor.getColumnIndex(MediaStore.Video.Media._ID);
absolutePathOfImage = cursor.getString(column_index_data);
Log.e("Column", absolutePathOfImage);
Log.e("Folder", cursor.getString(column_index_folder_name));
Log.e("column_id", cursor.getString(column_id));
Log.e("thum", cursor.getString(thum));
ImageItem obj_model = new ImageItem();
obj_model.id = id;
obj_model.thumb = cursor.getString(thum);
images.add(obj_model);
}
if (imagecursor != null) {
int image_column_index = imagecursor
.getColumnIndex(MediaStore.Images.Media._ID);
int count = imagecursor.getCount();
for (int i = 0; i < count; i++) {
imagecursor.moveToPosition(i);
int id = imagecursor.getInt(image_column_index);
ImageItem imageItem = new ImageItem();
imageItem.id = id;
lastId = id;
imageItem.img = MediaStore.Images.Thumbnails.getThumbnail(
getApplicationContext().getContentResolver(), id,
MediaStore.Images.Thumbnails.MICRO_KIND, null);
images.add(imageItem);
}
imagecursor.close();
}
notifyDataSetChanged();
}
public void checkForNewImages() {
//Here we'll only check for newer images
final String[] columns = {MediaStore.Images.Thumbnails._ID};
final String orderBy = MediaStore.Images.Media._ID;
Cursor imagecursor = managedQuery(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns,
MediaStore.Images.Media._ID + " > " + lastId, null, orderBy);
int image_column_index = imagecursor
.getColumnIndex(MediaStore.Images.Media._ID);
int count = imagecursor.getCount();
for (int i = 0; i < count; i++) {
imagecursor.moveToPosition(i);
int id = imagecursor.getInt(image_column_index);
ImageItem imageItem = new ImageItem();
imageItem.id = id;
lastId = id;
imageItem.img = MediaStore.Images.Thumbnails.getThumbnail(
getApplicationContext().getContentResolver(), id,
MediaStore.Images.Thumbnails.MICRO_KIND, null);
imageItem.selection = true; //newly added item will be selected by default
images.add(imageItem);
}
imagecursor.close();
notifyDataSetChanged();
}
public int getCount() {
return images.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, final ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.galleryitem1, null);
holder.imageview = (ImageView) convertView
.findViewById(R.id.thumbImage);
holder.ivVideoIcon = (ImageView) convertView
.findViewById(R.id.ivVideoIcon);
holder.checkbox = (CheckBox) convertView
.findViewById(R.id.itemCheckBox);
holder.pbImageLoad = (ProgressBar) convertView
.findViewById(R.id.pbImageLoad);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ImageItem item = images.get(position);
holder.checkbox.setId(position);
holder.imageview.setId(position);
if (item.thumb != null) {
/*Picasso.with(AndroidCustomGalleryActivity.this)
.load("file" + item.thumb)
.into(holder.imageview);*/
holder.ivVideoIcon.setVisibility(View.VISIBLE);
Glide.with(AndroidCustomGalleryActivity.this).load(Uri.fromFile(new File(item.thumb)))
.listener(new RequestListener<Uri, GlideDrawable>() {
#Override
public boolean onException(Exception e, Uri model, Target<GlideDrawable> target, boolean isFirstResource) {
holder.pbImageLoad.setVisibility(View.GONE);
return false;
}
#Override
public boolean onResourceReady(GlideDrawable resource, Uri model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
holder.pbImageLoad.setVisibility(View.GONE);
return false;
}
})
.skipMemoryCache(false)
.into(holder.imageview);
} else {
// holder.imageview.setImageBitmap(item.img);
if (item.img != null) {
holder.ivVideoIcon.setVisibility(View.GONE);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
item.img.compress(Bitmap.CompressFormat.PNG, 100, stream);
Glide.with(AndroidCustomGalleryActivity.this).load(stream.toByteArray()).asBitmap().listener(new RequestListener<byte[], Bitmap>() {
#Override
public boolean onException(Exception e, byte[] model, Target<Bitmap> target, boolean isFirstResource) {
holder.pbImageLoad.setVisibility(View.GONE);
return false;
}
#Override
public boolean onResourceReady(Bitmap resource, byte[] model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
holder.pbImageLoad.setVisibility(View.GONE);
return false;
}
}).skipMemoryCache(false).into(holder.imageview);
}
}
holder.checkbox.setChecked(item.selection);
return convertView;
}
}
class ViewHolder {
ImageView imageview;
ImageView ivVideoIcon;
CheckBox checkbox;
ProgressBar pbImageLoad;
}
class ImageItem {
boolean selection;
int id;
Bitmap img;
String thumb;
}
Related
I have a problem with retrieving albumArt and setting that art to ImageView using AsyncTask in cursor adapter.
When I open my app it looks like this:
Then I scroll down the list and everything is fine(but also if I scroll list not very fast):
Then I scroll list back to the very beggining(not fast) and it looks fine as well:
Probably I do something wrong, I think, so I have question:
Is it possible somehow to solve that problem, I already tried a lot of different ways on how to implement AsyncTask and make it works fine, but in the end of the day it looks always the same.
Below is code for cursor adapter:
public class AllSongsCursorAdapter extends CursorAdapter {
public AllSongsCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
public boolean isCheckBoxVisible;
private AddToFavouritesArray favouritesArray = AddToFavouritesArray.getInstance();
private static class ViewHolder {
CheckBox checkBox;
TextView title;
TextView artist;
ImageView albumArt;
private ViewHolder(View view) {
checkBox = (CheckBox) view.findViewById(R.id.favouritesCheckBox);
title = (TextView) view.findViewById(R.id.title);
artist = (TextView) view.findViewById(R.id.artist);
albumArt = (ImageView) view.findViewById(R.id.albumArt);
}
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
View view = LayoutInflater.from(context).inflate(R.layout.song_item, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(view);
view.setTag(viewHolder);
return view;
}
#Override
public void bindView(View view, Context context, final Cursor cursor) {
final ViewHolder viewHolder = (ViewHolder) view.getTag();
if (isCheckBoxVisible) {
viewHolder.checkBox.setVisibility(View.VISIBLE);
} else {
viewHolder.checkBox.setVisibility(View.GONE);
}
final int position = cursor.getPosition();
viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b) {
favouritesArray.integerArray.add(position);
} else {
favouritesArray.integerArray.remove(Integer.valueOf(position));
}
}
});
int songTitle = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
int songArtist = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);
String currentTitle = cursor.getString(songTitle);
String currentArtist = cursor.getString(songArtist);
viewHolder.title.setText(currentTitle);
viewHolder.artist.setText(currentArtist);
//__________________________ALBUM_ART_______________________________________________________
viewHolder.albumArt.setTag(cursor.getPosition());
new AsyncTask<ViewHolder, Void, Bitmap>(){
private ViewHolder viewHolder;
#Override
protected Bitmap doInBackground(ViewHolder... viewHolders) {
viewHolder = viewHolders[0];
int id = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
long songId = cursor.getLong(id);
Bitmap albumArt = getAlbumId(context, songId);
return albumArt;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if(bitmap != null) {
viewHolder.albumArt.setImageBitmap(bitmap);
}else{
viewHolder.albumArt.setImageResource(R.drawable.placeholder);
}
}
}.execute(viewHolder);
}
private Bitmap getAlbumId(Context context, long id) {
Bitmap albumArt = null;
String selection = MediaStore.Audio.Media._ID + " = " + id + "";
Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[]{
MediaStore.Audio.Media._ID, MediaStore.Audio.Media.ALBUM_ID},
selection, null, null);
if (cursor.moveToFirst()) {
long albumId = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
albumArt = getAlbumArt(context, albumId);
}
cursor.close();
return albumArt;
}
private Bitmap getAlbumArt(Context context, long albumId) {
Bitmap albumArt = null;
String selection = MediaStore.Audio.Albums._ID + " = " + albumId + "";
Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, null, selection, null, null);
if (cursor.moveToFirst()) {
int art = cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART);
String currentArt = cursor.getString(art);
albumArt = BitmapFactory.decodeFile(currentArt);
}
cursor.close();
return albumArt;
}
}
And yes, sure, without AsyncTask everything works fine except scrolling is very slow.
Thank you in advance!
EDIT
In the end of the day, that's how it works. Thank you very much # Orest Savchak, my up-vote and acceptance for your answer. Thanks a lot.
//__________________________ALBUM_ART_______________________________________________________
int id = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
long songId = cursor.getLong(id);
String string = getAlbumArtPath(context, songId);
if(string!=null) {
Picasso.with(context)
.load(new File(string))
.into(viewHolder.albumArt);
}else{
viewHolder.albumArt.setImageResource(R.drawable.placeholder);
}
}
private String getAlbumArtPath(Context context, long id) {
String selection = MediaStore.Audio.Media._ID + " = " + id + "";
Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[]{
MediaStore.Audio.Media._ID, MediaStore.Audio.Media.ALBUM_ID},
selection, null, null);
if (cursor.moveToFirst()) {
long albumId = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
return getAlbumArt(context, albumId);
}
cursor.close();
return null;
}
private String getAlbumArt(Context context, long albumId) {
String selection = MediaStore.Audio.Albums._ID + " = " + albumId + "";
Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, null, selection, null, null);
if (cursor.moveToFirst()) {
int art = cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART);
return cursor.getString(art);
}
cursor.close();
return null;
}
You should manage your tasks by yourself. Your views are recycled, so, you have one view for different rows, it causes a problem. Most of project use some libraries, that do it automatically for you - much easier, e.g Picasso
Picasso.with(context).load(new File(getAlbumArtPath(context, songId))).into(viewHolder.albumArt);
private String getAlbumArtPath(Context context, long id) {
String selection = MediaStore.Audio.Media._ID + " = " + id + "";
Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[]{
MediaStore.Audio.Media._ID, MediaStore.Audio.Media.ALBUM_ID},
selection, null, null);
if (cursor.moveToFirst()) {
long albumId = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
return getAlbumArt(context, albumId);
}
cursor.close();
return null;
}
private String getAlbumArt(Context context, long albumId) {
String selection = MediaStore.Audio.Albums._ID + " = " + albumId + "";
Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, null, selection, null, null);
if (cursor.moveToFirst()) {
int art = cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART);
return cursor.getString(art);
}
cursor.close();
return null;
}
I'm retrieving all contacts from both Google accounts and the phone.
I don't understand why pics are right for some and wrong for others.
Thanks a lot advance for any help.
This is my code,
List<AddressBookContact> list = new LinkedList<>();
LongSparseArray<AddressBookContact> array = new LongSparseArray<>();
String[] projection = {
ContactsContract.Data.MIMETYPE,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.PHOTO_THUMBNAIL_URI,
ContactsContract.CommonDataKinds.Contactables.DATA,
ContactsContract.CommonDataKinds.Contactables.TYPE,
ContactsContract.RawContacts.ACCOUNT_TYPE
};
String selection = ContactsContract.Data.MIMETYPE + " in (?, ?)";
String[] selectionArgs = {
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
};
String sortOrder = ContactsContract.Contacts.SORT_KEY_ALTERNATIVE;
Uri uri = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
uri = ContactsContract.Data.CONTENT_URI;
}
assert uri != null;
Cursor cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
assert cursor != null;
final int idIdx = cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
final int nameIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int picIdx = cursor.getColumnIndex(ContactsContract.Data.PHOTO_THUMBNAIL_URI);
final int dataIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.DATA);
final int typeIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.TYPE);
//final int typeDir = cursor.getColumnIndex(ContactsContract.Directory.ACCOUNT_TYPE);
I loop across the cursor and do some filters to avoid some duplicates
The idea is to gather same contact info under a same contact (object)
while (cursor.moveToNext()) {
long id = cursor.getLong(idIdx);
AddressBookContact addressBookContact = array.get(id);
//if(!cursor.getString(cursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_TYPE)).equals("com.google")){
//lastName = cursor.getString(nameIdx);
if(!lastName.toLowerCase().contains(cursor.getString(nameIdx).toLowerCase())){
if(!cursor.getString(nameIdx).toLowerCase().contains("unsub") && !cursor.getString(nameIdx).toLowerCase().contains("noreply")) {
if (!StringUtils.isEmailValid(cursor.getString(nameIdx).toLowerCase())) {
lastName = cursor.getString(nameIdx);
if (addressBookContact == null) {
addressBookContact = new AddressBookContact(id, cursor.getString(nameIdx), context.getResources());
addressBookContact.setImagepath(cursor.getString(picIdx));
array.put(id, addressBookContact);
list.add(addressBookContact);
addressBookContact.setId(id);
}
int type = cursor.getInt(typeIdx);
String data = cursor.getString(dataIdx);
addressBookContact.addEmail(type, data);
}
}
}
else{
if(addressBookContact != null){
int type = cursor.getInt(typeIdx);
String data = cursor.getString(dataIdx);
addressBookContact.addEmail(type, data);
}
}
//}
}
cursor.close();
return list;
}
Based on this, I create an object Contact which is retrieved within a Viewholder
#Override
public void onBindViewHolder(MyContactListViewHolder holder, int position) {
String imagepath = mainInfo.get(position).getImagepath();
if (imagepath != null && !imagepath.isEmpty()) {
ImageView imageView = (ImageView)holder.itemView.findViewById(R.id.imageview_contact_picture);
imageView.setImageURI(Uri.parse(imagepath));
}
else{
String firstLetter = mainInfo.get(position).getName().substring(0,1).toUpperCase();
TextDrawable drawable = TextDrawable.builder()
.buildRound(firstLetter, 0xff3fbfe8);
ImageView image = (ImageView) holder.itemView.findViewById(R.id.imageview_contact_no_picture);
image.setVisibility(View.VISIBLE);
image.setImageDrawable(drawable);
}
holder.textViewShowName.setText(mainInfo.get(position).getName());
}
Code for MyContactListViewHolder
class MyContactListViewHolder extends RecyclerView.ViewHolder{
ImageView imageViewUserImage;
TextView textViewShowName;
MyContactListViewHolder(View itemView) {
super(itemView);
textViewShowName = (TextView) itemView.findViewById(R.id.textview_contact_name);
imageViewUserImage = (ImageView) itemView.findViewById(R.id.imageview_contact_picture);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MyBottomSheetDialogFragment bottomSheetDialogFragment = MyBottomSheetDialogFragment.newInstance();
Bundle bundle = new Bundle();
bundle.putParcelable("contact", mainInfo.get(getAdapterPosition()));
bottomSheetDialogFragment.setArguments(bundle);
bottomSheetDialogFragment.show(fragmentManager, null);
}
});
}
}
#Override
public MyContactListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.contacts_list_item, parent, false);
return new MyContactListViewHolder(v);
}
Don't use findViewById in the onBindViewHolder method. Do it in MyContactListViewHolder (which you are already doing).
Try the following code,
#Override
public void onBindViewHolder(MyContactListViewHolder holder, int position) {
String imagepath = mainInfo.get(position).getImagepath();
if (imagepath != null && !imagepath.isEmpty()) {
holder.imageViewUserImage.setImageURI(Uri.parse(imagepath));
} else{
String firstLetter = mainInfo.get(position).getName().substring(0,1).toUpperCase();
TextDrawable drawable = TextDrawable.builder().buildRound(firstLetter, 0xff3fbfe8);
holder.imageViewUserImage.setVisibility(View.VISIBLE);
holder.imageViewUserImage.setImageDrawable(drawable);
}
holder.textViewShowName.setText(mainInfo.get(position).getName());
}
I am trying to display video files in listview from folder 'xyz' on sdcard, i have successfully displayed but problem is that it displays all video files stored on sdcard even out of folder 'abc' actually i want only video files stored in folder 'xyz' to be displayed. I am googling since 4 days but didn't find any solution for that. My code is that is showing all videos and working perfectly :
private Cursor videocursor;
private int video_column_index;
ListView videolist;
int count;
String[] thumbColumns = null ;
File videoFiles;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init_phone_video_grid();
#SuppressWarnings("deprecation")
private void init_phone_video_grid() {
System.gc();
String[] proj = { MediaStore.Video.Media._ID,
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.SIZE };
videocursor = managedQuery( MediaStore.Video.Media.EXTERNAL_CONTENT_URI,proj,
null, null,null);
count = videocursor.getCount();
videolist = (ListView) findViewById(R.id.list);
videolist.setAdapter(new VideoAdapter(getApplicationContext()));
videolist.setOnItemClickListener(videogridlistener);
}
private OnItemClickListener videogridlistener = new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position,
long id) {
System.gc();
video_column_index = videocursor
.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
videocursor.moveToPosition(position);
String filename = videocursor.getString(video_column_index);
Intent intent = new Intent(MainActivity.this, ViewVideo.class);
intent.putExtra("videofilename", filename);
startActivity(intent);
}
};
public class VideoAdapter extends BaseAdapter {
private Context vContext;
public VideoAdapter(Context c) {
vContext = c;
}
public int getCount() {
return count;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
System.gc();
ViewHolder holder;
String id = null;
convertView = null;
if (convertView == null) {
convertView = LayoutInflater.from(vContext).inflate(R.layout.listitem, parent, false);
holder = new ViewHolder();
holder.txtTitle = (TextView) convertView.findViewById(R.id.txtTitle);
holder.txtSize = (TextView) convertView.findViewById(R.id.txtSize);
holder.thumbImage = (ImageView) convertView.findViewById(R.id.imgIcon);
video_column_index = videocursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME);
videocursor.moveToPosition(position);
id = videocursor.getString(video_column_index);
video_column_index = videocursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE);
videocursor.moveToPosition(position);
// id += " Size(KB):" + // videocursor.getString(video_column_index);
holder.txtTitle.setText(id);
holder.txtSize.setText(" Size(KB):" + videocursor.getString(video_column_index));
String[] proj = { MediaStore.Video.Media._ID,
MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.DATA };
#SuppressWarnings("deprecation")
Cursor cursor = managedQuery(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, proj,
MediaStore.Video.Media.DISPLAY_NAME + "=?",
new String[] { id }, null);
cursor.moveToFirst();
long ids = cursor.getLong(cursor.getColumnIndex(MediaStore.Video.Media._ID));
ContentResolver crThumb = getContentResolver();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
Bitmap curThumb = MediaStore.Video.Thumbnails.getThumbnail(
crThumb, ids, MediaStore.Video.Thumbnails.MICRO_KIND,
options);
holder.thumbImage.setImageBitmap(curThumb);
curThumb = null;
}
return convertView;
}
}
static class ViewHolder {
TextView txtTitle;
TextView txtSize;
ImageView thumbImage;
}
Try this
public static final String[] VIDEO_PROJECTION = {MediaStore.Video.Media._ID, MediaStore.Video.Media.TITLE,
MediaStore.Video.Media.DATA};
public static final Uri VIDEO_SOURCE_URI = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
Querying the data using the content resolver
CursorLoader cursorLoader = new CursorLoader(getActivity(), VIDEO_SOURCE_URI, VIDEO_PROJECTION, MediaStore.Video.Media.DATA + " like ? ", new String[]{"%FOLDER_NAME%"},
MediaStore.Video.Media.DATA + " COLLATE NOCASE ASC;");
It retrievers all the video files from the FOLDER_NAME. Since there can be one or more folders with a name so it is better to provide absolute path.
I'm trying to create a custom gallery that allows users to pick from all the photos and videos contained on their Android device. I know how to create a gallery of just photos and just videos, but if I want to combine both, how can I do this?
I think the issue comes down to how I create my cursor. To select all videos, I created the cursor this way:
String[] videoParams = {MediaStore.Video.Media._ID,
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.DATE_TAKEN,
MediaStore.Video.Thumbnails.DATA};
videocursor = getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, videoParams, null, null, null);
If I want to query all the media files, not just video, what do I do?
This is what I tried, based off of: Custom Gallery with Images and Videos in android to select multiple items
String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + "=?";
String jpg_mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("jpg");
String png_mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("png");
String mp4_mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("mp4");
String[] selectionArgs = new String[]{jpg_mimeType, png_mimeType, mp4_mimeType};
mediaCursor = getContentResolver().query(MediaStore.Files.getContentUri("internal"), null, selectionMimeType, selectionArgs, MediaStore.Files.FileColumns.DATE_ADDED);
This gives me the error java.lang.IllegalArgumentException: Cannot bind argument at index 3 because the index is out of range. The statement has 1 parameters at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:167)
Perhaps my approach is completely wrong, but I can't find any examples of custom android galleries using both images and videos, which is bizarre to me as this seems like it would be a common thing to create.
Here's all of my code, in case it's helpful:
public class GridViewCompatActivity extends Activity {
GridViewCompat gridView;
private static final String TAG = "GridViewCompatActivity";
Cursor videocursor;
Cursor mediaCursor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_grid_view_compat);
gridView = (GridViewCompat) findViewById(R.id.gridView1);
// NOTE: We are using setChoiceMode, as I said, its a drop-in replacement
gridView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
gridView.setAdapter(new ImageAdapter(getApplicationContext()));
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> view, View arg1, int pos, long id) {
// We need to invalidate all views on 4.x versions
GridViewCompat gridView = (GridViewCompat) view;
gridView.invalidateViews();
}
});
findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
SparseBooleanArray checkArray;
checkArray = gridView.getCheckedItemPositions();
String selectedPos = "Selected positions: ";
int count = checkArray.size();
for (int i = 0; i < count; i++) {
if (checkArray.valueAt(i))
selectedPos += checkArray.keyAt(i) + ",";
}
Intent intent = new Intent();
intent.putExtra("result", selectedPos);
setResult(Activity.RESULT_OK, intent);
finish();
}
});
}
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
Log.d(TAG, "number of media: " + Integer.toString(MediaStore.Files.FileColumns.DATA.length()));
int mediaParams = MediaStore.MediaColumns.DATA.length();
return mediaParams;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new grid view item for each item referenced by the Adapter
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
CheckBox checkBox;
if (convertView == null) {
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
convertView = layoutInflater.inflate(R.layout.grid_view_item, parent, false);
}
imageView = (ImageView) convertView.findViewById(R.id.imageView1);
checkBox = (CheckBox) convertView.findViewById(R.id.checkBox1);
GridViewCompat gvc = (GridViewCompat) parent;
if (gvc.getChoiceMode() == ListView.CHOICE_MODE_MULTIPLE) {
SparseBooleanArray checkArray;
checkArray = gvc.getCheckedItemPositions();
checkBox.setChecked(false);
if (checkArray != null) {
if (checkArray.get(position)) {
checkBox.setChecked(true);
}
}
}
// imageView.setImageResource(mThumbIds[position]);
Bitmap bmThumbnail;
Log.d(TAG, "position: " + position);
mediaCursor = getContentResolver().query(MediaStore.Files.getContentUri("internal"), null, selectionMimeType, selectionArgs, MediaStore.Files.FileColumns.DATE_ADDED);
Log.d(TAG, Integer.toString(mediaCursor.getCount()));
for (int i = 0; i < mediaCursor.getCount(); i++){
mediaCursor.moveToPosition(i);
Boolean isVideo = mediaCursor.getString(mediaCursor.getColumnIndex(MediaStore.Video.Thumbnails.DATA)).length() > 0;
Log.d(TAG, "isVideo: " + isVideo);
String mediaPath = "";
if(isVideo){
mediaPath = mediaCursor.getString(mediaCursor.getColumnIndex(MediaStore.Video.Thumbnails.DATA));
video_paths.add(mediaPath);
}else{
mediaPath = mediaCursor.getString(mediaCursor.getColumnIndex(MediaStore.Images.Media.DATA));
video_paths.add(mediaPath);
}
Log.d(TAG, "mediaPath: " +mediaPath);
}
mediaCursor.moveToPosition(position);
String video_path = mediaCursor.getString(mediaCursor.getColumnIndex(MediaStore.Video.Thumbnails.DATA));
Log.d(TAG, "video_path: " + video_path);
imageView.setImageBitmap(ThumbnailUtils.createVideoThumbnail(video_path, Thumbnails.MICRO_KIND));
return convertView;
}
ArrayList<String> video_paths = new ArrayList<String>();
String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + "=?";
String jpg_mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("jpg");
String png_mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("png");
String mp4_mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("mp4");
String[] selectionArgs = new String[]{jpg_mimeType, png_mimeType, mp4_mimeType};
// String[] videoParams = {MediaStore.Video.Media._ID,
// MediaStore.Video.Media.DATA,
// MediaStore.Video.Media.DATE_TAKEN,
// MediaStore.Video.Thumbnails.DATA};
// }
}
}
public class GalleryFragment extends Fragment
{
private int count;
private Bitmap[] thumbnails;
private boolean[] thumbnailsselection;
private String[] arrPath;
private int[] typeMedia;
private ImageAdapter imageAdapter;
#SuppressLint("NewApi") #Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.gallery_gridview, container, false);
String[] columns = { MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.Files.FileColumns.MEDIA_TYPE,
MediaStore.Files.FileColumns.MIME_TYPE,
MediaStore.Files.FileColumns.TITLE,
};
String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE
+ " OR "
+ MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO;
final String orderBy = MediaStore.Files.FileColumns.DATE_ADDED;
Uri queryUri = MediaStore.Files.getContentUri("external");
#SuppressWarnings("deprecation")
Cursor imagecursor = getActivity().managedQuery(queryUri,
columns,
selection,
null, // Selection args (none).
MediaStore.Files.FileColumns.DATE_ADDED + " DESC" // Sort order.
);
int image_column_index = imagecursor.getColumnIndex(MediaStore.Files.FileColumns._ID);
this.count = imagecursor.getCount();
this.thumbnails = new Bitmap[this.count];
this.arrPath = new String[this.count];
this.typeMedia = new int[this.count];
this.thumbnailsselection = new boolean[this.count];
for (int i = 0; i < this.count; i++) {
imagecursor.moveToPosition(i);
int id = imagecursor.getInt(image_column_index);
int dataColumnIndex = imagecursor.getColumnIndex(MediaStore.Files.FileColumns.DATA);
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inSampleSize = 4;
bmOptions.inPurgeable = true;
int type = imagecursor.getColumnIndex(MediaStore.Files.FileColumns.MEDIA_TYPE);
int t = imagecursor.getInt(type);
if(t == 1)
thumbnails[i] = MediaStore.Images.Thumbnails.getThumbnail(
getActivity().getContentResolver(), id,
MediaStore.Images.Thumbnails.MINI_KIND, bmOptions);
else if(t == 3)
thumbnails[i] = MediaStore.Video.Thumbnails.getThumbnail(
getActivity().getContentResolver(), id,
MediaStore.Video.Thumbnails.MINI_KIND, bmOptions);
arrPath[i]= imagecursor.getString(dataColumnIndex);
typeMedia[i] = imagecursor.getInt(type);
}
GridView imagegrid = (GridView) v.findViewById(R.id.PhoneImageGrid);
Button reSizeGallery = (Button) v.findViewById(R.id.reSizeGallery);
imageAdapter = new ImageAdapter();
imagegrid.setAdapter(imageAdapter);
imagecursor.close();
reSizeGallery.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ChatViewerAdapter.ScreenResize(getActivity());
}
});
return v;//super.onCreateView(inflater, container, savedInstanceState);
}
public class ImageAdapter extends BaseAdapter {
private LayoutInflater mInflater;
public ImageAdapter() {
mInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return count;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
#SuppressLint("NewApi") public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
Display display = getActivity().getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(
R.layout.gallery_view, null);
holder.imageview = (ImageView) convertView.findViewById(R.id.thumbImage);
holder.videoICON = (ImageView) convertView.findViewById(R.id.videoICON);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.imageview.getLayoutParams().height = height/6;
holder.imageview.getLayoutParams().width = width/4;
holder.imageview.setId(position);
if(typeMedia[position] == 1)
holder.videoICON.setVisibility(View.GONE);
else if(typeMedia[position] == 3)
holder.videoICON.setVisibility(View.VISIBLE);
holder.imageview.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
int id = v.getId();
Display display = ((WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int height = display.getHeight();
final int height_half = (int) (height/2.5);
RelativeLayout fragment_layout = (RelativeLayout) getActivity().findViewById(R.id.fragment_gallery);
fragment_layout.setVisibility(View.VISIBLE);
fragment_layout.getLayoutParams().height = height_half;
GalleryImageChooseFragment f_img_choose =new GalleryImageChooseFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Bundle args = new Bundle();
args.putString("PATH", arrPath[id]);
f_img_choose.setArguments(args);
ft.show(f_img_choose);
ft.replace(R.id.fragment_tattle, f_img_choose);
ft.addToBackStack("f_img_choose");
ft.commit();
}
});
holder.imageview.setImageBitmap(thumbnails[position]);
holder.id = position;
return convertView;
}
}
class ViewHolder {
ImageView imageview;
ImageView videoICON;
int id;
}
}
Download source code form here (Get all videos from gallery android).
public void fn_video() {
int int_position = 0;
Uri uri;
Cursor cursor;
int column_index_data, column_index_folder_name,column_id,thum;
String absolutePathOfImage = null;
uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.MediaColumns.DATA, MediaStore.Video.Media.BUCKET_DISPLAY_NAME,MediaStore.Video.Media._ID,MediaStore.Video.Thumbnails.DATA};
final String orderBy = MediaStore.Images.Media.DATE_TAKEN;
cursor = getApplicationContext().getContentResolver().query(uri, projection, null, null, orderBy + " DESC");
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
column_index_folder_name = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_DISPLAY_NAME);
column_id = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);
thum = cursor.getColumnIndexOrThrow(MediaStore.Video.Thumbnails.DATA);
while (cursor.moveToNext()) {
absolutePathOfImage = cursor.getString(column_index_data);
Log.e("Column", absolutePathOfImage);
Log.e("Folder", cursor.getString(column_index_folder_name));
Log.e("column_id", cursor.getString(column_id));
Log.e("thum", cursor.getString(thum));
Model_Video obj_model = new Model_Video();
obj_model.setBoolean_selected(false);
obj_model.setStr_path(absolutePathOfImage);
obj_model.setStr_thumb(cursor.getString(thum));
al_video.add(obj_model);
}
}
This function will return arraylist of gallery images and videos in descending order. Just pass this function to adapter and show gallery stuff in recyclerview in kotlin.
#SuppressLint("Range")
fun getAllGalleryMedia(): ArrayList<Media> {
val result = ArrayList<Media>()
val projection = arrayOf(
MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.Files.FileColumns.DISPLAY_NAME,
MediaStore.Files.FileColumns.MEDIA_TYPE,
MediaStore.Files.FileColumns.MIME_TYPE,
MediaStore.Files.FileColumns.TITLE
)
val selection = (MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE
+ " OR "
+ MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO)
val queryUri = MediaStore.Files.getContentUri("external")
Handler(Looper.getMainLooper()).post {
val cursorLoader = CursorLoader(
context,
queryUri,
projection,
selection,
null,
MediaStore.Files.FileColumns.DATE_ADDED + " DESC"
)
val cursor: Cursor? = cursorLoader.loadInBackground()
if (cursor != null) {
while (cursor.moveToNext()) {
val id = cursor.getLong(cursor.getColumnIndex(MediaStore.Files.FileColumns._ID))
val displayName =
cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.DISPLAY_NAME))
val imagePath =
cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA))
val dateAdded =
cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.DATE_ADDED))
val mimeType =
cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.MIME_TYPE))
result.add(Media(id, displayName, imagePath, dateAdded, mimeType))
}
cursor.close()
}
}
return result
}
This is model class,you can modify according to your needs.
class Media:java.io.Serializable{
var id:Long=0
var displayName:String=""
var imagePath:String=""
var dateAdded:String=""
var mimeType:String=""
var isSelected:Boolean = false
constructor(){
// empty constructor
}
constructor(
id: Long,
displayName: String,
imagePath: String,
dateAdded: String,
mimeType: String
){
this.id = id
this.displayName = displayName
this.imagePath = imagePath
this.dateAdded = dateAdded
this.mimeType = mimeType
}}
Actually I tried with this coding it's working fine.i.e., showing all the images perfectly in emulator but coming to mobile it showing repeatedly the same image. I have attached the adapter class also
File file[] = Environment.getExternalStorageDirectory().listFiles();
String strFile = "";
for (int i = 0; i < file.length; i++) {
strFile += file[i].getAbsolutePath() + " :: ";
System.out.println("\n");
}
Log.i("test", strFile);
String[] img = { MediaStore.Images.Thumbnails._ID };
imagecursor = managedQuery(
MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, img, null,
null, MediaStore.Images.Thumbnails.IMAGE_ID + "");
image_column_index = imagecursor
.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);
count = imagecursor.getCount();
imagegrid = (ListView) findViewById(R.id.PhoneImageGrid);
imagegrid.setAdapter(new ImageAdapter(getApplicationContext()));
imagegrid.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position,
long id) {
System.gc();
String[] proj = { MediaStore.Images.Media.DATA };
actualimagecursor = managedQuery(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, proj,
null, null, null);
actual_image_column_index = actualimagecursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
actualimagecursor.moveToPosition(position);
String i = actualimagecursor
.getString(actual_image_column_index);
System.gc();
Intent intent = new Intent(getApplicationContext(),
ViewImage.class);
intent.putExtra("filename", i);
startActivity(intent);
}
});
}
Adapter Class:
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return count;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
System.gc();
ImageView i = new ImageView(mContext.getApplicationContext());
if (convertView == null) {
imagecursor.moveToPosition(position);
int id = imagecursor.getInt(image_column_index);
i.setImageURI(Uri.withAppendedPath(
MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, ""
+ id));
i.setScaleType(ImageView.ScaleType.CENTER_CROP);
i.setLayoutParams(new GridView.LayoutParams(92, 92));
} else {
i = (ImageView) convertView;
}
return i;