I'm trying to load images with an async taks from internet. The problem is that the image will not update. Code:
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i ;
i = new ImageView(this.mContext);
AsycTask task = new AsycTask();
task.url = new URL(mImageIds.get(position));
task.iv = i;
task.execute(i);
return i;
}
public class AsycTask extends AsyncTask<ImageView, Void, Bitmap>{
public Bitmap bm2;
public ImageView iv;
public URL url;
#Override
protected Bitmap doInBackground(ImageView... arg0) {
iv = arg0[0];
try {
bm2 = BitmapFactory.decodeStream((InputStream)url.getContent());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bm2;
}
#Override
protected void onPostExecute(Bitmap result) {
// iv.setImageResource(R.drawable.sw10)
iv.setVisibility(View.VISIBLE);
iv.setBackgroundResource(R.drawable.search);
iv.setScaleType(ImageView.ScaleType.FIT_XY);
iv.setImageBitmap(result);
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
Why isn't the Image updating after I set the Bitmap?
I'm using an async task to update my Image, is this possible?
Try to use UnivsersalImageLoader lib which will simplify your development.
Your code for image loading will be next:
ImageLoader.getInstance().displayImage(imageUrl, imageView); // Default options will be used
UniversalImageLoader
Related
I am building an app which will continuously get screenshots of my laptop screen and transfer it to my android app but there is some problem within the while loop, when I put a for loop to a limit then my program runs but as it goes till infinity or I replace it with infinite while loop my code suspends all the threads and app crash dueto memory allocation problem, please suggest me to execute my code infinite times so that there are continuous screenshots displayed.
Thank You.
Here is my code
public class ScreenActivity extends AppCompatActivity {
ImageView img;
int width,height;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen);
img=(ImageView)findViewById(R.id.imageView);
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
// while (true)
for (int i=0;i<100;i++)
new GetImg().execute();
}
Bitmap imgscr;
public class GetImg extends AsyncTask<Object,Void,Bitmap> {
#Override
protected Bitmap doInBackground(Object[] params) {
Socket client= null;
try {
client = new Socket("192.168.1.5",6767);
InputStream in=client.getInputStream();
imgscr=Bitmap.createScaledBitmap(BitmapFactory.decodeStream(in), width, height, false);
} catch (Exception e) {
e.printStackTrace();
}
return imgscr;
}
#Override
protected void onPostExecute(Bitmap bm)
{
img.setImageBitmap(bm);
}
}
}
#m0skit0 commented the actual reason of getting the ANR. You're out of your run-time memory when you're creating threads in an infinite loop. I'm pretty confused about your purpose though. I think you need to get the screenshots one after one and if this is the case, you can simply add a listener to the AsyncTask and get the callback when the screenshot is downloaded fully.
So if I've understood correctly, you need to declare an interface like this.
public interface DownloadCompletedListener {
public void onDownloadComplete(String result);
}
Now you need to implement the interface in your Activity like this
public class ScreenActivity extends AppCompatActivity implements DownloadCompletedListener {
private GetImg getImageTask;
private Bitmap imageBitmap;
#Override
public void onDownloadComplete(String result) {
if(result.equals("SUCCESS")) {
// Set the image now
img.setImageBitmap(imageBitmap);
// Start next download here
getImageTask = new GetImg();
getImageTask.mListener = this;
getImageTask.execute();
} else {
// Do something
}
}
}
You need to modify your AsyncTask a bit. You need to declare the DownloadCompletedListener.
public class GetImg extends AsyncTask<Object,Void,Bitmap> {
private DownloadCompletedListener mListener;
#Override
protected Bitmap doInBackground(Object[] params) {
Socket client= null;
try {
client = new Socket("192.168.1.5",6767);
InputStream in=client.getInputStream();
imgscr=Bitmap.createScaledBitmap(BitmapFactory.decodeStream(in), width, height, false);
} catch (Exception e) {
e.printStackTrace();
}
return imgscr;
}
#Override
protected String onPostExecute(Bitmap bm)
{
imageBitmap = bm;
mListener.onDownloadComplete("SUCCESS");
}
}
So your onCreate function will look like this now
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen);
img=(ImageView)findViewById(R.id.imageView);
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
// Start downloading image here. Remove the loop
getImageTask = new GetImg();
getImageTask.mListener = this;
getImageTask.execute();
}
i am making a gallery app and when i execute my asynctask in Getview of Adapter class then only onPreExecution part of Asynctask gets execute and others don't.
So, what i see is a progress bar But not the image after downloading...on my activity just a progress bar keeps on rolling
Here is my code of Getview method
enter public View getView(int position, View convertview, ViewGroup parent) {
// TODO Auto-generated method stub
img=new ImageView(mContext);
new DownloadImage().execute();
return img;
}
and this is my Asynctaskclass
private class DownloadImage extends AsyncTask<String, Void, Bitmap>{
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog = new ProgressDialog(mContext);
// Set progressdialog title
mProgressDialog.setTitle("Download Image");
// Set progressdialog message
mProgressDialog.setMessage("Loading...");
mProgressDialog.setIndeterminate(false);
// Show progressdialog
mProgressDialog.show();
}
#Override
protected Bitmap doInBackground(String... URL) {
// TODO Auto-generated method stub
String imageURL = URL[0];
Bitmap bitmap = null;
try {
// Download Image from URL
InputStream input = new java.net.URL(imageURL).openStream();
// Decode Bitmap
bitmap = BitmapFactory.decodeStream(input);
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
// Set the bitmap into ImageView
img.setImageBitmap(result);
// Close progressdialog
mProgressDialog.dismiss();
}
}
I think Just right after executing onPreExecution my GetView method return img variable to my MainActivity class..here it is
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
setTitle("My Gallery");
GridView g=(GridView)findViewById(R.id.gallery);
// Gallery g=(Gallery)findViewById(R.id.gallery);
// ImageAdapter width=new ImageAdapter(context);
g.setAdapter(new ImageAdapter(this));
Resources r = getResources();
float padding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
GRID_PADDING, r.getDisplayMetrics());
g.setNumColumns(NUM_OF_COLUMN);
g.setColumnWidth(columnWidth);
g.setStretchMode(GridView.NO_STRETCH);
g.setPadding((int) padding, (int) padding, (int) padding,
(int) padding);
// g.setHorizontalSpacing((int) padding);
// g.setVerticalSpacing((int) padding);
g.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView parent, View v, int position,
long id) {
// TODO Auto-generated method stub
Intent i=new Intent(getApplicationContext(),ImageViewPager.class);
i.putExtra("id", position);
startActivity(i);
}
});
Can anybody tell me how to proceed?
You shouldn't be running your AsyncTask in getView(). Since it is asynchronous, getView() won't wait for it to return. It will return a blank ImageView.
You should run the task before setting the adapter and get all of the images first.
You can also use some image loading library like Picaso. You can Google and find other libraries, as well, and how to use them. And you shouldn't be using StrictMode.
To get the images before running getView()
Run the task in onCreate(). Then simply set your Adapter in onPostExecute() of your task.
Related explanation
I am building an activity that shows two horizontal scroll views. The top one holds large images while the lower one holds the thumbnails of those images. When the user clicks on a thumbnail the upper scroll view will automatically scroll to the image corresponding to the thumbnail. My problem is that getWidth() method of layout always returns 0. I am creating the layout at runtime and then calling the getwidth() method so it should return the correct value but it is not.
public class ZoomActivity extends Activity {
private final String THUMBS="http://kurdshopping.net/thumbs/";
private final String UPLOADS="http://kurdshopping.net/uploads/";
private ImageView imageView;
private String path;
private String[] filenames;
private LinearLayout l1,l2;
private int[] widths=null;
private HorizontalScrollView hsv=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_zoom);
ActionBarUtils.setActionBar(this);
path = getIntent().getExtras().getString("path");
filenames=getIntent().getExtras().getStringArray("images");
widths=new int[filenames.length];
l1=(LinearLayout) findViewById(R.id.LinearLayout1);
l2=(LinearLayout) findViewById(R.id.LinearLayout2);
hsv=(HorizontalScrollView) findViewById(R.id.horizontalScrollView1);
for(int i=0; i<filenames.length; i++){
BitmapLoaderTask task = new BitmapLoaderTask(i);
task.execute(UPLOADS+filenames[i],"1");
}
for(int i=0;i<filenames.length;i++){
BitmapLoaderTask task = new BitmapLoaderTask(i);
task.execute(THUMBS+filenames[i],"2");
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.zoom, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
break;
// case R.id.action_all:
// Intent allitemIntent = new Intent(MainActivity.this,
// AllItemsActivity.class);
// startActivity(allitemIntent);
// break;
// case R.id.action_search:
// Intent search = new Intent(this, SearchDialogActivity.class);
// startActivity(search);
// break;
}
return super.onOptionsItemSelected(item);
}
private void setImageBitmap(Bitmap bmp) {
imageView = new ScrollableImageView(this);
imageView.setLayoutParams(new LayoutParams(bmp.getWidth(), bmp
.getHeight()));
imageView.setImageBitmap(bmp);
ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
root.addView(imageView);
}
private class BitmapLoaderTask extends AsyncTask<String, Void, Bitmap> {
private String layout;
private int index;
private int x_coords=0;
public BitmapLoaderTask(int index){
super();
this.index=index;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
setProgressBarIndeterminateVisibility(true);
}
#Override
protected synchronized Bitmap doInBackground(String... params) {
// AssetManager assets = getAssets();
Bitmap bmp = null;
layout=params[1];
try {
URL url = new URL(params[0]);
bmp = BitmapFactory.decodeStream(url.openConnection()
.getInputStream());
} catch (IOException e) {
Log.e("ZoomActivity", e.getMessage(), e);
}
return bmp;
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
View view=null;
try {
view=ImageUtils.insertPhoto(ZoomActivity.this, result);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(layout.equals("1")){
l1.addView(view);
view.setTag(x_coords);
x_coords+=((LinearLayout)view).getMeasuredWidth();// this is always returning 0, view.getLayoutParams().width is also same.
}else{
l2.addView(view);
ImageView img=(ImageView) ((LinearLayout)view).getChildAt(0);
img.setTag(index);
img.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int index=(Integer) v.getTag();
LinearLayout layout = (LinearLayout) l1.getChildAt(index);
int x=(Integer) layout.getTag();
hsv.scrollTo(x, 0);
}
});
}
// ImageView imageview=(ImageView) findViewById(R.id.imageView1);
// imageview.setImageBitmap(result);
// setImageBitmap(result);
setProgressBarIndeterminateVisibility(false);
}
}
}
The insertPhoto function where I am creating the layout-
public static View insertPhoto(final Activity activity, Bitmap bm) throws MalformedURLException, IOException {
LinearLayout layout = new LinearLayout(activity.getApplicationContext());
layout.setLayoutParams(new LayoutParams(bm.getWidth()+10, bm.getHeight()+10));
layout.setGravity(Gravity.CENTER);
final ImageView imageView = new ImageView(
activity.getApplicationContext());
imageView.setLayoutParams(new LayoutParams(bm.getWidth(), bm.getHeight()));
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setImageBitmap(bm);
// imageView.setTag(filename);
layout.addView(imageView);
return layout;
}
Thanks in advance for the help.
Edit: I am posting only the portion of the code that needs the width. I modified it to use viewtreeoserver but it still doesn't work -
l1.addView(view);
view.setTag(x_coords);
view.requestLayout();
ViewTreeObserver vto=view.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
x_coords+=((LinearLayout)view).getMeasuredWidth();
}
});
Try this code before using get width method-
yourlayout.requestLayout();
Hope this helps you!!!
If it is not working please let me know i will try to help you more.
Edit answer
try this code-
l1.addView(view);
view.setTag(x_coords);
view.requestLayout();
ViewTreeObserver vto=view.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
x_coords+=((LinearLayout)view).getMeasuredWidth();
}
});
I have this little piece of code and I want to achieve this: program should set a wallpaper from linked image.
ImgDownload:
public class ImgDownload extends AsyncTask {
private String requestUrl;
private ImageView view;
private Bitmap pic;
private ImgDownload(String requestUrl, ImageView view) {
this.requestUrl = requestUrl;
this.view = view;
}
#Override
protected Object doInBackground(Object... objects) {
try {
URL url = new URL(requestUrl);
URLConnection conn = url.openConnection();
pic = BitmapFactory.decodeStream(conn.getInputStream());
} catch (Exception ex) {
}
return null;
}
#Override
protected void onPostExecute(Object o) {
view.setImageBitmap(pic);
}
}
main
public class MainActivity extends Activity {
private ImageView img;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img= (ImageView)findViewById(R.id.img);
//!!!! This is where I am stuck :)
Object s = new ImgDownload("http://images1.wikia.nocookie.net/__cb20120402213849/masseffect/images/4/42/Uncharted_Worlds_Codex_Image.jpg",img );
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
How to instantiate/create this class in my mainActivity, so it could download img from link? Any help suggestions, thoughts, will be appreciated :)
You execute this AsyncTask like this:
ImgDownload downloader = new ImgDownload("http://images1.wikia.nocookie.net/__cb20120402213849/masseffect/images/4/42/Uncharted_Worlds_Codex_Image.jpg",img);
downloader.execute();
But I would not recommend using your code as it will produce memory leaks. For example try to rotate your device while it is downloading an image. I guarantee you your application will crash. Plus AsyncTask is a generic class. You could use that to make your code a little simpler. Here is my improved image download task:
public class ImgDownload extends AsyncTask<Void, Void, Bitmap> { // Use Generics
private final String requestUrl;
private final WeakReference<ImageView> imageViewReference; // Use WeakReference to prevent memory leaks
public ImgDownload(String requestUrl, ImageView view) {
this.requestUrl = requestUrl;
this.imageViewReference = new WeakReference<ImageView>(view);
}
#Override
protected Bitmap doInBackground(Void... objects) {
try {
URL url = new URL(requestUrl);
URLConnection conn = url.openConnection();
return BitmapFactory.decodeStream(conn.getInputStream()); // Return bitmap instead of using global variable
} catch (Exception ex) {
}
return null;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
ImageView imageView = imageViewReference.get();
if(imageView != null && bitmap != null) { // Check if image or ImageView are null
imageView.setImageBitmap(bitmap);
}
}
}
new ImgDownload("http://images1.wikia.nocookie.net/__cb20120402213849/masseffect/images/4/42/Uncharted_Worlds_Codex_Image.jpg", MainActivity.img).execute();
I am working with some Acitivitys , it's working pretty well. But i am having a strange delay on it.
And I figure it out that, it was about this part of the code, where I am loading stored image in the SDCard.
if(p.getAdress() != null){
Bitmap bitmap = BitmapFactory.decodeFile(p.getAdress());
new_image.setBackgroundDrawable(null);
new_image.setImageBitmap(bitmap);
}
Why this simple code is taking too long to execute?
How to solve it?
If I take this code off, everything works as i wished.
You shouldn't load large bitmaps directly on the UI thread.
Actually, the best reference to loading large Bitmaps efficiently can be found here.
And right here you can find good information on how you can load them using an AsyncTask.
This is the method they show you there (you can even download the sample!)
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private int data = 0;
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(Integer... params) {
data = params[0];
return decodeSampledBitmapFromResource(getResources(), data, 100, 100));
}
// Once complete, see if ImageView is still around and set bitmap.
#Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
public void loadBitmap(int resId, ImageView imageView) {
if (cancelPotentialWork(resId, imageView)) {
final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
final AsyncDrawable asyncDrawable =
new AsyncDrawable(getResources(), mPlaceHolderBitmap, task);
imageView.setImageDrawable(asyncDrawable);
task.execute(resId);
}
}
Your can try this way. It help you
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
if(p.getAdress() != null){
Bitmap bitmap = BitmapFactory.decodeFile(p.getAdress());
new_image.setBackgroundDrawable(null);
new_image.setImageBitmap(bitmap);
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}