I need to load App icon into image view. It is too slow to load it in list view.
I tried to use Picasso or Glide to load it.
I could not find out how to load Drawable object (NOT FROM RESOURCES) into image view using any of those libraries?
The function for getting the drawable:
public Drawable getIcon() {
if (icon == null) {
icon = getResolveInfo().loadIcon(ctx.getPackageManager());
}
return icon;
}
You can do this
Drawable icon = ....
Bitmap bitmap = ((BitmapDrawable) icon).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] bitmapdata = stream.toByteArray();
Glide.with(context)
.load(bitmapdata)
.into(imageView);
But i am not sure that in this case the Glide (or Picasso) will be use the cache.
You can create your own RequestHandler for Picasso. There is a tutorial here.
For example,
class AppIconRequestHandler extends RequestHandler {
#Override
public boolean canHandleRequest(Request data) {
return true; // or do validation here
}
#Override
public Result load(Request request, int networkPolicy) {
// Not sure if DISK or correct or if it should be something else, but it works for me.
return new Result(yourApp.getIcon().bitmap, Picasso.LoadedFrom.DISK);
}
}
// When you want to show the icon
Picasso picasso = Picasso.Builder(context)
.addRequestHandler(new AppIconRequestHandler())
.build()
picasso.load(packageName)
.placeholder(placeholderIcon)
.into(imageView)
Don't forget to scale app icons, by the way! You can't rely on them to be small images and you may end up using a lot more ram than you need.
This one is using the Picasso library.
String url = "some url to your image";
ImageView thumbnail = (ImageView) findViewById(R.id.thumbnail);
Picasso.with(context).load(url).into(thumbnail);
I have an activity in which I have an EditText, an ImageButton to grab an image, and an ImageView.
The ImageView is empty, but I can add a src via Intent.ACTION_GET_CONTENT
The EditText was very slow if I had an image too, so I'm using thumbnails now:
Bitmap thumbImage = ThumbnailUtils.extractThumbnail(
BitmapFactory.decodeFile(imageFile.getAbsolutePath()),
uploadedImageView.getWidth(), uploadedImageView.getWidth());
uploadedImageView.setImageBitmap(thumbImage);
And all works fine now.
The problem is when I share an image with this activity from another app.
The EditText is slow as before the thumbnails.
This is how I'm doing it now:
in my onCreate method:
if (Intent.ACTION_SEND.equals(action) && type != null) {
if ("text/plain".equals(type)) {
...
} else if (type.startsWith("image/")) {
ViewTreeObserver viewTree = uploadedImageView.getViewTreeObserver();
viewTree.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
Uri selectedImageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
imageFile = new File(FileUtils.getPath(MyActivity.this, selectedImageUri));
Bitmap thumbImage = ThumbnailUtils.extractThumbnail(
BitmapFactory.decodeFile(imageFile.getAbsolutePath()),uploadedImageView.getWidth(),uploadedImageView.getWidth());
uploadedImageView.setImageBitmap(thumbImage);
return true;
}
});
}
}
What am I missing?
i am using imageAdapter class in which i have an array that stores drawables
public Integer[] mThumbIds = {
R.drawable.blue, R.drawable.floral,
R.drawable.bluefloral };
in first activity when user click on save button i have saved those images in android internal memory like data/ data/ com.myapp.color , i have get the file name, and file path too and passed it to imageAdapter class i just wanted to know that through this file name and path how can i save these images in to this array. because through this array i am displaying images in gridview.
If the image inside the internal or external storage you can load it by this:
Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath());
ImageView imageView = (ImageView) findViewById(R.id.imageView);
imageView.setImageBitmap(bitmap);
If the image inside the drawable folder inside the apk you can use:
ImageView imageView = (ImageView) findViewById(R.id.imageView);
imageView.setImageResource(R.drawable.drawable_name);
If the image inside the assets folder you can use:
InputStream inputStream = getAssets().open("image_name.jpg");
Drawable drawable = Drawable.createFromStream(inputStream, null);
ImageView imageView = (ImageView) findViewById(R.id.imageView);
imageView.setImageDrawable(drawable);
If the image inside drawable folder and you have only the name you can get the resource id by using:
int drawableResourceId = this.getResources().getIdentifier("image_name_without_extension", "drawable", this.getPackageName());
This is how you can get the image id's using their file names. Using this id you can load the image in image view.
If the image name is my_image this method would return id value associated with R.id.my_image
public static int getImageIDFromName(String imageName)
{
int imageID = 0;
if(imageName == null
|| imageName.equalsIgnoreCase(""))
{
return 0;
}
try
{
#SuppressWarnings("rawtypes")
Class res = R.drawable.class;
Field field = res.getField(imageName);
imageID = field.getInt(null);
}
catch(Exception e)
{
}
return imageID;
}
I know it is possible to use another app's bitmaps using the following blockquote, or similar:
String packageName = "com.some.package";
Resources res = getPackageManager().getResourcesForApplication(packageName);
int resId = res.getIdentifier("some_bitmap_icon", "drawable", packageName);
((BitmapDrawable) res.getDrawable(resId)).getBitmap();
Is there anyway of passing res and resIdto Android-Universal-Image-Loader to directly load the bitmap from the 3rd party app?
Or would I have to copy the bitmap to the SD card, then display it by passing "file:///mnt/sdcard/some_temp_bitmap"
Thanks to #CommonsWare for pointing me in the right direction.
I started by extending BaseImageDownloader, and overriding getStreamFromOtherSource:
public class CustomImageDownloader extends BaseImageDownloader {
public CustomImageDownloader(Context context) {
super(context);
}
#Override
protected InputStream getStreamFromOtherSource(String imageUri, Object extra) {
if (imageUri.startsWith("thirdparty://")) {
try {
String drawableString = imageUri.replace("thirdparty://", "");
String[] location = drawableString.split("/");
Resources res = context.getPackageManager().getResourcesForApplication(location[0]);
return res.openRawResource(Integer.parseInt(location[1]));
} catch (PackageManager.NameNotFoundException e) {
return null;
}
} else throw new UnsupportedOperationException(imageUri);
}
}
Then implemented this class in my ImageLoaderConfiguration using:
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.imageDownloader(new CustomImageDownloader(context))
.build();
ImageLoader.getInstance().init(config);
Then it's just a case of starting the image loader using:
ImageLoader.getInstance().displayImage("thirdparty://"+ packageName + "/" + resId, imageView, options);
Now Android universal image loader can be used for loading bitmaps from 3rd party apps.
Query to MediaStore.Video.Media.EXTERNAL_CONTENT_URI returns only video in /sdcard/DCIM/100MEDIA
But I want to get thumbnails for video in my /sdcard/Android/data/mypackage/files folder. Is it possible ?
Here is part of my code:
ContentResolver cr = getContentResolver();
String[] proj = {
BaseColumns._ID
};
Cursor c = cr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, proj, null, null, null);
if (c.moveToFirst()) {
do
{
int id = c.getInt(0);
Bitmap b = MediaStore.Video.Thumbnails.getThumbnail(cr, id, MediaStore.Video.Thumbnails.MINI_KIND, null);
Log.d("*****My Thumbnail*****", "onCreate bitmap " + b);
ImageView iv = (ImageView) findViewById(R.id.img_thumbnail);
iv.setImageBitmap(b);
}
while( c.moveToNext() );
}
c.close();
If you are on android-8 (Froyo) or above, you can use ThumbnailUtils.createVideoThumbnail:
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
MediaStore.Images.Thumbnails.MINI_KIND);
Use Glide it will fetch the thumbnail in async.
Glide.with(context)
.load(videoFilePath) // or URI/path
.into(imgView); //imageview to set thumbnail to
3 ways to get a thumbnail from a video:
The best way is to use Glide. It will do all the work in the background, load the thumbnail right into the ImageView and even can show animation when loading. It can work with Uri, byte[] and many other sources.
As #Ajji mentioned:
Glide.with(context)
.load(videoFilePath) // or URI/path
.into(imgView); //imageview to set thumbnail to
If you just need a bitmap in the most efficient way - use ThumbnailUtils.
In my case, it produced a bitmap with a size of 294 912 bytes (video taken with a camera of Nexus5X - 1280x720) and the quality was the same as in the next approach. After you compress into JPEG with 90 it will generate a jpeg file of ~30Kb.
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
MediaStore.Images.Thumbnails.MINI_KIND);
The last approach is to use MediaMetadataRetriever. But in my case, it produced a bitmap with size more than 6 times bigger than you got with ThumbnailUtils (with the same quality). So consider it as a last resort.
MediaMetadataRetriever mMMR = new MediaMetadataRetriever();
mMMR.setDataSource(mContext, mAttachment.getUri());
bmp = mMMR.getFrameAtTime();
P.S.: Don't forget that images in Bitmap, byte[] and real file .jpeg formats can be easily converted in any direction within these types. In case of Uri's you often don't have real path to the source file but you can always get the byte stream from it like this:
InputStream in = mContext.getContentResolver().openInputStream(uri);
and with this input stream you can do whatever you want.
You can just use FFmpegMediaMetadataRetriever and forget the reflection:
/**
*
* #param path
* the path to the Video
* #return a thumbnail of the video or null if retrieving the thumbnail failed.
*/
public static Bitmap getVideoThumbnail(String path) {
Bitmap bitmap = null;
FFmpegMediaMetadataRetriever fmmr = new FFmpegMediaMetadataRetriever();
try {
fmmr.setDataSource(path);
final byte[] data = fmmr.getEmbeddedPicture();
if (data != null) {
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
}
if (bitmap == null) {
bitmap = fmmr.getFrameAtTime();
}
} catch (Exception e) {
bitmap = null;
} finally {
fmmr.release();
}
return bitmap;
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmapThumb = MediaStore.Video.Thumbnails.getThumbnail(mActivity.getContentResolver(),
Long.parseLong(video_id),
Images.Thumbnails.MINI_KIND,
options);
Use Options to load bitmap of decrease the bitmap size..
see #Ajji 's answer :
Glide.with(context)
.load(videoFilePath) // or URI/path
.into(imgView); //imageview to set thumbnail to
It sometimes returns black image, this issue is already mentioned in Glide library's issues
Use this code:
BitmapPool bitmapPool = Glide.get(activity).getBitmapPool();
int microSecond = 6000000;// 6th second as an example
VideoBitmapDecoder videoBitmapDecoder = new VideoBitmapDecoder(microSecond);
FileDescriptorBitmapDecoder fileDescriptorBitmapDecoder = new FileDescriptorBitmapDecoder(videoBitmapDecoder, bitmapPool, DecodeFormat.PREFER_ARGB_8888);
Glide.with(activity)
.load(videoPath)
.asBitmap()
.override(50,50)// Example
.videoDecoder(fileDescriptorBitmapDecoder)
.into(holder.ivFirstUpload);
Get video thumbnail from VIDEO_ID:
public static Drawable getVideoThumbnail(Context context, int videoID) {
try {
String[] projection = {
MediaStore.Video.Thumbnails.DATA,
};
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(
MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI,
projection,
MediaStore.Video.Thumbnails.VIDEO_ID + "=?",
new String[] { String.valueOf(videoID) },
null);
cursor.moveToFirst();
return Drawable.createFromPath(cursor.getString(0));
} catch (Exception e) {
}
return null;
}
Here is a similar answer to Matthew Willis but with added reflection. Why? because science.
/**
*
* #param path
* the path to the Video
* #return a thumbnail of the video or null if retrieving the thumbnail failed.
*/
public static Bitmap getVidioThumbnail(String path) {
Bitmap bitmap = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
bitmap = ThumbnailUtils.createVideoThumbnail(path, Thumbnails.MICRO_KIND);
if (bitmap != null) {
return bitmap;
}
}
// MediaMetadataRetriever is available on API Level 8 but is hidden until API Level 10
Class<?> clazz = null;
Object instance = null;
try {
clazz = Class.forName("android.media.MediaMetadataRetriever");
instance = clazz.newInstance();
final Method method = clazz.getMethod("setDataSource", String.class);
method.invoke(instance, path);
// The method name changes between API Level 9 and 10.
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD) {
bitmap = (Bitmap) clazz.getMethod("captureFrame").invoke(instance);
} else {
final byte[] data = (byte[]) clazz.getMethod("getEmbeddedPicture").invoke(instance);
if (data != null) {
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
}
if (bitmap == null) {
bitmap = (Bitmap) clazz.getMethod("getFrameAtTime").invoke(instance);
}
}
} catch (Exception e) {
bitmap = null;
} finally {
try {
if (instance != null) {
clazz.getMethod("release").invoke(instance);
}
} catch (final Exception ignored) {
}
}
return bitmap;
}
If you are directly creating thumbnails as follows
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
MediaStore.Images.Thumbnails.MINI_KIND);
Then there is a problem with this method if your are creating thumbnails for large video set(for large number of videos). the application will freeze until all the thumbnails are loaded because all the process are executing in the main thread.
Use SuziLoader
This loader will load the thumbnails for the videos which is locally stored on your filesystem in background.
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/video.mp4";
ImageView mThumbnail = (ImageView) findViewById(R.id.thumbnail);
SuziLoader loader = new SuziLoader(); //Create it for once
loader.with(MainActivity.this) //Context
.load(path) //Video path
.into(mThumbnail) // imageview to load the thumbnail
.type("mini") // mini or micro
.show(); // to show the thumbnail
To get this dependency use the following steps
Step 1. Add the JitPack repository to your build file
Add it in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Step 2. Add the dependency
dependencies {
compile 'com.github.sushinpv:SuziVideoThumbnailLoader:0.1.0'
}
ADD READ EXTERNAL STORAGE Permission in manifest
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Try something similar to this code snippet:
img.setImageBitmap(ThumbnailUtils.createVideoThumbnail(
Environment.getExternalStorageDirectory().getPath() + "/WhatsApp/Media/WhatsApp Video/"+getItem(position),
MediaStore.Video.Thumbnails.FULL_SCREEN_KIND));
Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] projection = { MediaStore.Video.VideoColumns.DATA };
Cursor c = getContentResolver().query(uri, projection, null, null, null);
int vidsCount = 0;
if (c != null) {
vidsCount = c.getCount();
while (c.moveToNext()) {
String path = c.getString(0);
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
MediaStore.Images.Thumbnails.MINI_KIND);
}
c.close();
}
You can use this method with any Uri:
public static Bitmap getVideoFrame(Uri uri, Context context) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(context, uri);
return retriever.getFrameAtTime();
}