InputStream freezes UI on Android - java

I am downloading images in background for a list. I have noticed that even with AsycTask the scrolling is not smooth. After some hours of debugging, I have came to conclusion that the InputStream is the guilty one.
doInBackground should be working on a non-ui thread, then why does it impact the UI?
If I comment out the InputStream code, the scrolling is smooth.
I have 3 images in a row, so usually 3 images are loaded at the same time.
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
final WeakReference<ImageView> imageViewReference;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
#Override
protected Bitmap doInBackground(String... params) {
InputStream is = null;
try {
is = (InputStream) new URL(params[0]).getContent();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
// Once complete, see if ImageView is still around and set bitmap.
#Override
protected void onPostExecute(Bitmap bitmap) {
// REMOVED ON PURPOSE TO CONFIRM THAT INPUTSTREAM IS GUILTY
}
}

Related

onProgressUpdate() for AsyncTask class doesn't work

I want to show progressbar where image downloaded and set custom color
I do it in onProgressUpdate() but it dosent work it also doesn't appear in logcat.. it also shows a white screen until download completed and if I press back button during the download, it will crash.
my code:
public class DownloadImage extends AsyncTask<String ,Void, Bitmap> {
Bitmap bit;
#Override
protected Bitmap doInBackground(String... urls) {
try {
URL url = new URL(urls[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
return BitmapFactory.decodeStream(connection.getInputStream());
} catch(Exception e){
Log.i("error download", "doInBackground: "+e.getMessage());
}
return null;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
Log.i("download", "onPostExecute: ");
imageView.setImageBitmap(bitmap);
progressBar.setVisibility(View.GONE);
}
#Override
protected void onProgressUpdate(Void... values) {
Log.i("download", "onProgressUpdate: ");
imageView.setColorFilter(R.color.imagecolor);
}
}
and onCreate() method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
imageView = findViewById(R.id.imageView2);
progressBar = findViewById(R.id.progressBar2);
DownloadImage downloadImage = new DownloadImage();
downloadImage.execute("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRaL6woz3RgMF-UXU682S_BYb1ayl5xaVancp0PPvF2HnCDmPsb");
try {
downloadImage.get();
} catch (Exception e){
}
}
I want to show progressbar where image downloaded and set custom color I do it in onProgressUpdate() but it dosent work
You need to call publishProgress() from doInBackground(). That will trigger calls to onProgressUpdate(). You are not doing this, and so onProgressUpdate() will not be called.
it also shows a white screen until download completed
Remove your downloadImage.get(); call. That will block the main application thread, and the point of using AsyncTask (or its more modern replacements) is to not block the main application thread.
and if I press back button during the download, it will crash.
If the activity/fragment is destroyed, you should not update the UI. So, you need to confirm in onPostExecute() whether it is safe to update the UI (e.g., call isDestroyed() on the activity).
Beyond that, use Logcat to examine the stack trace associated with any crashes.

Camera2 ImageReader hangs after a while with "Failed to release buffer" message

I'm having a problem with android's camera2 API.
My end goal here is to have a byte array which I can edit using opencv, whilst displaying the preview to the user (e.g. an OCR with a preview).
I've create a capture request and added an ImageReader as a target. Then on the OnImageAvailableListener, i'm getting the image, transforming it to a bitmap and then display it on an ImageView (and rotating it).
My problem is that after a few seconds, the preview stalls (after gradually slowing down) and in the log om getting the following error: E/BufferItemConsumer: [ImageReader-1225x1057f100m2-18869-0] Failed to release buffer: Unknown error -1 (1)
As you can see in my code, I have already tried closing the img after getting my byte[] from it.
I've also tried clearing the buffer.
I've tried closing the ImageReader but that of course stopped me from getting any further images (throws an exception).
Can anyone please help me understand what im doing wrong? I've been scouring google to no avail.
This is my OnImageAvailableListener, do let me know if you need more of my code to assist:
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
= new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
Image img = reader.acquireLatestImage();
final ImageView iv = findViewById(R.id.camPrev);
try{
if (img==null) throw new NullPointerException("null img");
ByteBuffer buffer = img.getPlanes()[0].getBuffer();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
final Bitmap b = BitmapFactory.decodeByteArray(data, 0, data.length);
runOnUiThread(new Runnable() {
#Override
public void run() {
iv.setImageBitmap(b);
iv.setRotation(90);
}
});
} catch (NullPointerException ex){
showToast("img is null");
}finally {
if(img!=null)
img.close();
}
}
};
Edit - adding cameraStateCallback
private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(CameraDevice cameraDevice) {
mCameraDevice = cameraDevice;
showToast("Connected to camera!");
createCameraPreviewSession();
}
#Override
public void onDisconnected(CameraDevice cameraDevice) {
closeCamera();
}
#Override
public void onError(CameraDevice cameraDevice, int i) {
closeCamera();
}
};
private void closeCamera() {
if (mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
}
You seem to have used setRepeatingRequest() for Jpeg format. This may not be fully supported on your device, also depends on the image resolution that you choose. Normally, we use createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW) in these cases, and get YUV or raw format from ImageReader.
I would try to choose low resolution for Jpeg: maybe this will be enough to keep the ImageReader running.

