in my application I import the images from mobile database and display this into my application's gridview.I wrote the following code in my activitiy's onCreate() for same..
String[] projection = { MediaStore.Images.Media._ID,};
Cursor mImageCursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, null );
if (mImageCursor != null)
{
mImageCursor.moveToFirst();
for (int i = 0; i < mImageCursor.getCount(); i++)
{
Images im=new Images();
eachImageView=new ImageView(this);
int imageId = mImageCursor.getInt((mImageCursor.getColumnIndex( MediaStore.Images.Media._ID)));
selectedImageUri = Uri.withAppendedPath(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + imageId);
ContentResolver cr = getContentResolver();
Bitmap bm = getScaledImage(selectedImageUri, 2, cr);
im.setBitmap(bm);
eachImageView.setImageBitmap(bm);
im.setImageView(eachImageView);
arrayOfImages.add(im);
mImageCursor.moveToNext();
}
}
But the problem is that it takes too much time when the number of images are more.I heard about the async task to reduce this time but i am confused how to implement it in my code.
please provide me solution.
Thanks in advance..
AsyncTask are used if you want to perform operation without freezing the UI thread.
In your case you could use one. However it seems that you are loading the images when your activity is started so you can use a Loader.
Very good exemple are available in the documentation and DemoApi.
AsyncTask and Loader
Related
I am trying to load images and show them as a gallery in the form of list.
The problem is that I am able to do it from default android gallery, but I don't know how to do t for custom folder. for e.g /Pictures folder. I have been trying, here is the code that I use for default gallery, I want it for some other folder, e.g /Pictures/Col.
public static List<PhotoItem> getAlbumThumbnails(Context context){
final String[] projection = {MediaStore.Images.Thumbnails.DATA, MediaStore.Images.Thumbnails.IMAGE_ID};
Cursor thumbnailsCursor = context.getContentResolver().query( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
projection, // Which columns to return
null, // Return all rows
null,
null);
// Extract the proper column thumbnails
int thumbnailColumnIndex = thumbnailsCursor.getColumnIndex(MediaStore.Images.Thumbnails.DATA);
ArrayList<PhotoItem> result = new ArrayList<PhotoItem>(thumbnailsCursor.getCount());
if (thumbnailsCursor.moveToFirst()) {
do {
// Generate a tiny thumbnail version.
int thumbnailImageID = thumbnailsCursor.getInt(thumbnailColumnIndex);
String thumbnailPath = thumbnailsCursor.getString(thumbnailImageID);
Uri thumbnailUri = Uri.parse(thumbnailPath);
Uri fullImageUri = uriToFullImage(thumbnailsCursor,context);
// Create the list item.
PhotoItem newItem = new PhotoItem(thumbnailUri,fullImageUri);
result.add(newItem);
} while (thumbnailsCursor.moveToNext());
}
thumbnailsCursor.close();
return result;
}
What all should I change here, I tried to change projection, query parameters but failed, new in this field, please help :)
You can custom recent-images library for your purpose. It's very simple and easy to use library.
I am creating a custom image and video gallery just like Whatsapp have to allow user to select multiple image/video,so far i am populating and showing thumbnails on gridview.But the result is,on some devices the images sometimes got shown duplicated and on some they do not.same happens with video gallery also.
I am quering the ID of Images from
MediaStore.images
and get thumbnails using
MediaStore.images.thumbnails.getThumbnail
from obtained IDs
below is my code
final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID };
final String orderBy = MediaStore.Images.Media.DATE_ADDED;
imageCursor = activity.managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null,null, orderBy+" DESC");
int image_column_index = imageCursor.getColumnIndex(MediaStore.Images.Media._ID);
int count = imageCursor.getCount();
thumbnails = new Bitmap[count];
arrPath = new String[count];
Log.d("count ", ""+count);
int i=0;
for ( i= 0; i <count; i++)
{
imageCursor.moveToPosition(i);
int id = imageCursor.getInt(image_column_index);
int dataColumnIndex = imageCursor.getColumnIndex(MediaStore.Images.Media._ID);
thumbnails[i] = MediaStore.Images.Thumbnails.getThumbnail(context.getContentResolver(), id,MediaStore.Images.Thumbnails.MICRO_KIND, null);
arrPath[i]= imageCursor.getString(dataColumnIndex);
}
from android documentation getThumbnail should create thumbnail if it is not available.
one example that produce same issue is MediaStore.Images.Thumbnails.getThumbnail returns wrong thumbnail instead of NULL but that guy hasn't found the solution (question was asked 2 years ago).
Has anybody faced this problem,i have gone through many examples and to add more i am loading cursor in asynctask so populating thubnails should not be a problem for Adroid OS i guess.Is there a solution available for this issue?Its quite frustrating.
I'm not sure if you've found the solution to your problem yet but I had a similar issue. My app was returning thumbnail uri's that didn't point to anything. But a call to ThumbnailUtils.createVideoThumbnail() would fix the reference in the content resolver. I ultimately dropped something like the below into my app:
Bitmap bitmap = Thumbnails.getThumbnail(mActivity.getContentResolver(), videoFile.mId,
Thumbnails.MINI_KIND, null);
if (bitmap == null) {
ThumbnailUtils.createVideoThumbnail(videoFile.mAbsolutePath, Thumbnails.MINI_KIND);
}
Then I told my adapter to update for the element that was affected.
I'm writing an app that removes files that may or may not be listed in any one of the types of media libraries such as music or pictures. While I can use the MediaScannerConnection.scanFile method to add files to the media library there doesn't seem to be any call to notify the service that the file has been removed. Sending it the path of the file that no longer exists doesn't result in the desired behavior either. How should I go about removing items from the library that no longer exist on the Android storage?
I was able to put a method together using bits and pieces from these two questions
What is the String 'volumeName' argument of MediaStore.Audio.Playlists.Members.getContentUri referring to?
How can I refresh MediaStore on Android?
Basically I just run a query on each one of the MediaStore types (Audio, Video and Images) selecting by path and deleting any records I find.
public static void RemoveAllForPaths(String[] paths, Context context)
{
private static final String[] FIELDS = { MediaStore.MediaColumns._ID, MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.TITLE };
if(paths == null || paths.length == 0) return;
String select = "";
for(String path : paths)
{
if(!select.equals("")) select += " OR ";
select += MediaStore.MediaColumns.DATA + "=?";
}
Uri uri;
Cursor ca;
uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
ca = context.getContentResolver().query(uri, FIELDS, select, paths, null);
for(ca.moveToFirst(); !ca.isAfterLast(); ca.moveToNext()){
int id = ca.getInt(ca.getColumnIndex(MediaStore.MediaColumns._ID));
uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
context.getContentResolver().delete(uri, null, null);
}
ca.close();
// More of the same just setting the URI to Video and Images
}
I'm not entirely sure how safe this is to do but it's the only solution I've found so far and some initial testing seems to be working. I invite others to submit other answers if anyone has any further information on this approach or a better method for performing this functionality.
Answer of Spencer Ruport is right, but you don't need to query and open a cursor in order to delete.
So for one file that is music file the code is simple like that:
public void DeleteMP3FromMediaStore( Context context, String path )
{
Uri rootUri = MediaStore.Audio.Media.getContentUriForPath( path );
context.getContentResolver().delete( rootUri,
MediaStore.MediaColumns.DATA + "=?", new String[]{ path } );
}
P.S. I wanted to comment answer of Spencer Ruport but don't have enough reputation yet.
Easy as pie: whenever you add a file, let MediaStore ContentProvider knows about it using
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(fileToAddInMediaStore)));
For deletion: just use
getContentResolver().delete(Uri.fromFile(fileToDeleteFromMediaStore), null, null)
The following works well for me. You can delete or add files using this.
MediaScannerConnection.scanFile(
context,
new String[]{fileToDelete, fileToAdd},
null, null);
The available method is to remove the item from library.
This post is detailed expressed how to add into or remove from the Media Library.
http://androidyue.github.io/blog/2014/01/19/scan-media-files-in-android/ Hopes this could help you.
I have make on demo that list all contact from contact Uri in that I have made custom list view after adding of contact image my listview scrolling is very slow, following is my code.
public Bitmap getProfilepicture(Activity activity, String address)
{
Bitmap bitmap;
Uri personUri = Uri
.withAppendedPath(Phones.CONTENT_FILTER_URL, address);
Cursor phoneCursor = activity.getContentResolver().query(personUri,
PHONE_PROJECTION, null, null, null);
if (phoneCursor.moveToFirst()) {
int indexPersonId = phoneCursor.getColumnIndex(Phones.PERSON_ID);
long personId = phoneCursor.getLong(indexPersonId);
phoneCursor.close();
Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, personId);
bitmap = People.loadContactPhoto(activity, uri, R.drawable.icon,
null);
return bitmap;
}
return null;
}
with the help of method I getting contact photo that i use in my getView method. like
holder.imgViewLogo.setImageBitmap(getProfilepicture(activity,pos));
it's working proper but listview performance is low.
please help me out improve performance of listview.
I suggest moving the image loading to a background task.
From another thread, load all images to memory (or you can do some caching for only part of the list according to what is visible), once an image is ready, update the UI.
The functional behavior will be that at first, some images will not be shown immediately but performance will be much better.
Take a look here
Perhaps caching the data would improve performance? Try adding this to your code:
private static HashMap<String address, Bitmap image> cache = new HashMap<String address, Bitmap image>();
public Bitmap getProfilepicture(Activity activity, String address) {
if (cache.containskey(address) return cache.get(address);
Bitmap bitmap;
.
.
.
bitmap = People.loadContactPhoto(activity, uri, R.drawable.icon,
null);
cache.put(address,bitmap);
return bitmap;
}
This would at least prevent the bitmap from being created every time getView() is called.
Depending on the life of this particular class, you may or may not make the cache static and/or save its state to file for later loading.
you need to load the images asyncronesly.
here is a thread which discusses about this.
Lazy load of images in ListView
and this response has source code mentioned as source links
GitHub: https://github.com/thest1/LazyList
Source: http://open-pim.com/tmp/LazyList.zip
I'm attempting to create a gridview that is loaded with images from a specific folder that resides on an SDCard. The path to the folder is known, ("/sdcard/pictures") , but in the examples I've seen online I am unsure how or where to specify the path to the pictures folder I want to load images from. I have read through dozens of tutorials, even the HelloGridView tutorial at developer.android.com but those tutorials do not teach me what i am seeking.
Every tutorial I have read so far has either:
A) called the images as a Drawable from the /res folder and put them into an array to be loaded, not using the SDCard at all.
B) Accessed all pictures on the SDCard using the MediaStore but not specifying how to set the path to the folder I want to display images form
or
C) Suggested using BitmapFactory, which I haven't the slightest clue how to use.
If I'm going about this in the wrong way, please let me know and direct me toward the proper method to do what I'm trying to do.
OK, after many iterations of trying, I finally have an example that works and I thought I'd share it. My example queries the images MediaStore, then obtains the thumbnail for each image to display in a view. I am loading my images into a Gallery object, but that is not a requirement for this code to work:
Make sure you have a Cursor and int for the column index defined at the class level so that the Gallery's ImageAdapter has access to them:
private Cursor cursor;
private int columnIndex;
First, obtain a cursor of image IDs located in the folder:
Gallery g = (Gallery) findViewById(R.id.gallery);
// request only the image ID to be returned
String[] projection = {MediaStore.Images.Media._ID};
// Create the cursor pointing to the SDCard
cursor = managedQuery( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection,
MediaStore.Images.Media.DATA + " like ? ",
new String[] {"%myimagesfolder%"},
null);
// Get the column index of the image ID
columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
g.setAdapter(new ImageAdapter(this));
Then, in the ImageAdapter for the Gallery, obtain the thumbnail to display:
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i = new ImageView(context);
// Move cursor to current position
cursor.moveToPosition(position);
// Get the current value for the requested column
int imageID = cursor.getInt(columnIndex);
// obtain the image URI
Uri uri = Uri.withAppendedPath( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, Integer.toString(imageID) );
String url = uri.toString();
// Set the content of the image based on the image URI
int originalImageId = Integer.parseInt(url.substring(url.lastIndexOf("/") + 1, url.length()));
Bitmap b = MediaStore.Images.Thumbnails.getThumbnail(getContentResolver(),
originalImageId, MediaStore.Images.Thumbnails.MINI_KIND, null);
i.setImageBitmap(b);
i.setLayoutParams(new Gallery.LayoutParams(150, 100));
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setBackgroundResource(mGalleryItemBackground);
return i;
}
I guess the most important section of this code is the managedQuery that demonstrates how to use MediaStore queries to filter a list of image files in a specific folder.
You need to do a few more steps than the GridView tutorial on developer.android.com. Using the following tutorial
http://developer.android.com/resources/tutorials/views/hello-gridview.html
You'll want to add a method to create ImageView's of the files from your sd card:
Create/add a Vector to your class variables (to hold a list of ImageViews):
private Vector<ImageView> mySDCardImages;
Initialize the vector:
mySDCardImages = new Vector<ImageView>();
Create a method to load images:
List<Integer> drawablesId = new ArrayList<Integer>();
int picIndex=12345;
File sdDir = new File("/sdcard/pictures");
File[] sdDirFiles = sdDir.listFiles();
for(File singleFile : sdDirFiles)
{
ImageView myImageView = new ImageView(context);
myImageView.setImageDrawable(Drawable.createFromPath(singleFile.getAbsolutePath());
myImageView.setId(picIndex);
picIndex++;
drawablesId.add(myImageView.getId());
mySDCardImages.add(myImageView);
}
mThumbIds = (Integer[])drawablesId.toArray(new Integer[0]);
Then down in your ImageAdapter method, change
imageView.setImageResource(mThumbIds[position]);
to
imageView.setImageDrawable(mySDCardImages.get(position).getDrawable());
Remove from the ImageAdapter the initialization of mThumbIds. (it should be up with the definition of mySDCardImages. Accessible to both class methods.)
(Quick and dirty version) Make sure to test your path, etc and catch any Exceptions.
In your case BitmaFactory might be a good way to go. Example:
File dir = new File( "/sdcard/pictures" );
String[] fileNames = dir.list(new FilenameFilter() {
boolean accept (File dir, String name) {
if (new File(dir,name).isDirectory())
return false;
return name.toLowerCase().endsWith(".png");
}
});
for(string bitmapFileName : fileNames) {
Bitmap bmp = BitmapFactory.decodeFile(dir.getPath() + "/" + bitmapFileName);
// do something with bitmap
}
Not time to test this but should work ;-)
read this link: http://androidsamples.blogspot.com/2009/06/how-to-display-thumbnails-of-images.html
it shows how to use both mediastore and bitmapfactory.
the way you should chose depends on what exactly you need. if you have a static set of images, it's much better idea to put them to drawables, i think, cause this way it's faster and you don't rely on sd card, which can be removed, corrupt or files could be renamed/deleted
if images are dynamic, then use mediastore or bitmap factory. but keep in mind that putting images into array or something it's quite memory consuming, so you can end up having outofmemory exception
Looks like you want custom gallerry, it will take much time for you,
I suggest you get Custom Camera Gallery for your working.
You will get Photos/Videos in Grid View as you want.
for Kotlin code see the answer of this question
the idea is alslo applicable for java (but you need to modify the code)