I have spent a lot of time trolling through multiple different threads concerning this topic, but I have yet to find an answer that works well with my code (Android SDK 23, in 2016). A lot of the answers are deprecated, and others just flat-out don't work like they're supposed to, and I was wondering if I could get a solid answer on this:
I am trying to include a Pokemon sprite (static image) in my program from Serebii. nums is a variable indicating the Pokemon's dex number (this one functions correctly, I promise). And this code is running in the main UI thread, which I know is frowned upon, but right now I'm trying to get the image loading, and then the smoothness of the app down. I don't really need a Bitmap, per se, but I need my ImageView to update and display the image given by the URL. How do I do it?
URL url = null;
try {
url = new URL("http://www.serebii.net/xy/pokemon/" + nums + ".png");
} catch (MalformedURLException e) {
e.printStackTrace();
}
Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
mImageView.setImageBitmap(bmp);
Just use Picasso library, it will do all your image loading. You only need to provide the url of the image correctly.
String url = "http://www.serebii.net/xy/pokemon/" + nums + ".png";
Picasso.with(yourContext)
.load(url)
.into(mImageView);
You can use Picasso Library to load images.
a) Add Gradle into your project.
compile 'com.squareup.picasso:picasso:2.5.2'
b) Usage
Picasso.with(context).load("http://www.serebii.net/xy/pokemon/" + nums + ".png").into(imageView);
Also there are another libraries, you can use like
Fresco by Facebook, Universal Image loader
You can try using Picasso as:
Picasso.with(context)
.load(url)
.into(imageview);
Or use Universal Image loader as:
ImageLoader imageLoader = new ImageLoader(context);
imageLoader.displayImage(imageUri, imageView);
Use the Piassco library for it..Library link
For setting the Bitmap on the ImageView
Picasso.with(getContext()).load("your url").into(new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
//do what ever you want with your bitmap
imgView.setImageBitmap(loadedImage);///imgView is use to set the image in it
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
And another method of Picasso :-
Picasso.with(this)
.load("your_image_url")
.placeholder(R.drawable.no_image)
.error(android.R.drawable.stat_notify_error)
.networkPolicy(NetworkPolicy.OFFLINE)//user this for offline support
.into(YOUR_IMAEGVIEW);
OR
You can also use the Universal Image Loader..Here is the link Universal image loader
ImageLoader imageLoader = ImageLoader.getInstance(); // Get singleton instance
ImageLoader.getInstance().init(ImageLoaderConfiguration.createDefault(getActivity()));
imageLoader = com.nostra13.universalimageloader.core.ImageLoader.getInstance();
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.YOUR_DRAWABLE)
.showImageForEmptyUri(R.drawable.YOUR_DRAWABLE)
.showImageOnFail(R.drawable.YOUR_DRAWABLE)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.build();
imageLoader.displayImage("your_image_url", YOUR_IMAGEVIEW, null);
Related
I want to show a video thumbnail in an ImageView from a video path on storage. Is there a function that takes a video path and returns a bitmap of a thumbnail? I get the video path by this code:
public ArrayList<String> getAllMedia() {
HashSet<String> videoItemHashSet = new HashSet<>();
String[] projection = {MediaStore.Video.VideoColumns.DATA, MediaStore.Video.Media.DISPLAY_NAME};
Cursor cursor = getContext().getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
try {
cursor.moveToFirst();
do {
videoItemHashSet.add((cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA))));
} while(cursor.moveToNext());
cursor.close();
} catch(Exception e) {
e.printStackTrace();
}
ArrayList<String> downloadedList = new ArrayList<>(videoItemHashSet);
return downloadedList;
}
It is the default way to create a thumbnail.
For Mini Kind
Bitmap thumb;
//MINI_KIND, size: 512 x 384 thumbnail
thumb = ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Video.Thumbnails.MINI_KIND);
img_tumbnail.setImageBitmap(thumb);
For Micro Kind
Bitmap thumb;
//MICRO_KIND, size: 96 x 96 thumbnail
thumb= ThumbnailUtils.createVideoThumbnail(filePath, Thumbnails.MICRO_KIND);
img_tumbnail.setImageBitmap(thumb);
Also, you can use Glide for Url as well as Video path of Device.
Glide.with(context).with(this)
.asBitmap()
.load(videoFilePath) // or URI/path
.into(imgView); //imageview to set thumbnail to
also, you can resize thumbnail by using .override(50,50) with Glide.
Use Glide lib
to show thumbnail from local storage
String filePath = "/storage/emulated/0/Pictures/example_video.mp4";
GlideApp
.with(context)
.asBitmap()
.load(Uri.fromFile(new File(filePath)))
.into(imageViewGifAsBitmap);
You can use ThumbnailUtils to load video thumb in 3 format:
MINI_KIND : Good for media detail view
FULL_SCREEN_KIND : Good for header
MICRO_KIND : Good for recycleView
Ex:
holder.videoThumb.setImageBitmap(ThumbnailUtils.createVideoThumbnail(getItem(position).videoURL, MediaStore.Images.Thumbnails.MICRO_KIND))
The biggest drawback is that ThumbnailUtils operate on UI thread so if you try to use this method in a recycleView then it gone make your app skip frames. Your RecycleView will have laggy scroll and if you have more than 7 items then your app will start throwing ANR.
That means you need to create AsyncTask or Threads which again might lead to memory leaks.
Conclusion; Glide is better in loading video thumbs.
Here DiskCacheStrategy.RESULT is important parameter which worked for me and give a smooth fast scroll in recycle view.
Glide.with(context).load(getItem(position).videoURL)
.asBitmap()
.placeholder(R.drawable.app_icon)
.centerCrop()
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.into(holder.videoThumb)
I have 3rd method to set thumbnail of image/video.
Hope it will help you.
1) ThumbnailUtils --> Effective but Slow
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(thumbPath, MediaStore.Video.Thumbnails.MINI_KIND);
holder.ivThumb.setImageBitmap(thumb);
2) FFmpegMediaMetadataRetriever --> Very Effective but Slow
FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever();
try {
retriever.setDataSource(thumbPath);
thumb.setImageBitmap(retriever.getFrameAtTime(0));
} catch (Exception ex) {
// Assume this is a corrupt file
}
3) Glide --> Effective and Fast
RequestOptions options = new RequestOptions()
.centerCrop()
.placeholder(android.R.drawable.stat_notify_error)
.error(android.R.drawable.stat_notify_error);
Glide.with(context)
.load(thumPath)
.apply(options)
.into(thumb);
If anyone is looking for a Kotlin version. You can try this extension function.
It is using coil.
/**
* https://github.com/coil-kt/coil/issues/413
*/
fun ImageView.setThumbnail(uri: Uri, frameMillis: Long = 2000) {
val imageLoader = ImageLoader.Builder(context)
.componentRegistry {
add(VideoFrameFileFetcher(context))
add(VideoFrameUriFetcher(context))
}.build()
val request = ImageRequest.Builder(context)
.data(uri)
.videoFrameMillis(frameMillis)
.target(this)
.fetcher(VideoFrameUriFetcher(context))
.build()
findViewTreeLifecycleOwner()?.lifecycleScope?.launch(Dispatchers.Main) {
imageLoader.execute(request)
}
}
In some devices not working for me without FileDescriptorBitmapDecoder
So I used following code with FileDescriptorBitmapDecoder
public static void loadLocalVideoThumbanail(Context context, String path, final ImageView imageView) {
try {
if (path == null || path.isEmpty())
return;
BitmapPool bitmapPool = Glide.get(context).getBitmapPool();
int microSecond = 1000000;// 1st second as an example
VideoBitmapDecoder videoBitmapDecoder = new VideoBitmapDecoder(microSecond);
FileDescriptorBitmapDecoder fileDescriptorBitmapDecoder = new FileDescriptorBitmapDecoder(videoBitmapDecoder, bitmapPool, DecodeFormat.PREFER_ARGB_8888);
Glide.with(context).load(path).asBitmap().thumbnail(0.6f)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.dontAnimate()
.videoDecoder(fileDescriptorBitmapDecoder)
.override(200,200)
.into(imageView);
} catch (Exception e) {
MyLog.e(TAG, "LoadImage: ", e);
}
}
#Override
public void onBindViewHolder(final ViewHolder holder ,int position) {
Glide.with(c)
.load(images.get(position))
.placeholder(R.mipmap.ic_launcher)
.into(holder.img);
holder.img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try{
String fileName = "bitmap.png";
FileOutputStream stream = c.openFileOutput(fileName,Context.MODE_PRIVATE);
Intent showBigPicture = new Intent(c,showBigPicture.class);
Bitmap bitmapImage = BitmapFactory.decodeFile(images.get(position));
bitmapImage.compress(Bitmap.CompressFormat.PNG,100,stream);
stream.close();
bitmapImage.recycle();
showBigPicture.putExtra("image",fileName);
c.startActivity(showBigPicture);
}catch (Exception e){
e.printStackTrace();
}
}
});
}
this is showing in logCat " Unable to decode stream: java.io.FileNotFoundException: android.support.v7.widget.AppCompatImageView{e22d977 V.ED..C. ...P.... 0,0-540,890 #7f0b0061 app:id/img}: open failed: ENOENT (No such file or directory)"
I believe you want to follow this answer on saving Bitmap images. I believe the reason you're getting a FileNotFoundException is because you're providing the URI to a file that doesn't exist yet to the decodeFile function that's quite possibly a URL from what I can tell. In short, to save a bitmap:
Create a new File(filename)
Decode file using getName on the File from step 1
Create FileOutputStream from File
Compress the bitmap image into the FileOutputStream
From what I can surmise from your question, it looks as though you're showing a images in a RecyclerView and when an image is clicked, you want to open another activity which shows a version of the full image. If that's close to your use-case, and you're using Glide, I would recommend taking advantage of its built-in automatic caching feature to reduce network calls instead of manually saving the file.
By default, disk and memory-based caching is enabled in Glide as long as the same filename, path, or URL are used to obtain the image on each Glide.load(...). If you'd like to manipulate how the caching occurs, use the DiskCacheStrategy enum to control that every time you load the image:
Glide.with(c)
.load(images.get(position))
.diskCacheStrategy(DiskCacheStrategy.SOURCE) # Will cache the source downloaded image before any transformations are applied
.placeholder(R.mipmap.ic_launcher)
.into(holder.img);
If you still want to save the file for other reasons, use a SimpleTarget instead of loading directly into your ImageView like so:
Glide.with(c)
.load(images.get(position))
.diskCacheStrategy(DiskCacheStrategy.SOURCE) # Will cache the source downloaded image before any transformations are applied
.placeholder(R.mipmap.ic_launcher)
.asBitmap()
.into(new SimpleTarget<GlideDrawable>() {
#Override
public void onResourceReady(Bitmap bitmap, GlideAnimation anim) {
holder.img.setImageDrawable(new BitmapDrawable(bitmap));
saveImage(bitmap); # This being an encapsulation of the steps outlined earlier
}
});
i´m using Picasso and Target for downloading an image and saving it as a bitmap to pass it into an Object which i use for and RecyclerView.
But when I try to download the image the Target also loads the onBitmapFailed or onPrepareLoad and the bitmapis not successfully received...
where´s the bug in my code? The URL is absolutely correct. when i take the passed URL and paste it in chrome browser the image shows...
Code
//Get Bitmap
targetForBitmap = new Target() {
#Override
public void onBitmapLoaded (final Bitmap responseBitmap, Picasso.LoadedFrom from){
bitmap = responseBitmap;
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
Log.i("prepareLoad", "onPrepereLoad ääääääääääääääääääää ");
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
Log.i("onBitmapFailed", "onBitmapFailed xxxxxxxxxxxxxxxx");
}
};
String url = "Http://" + server_wan + ":" + port_wan + "/" + server_path + "/Produktbilder/" + product_image + ".png";
Log.i("url", url);
Picasso.with(SpeisekarteActivity.this)
.load(url)
.into(targetForBitmap);
targetForBitmap is string instance at beginning of the class (private Target targetForBitmap)
Please provide the imageview where you want to load the image inside the onBitmapLoaded.
Try using .placeholder(drawable) and .error(drawable) with picasso.Use it after .load function.
Try checking out here:
[1]: Picasso Library, Android: Using Error Listener
I have many images that I want to preload and use later on. I want to make it so that I can load an image, hide it, and then load it again whenever I want.
https://github.com/bumptech/glide/wiki/Loading-and-Caching-on-Background-Threads#into
I have tried following this, but it doesn't work.
Here is my code:
private void loadImage() throws ExecutionException, InterruptedException {
FutureTarget<File> future = Glide.with(this)
.load(R.drawable.image1)
.downloadOnly(500, 500);
File cacheFile = future.get();
Bitmap myBitmap = Glide.with(this)
.load(cacheFile)
.asBitmap()
.centerCrop()
.into(500, 500)
.get();
Glide.with(this).load(myBitmap).into(image_name);
}
I tried using Picasso because I read that this can easily be done in it, but the images take really long to load in Picasso.
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);