Glide and GPUImageView issue

I am trying to implement an Android image filter library called GPUImage Located here.
I have tried to use it like below
public static GPUImageView img_bg;
img_bg = (GPUImageView) findViewById(R.id.img_bg);
categoryAdapter1.setOnClickLIstner(new OnClickLIstner() {
#Override
public void onClick(View v, Image image, int pos) {
Glide.with(NameArt.this)
.load(image.getDrawableId())
.centerCrop()
.dontAnimate()
.into(img_bg);
img_bg.setVisibility(View.VISIBLE);
}
});
But I am getting error like below
cannot resolve method 'into' (jp.co.cyberagent.android.gpuimage.GPUImageView)
I am unable to solve it because I am learning android and java yet. Let me know if any expert here can help me for solve the issue. Thanks
Ensure you are using right version of Glide your GPUImageView can deal with. Recent v4 brings API changes that are not backward compatible and since this lib you are using looks bit rusty and does not set properly dependencies, you got the clash. Enforce v3 of Glide, or drop dated library.
try this to load image in your GPUImage
new DownloadImage(img_bg).execute(url);
create a Async Task
public class DownloadImage extends AsyncTask<String, Void, Bitmap> {
GPUImageView bmImage;
public DownloadImage(GPUImageView bmImage) {
this.bmImage = (GPUImageView ) bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.d("Error", e.getStackTrace().toString());
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
i hope that it will work in your case

Android image didn't display to ImageView from image URL

I want to display image to ImageView from "http://i.imgur.com/4GLKF4Q.jpg" but The image in image URL didn't display to imageview. Can I do this?
AsyncTask
class DownloadImageTask extends AsyncTask<String, Void, byte[]> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected byte[] doInBackground(String... urls) {
try {
URL url = new URL(urls[0]);
InputStream is = (InputStream) url.getContent();
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
while ((bytesRead = is.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
return output.toByteArray();
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
protected void onPostExecute(byte[] result) {
ByteArrayInputStream imageStream = new ByteArrayInputStream(result);
Bitmap bm = BitmapFactory.decodeStream(imageStream);
bmImage.setImageBitmap(bm);
}
}
in activity
new DownloadImageTask((ImageView) newView.findViewById(R.id.thumbnail))
.execute("http://i.imgur.com/4GLKF4Q.jpg");
The image in image URL didn't display to imageview.
in Logcat :
09-23 10:26:49.410 10591-10591/com.*** D/skia: --- SkImageDecoder::Factory returned null
Update from comment : changing image server to another one solve the issue. I guess it's a i.imgur.com issue.
You shouldn't use your own image loader task, it will leak somewhere.
Two good library exist :
- Fresco (from Facebook)
- Picasso (from Square up)
There is also UniversalImageLoader (UIL).
I would suggest you to checkout Image Management Library by Facebook that is Fresco that is pretty awesome and mature as compared to other Image Loading Library.
Fresco handles all the things caching of images with 3 Tier architecture ( BITMAP_MEMORY_CACHE, ENCODED_MEMORY_CACHE and DISK_CACHE). It also reduces OOM(Out Of Memory) issues. When image in a view goes out of screen it automatically recycles the bitmap, hence releasing the memory.
Now there is an official way to load an ImageView from a URL and that is NOT to use an ImageView.
NetworkImageView—builds on ImageLoader and effectively replaces ImageView for situations where your image is being fetched over the network via URL. NetworkImageView also manages canceling pending requests if the view is detached from the hierarchy.
Images are automatically loaded in a background thread and the view updated on the UI thread. It even supports caching.

Android Picaso - How to not cache images that are not downloaded through it?

So I am using Picaso to load some images and cache them like so:
ImageView logo = (ImageView)findViewById(R.id.image_logo);
Picasso.with(VenueDetailsActivity.this).load(url).into(logo);
However, I have other images that should not be cached. However, it seems like as soon as Picaso is running in any point in the app, then it starts caching all images no matter if I use Picaso loading on them or not.
How can I not cache certain images using Picasso?
** Does Picasso setups your app that any image loading is cached regardless of using Picasso or not?**
The method I use to download my images are:
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
If you don't want Picasso to cache an image you can use .skipMemoryCache() like so:
Picasso.with(VenueDetailsActivity.this).load(url).skipMemoryCache().into(logo);
For more information you can view the documentation here

Categories