I am displaying an image from a server in Android. For that I have gone through the tutorial Android Load Image From URL Example. It is very helpful. But it is taking 5 minutes to display the image from the server. So I want to display the image asynchronously. How can I do that?
The below snippets will help you.
DownloadHelper.java
public interface DownloadHelper
{
public void OnSucess(Bitmap bitmap);
public void OnFailure(String response);
}
MainActivity.java
public class GalleryExample extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
DownloadHelper downloadHelper = new DownloadHelper()
{
#Override
public void OnSucess(Bitmap bitmap)
{
ImageView imageView=(ImageView)findViewById(R.id.imageView);
imageView.setImageBitmap(bitmap);
}
#Override
public void OnFailure(String response)
{
Toast.makeText(context, response, Toast.LENGTH_LONG).show();
}
};
new MyTask(this,downloadHelper).execute("image url");
}
MyTask.java
public class DownloadTask extends AsyncTask<String, Integer, Object>
{
private Context context;
private DownloadHelper downloadHelper;
private ProgressDialog dialog;
public DownloadTask(Context context,DownloadHelper downloadHelper)
{
this.context = context;
}
#Override
protected void onPreExecute()
{
dialog = new ProgressDialog(context);
dialog.setTitle("Please Wait");
dialog.setMessage("Fetching Data!!");
dialog.setCancelable(false);
dialog.show();
super.onPreExecute();
}
#Override
protected Object doInBackground(String... params)
{
URL aURL = new URL(myRemoteImages[position]);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
/* Decode url-data to a bitmap. */
Bitmap bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
return bm;
}
#Override
protected void onPostExecute(Object result)
{
dialog.dismiss();
if (result != null)
{
downloadHelper.OnSucess((Bitmap)result);
}
else
{
downloadHelper.OnFailure("Error in Downloading Data!!");
}
super.onPostExecute(result);
}
}
Related
I have a class:
public class DownloadImageFromInternet extends AsyncTask<String, Void, Bitmap> {
private ImageView imageView;
public DownloadImageFromInternet(ImageView imageView) {
this.imageView = imageView;
}
protected Bitmap doInBackground(String... urls) {
String imageURL = urls[0];
Bitmap bimage = null;
try {
InputStream in = new java.net.URL(imageURL).openStream();
bimage = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error Message", e.getMessage());
e.printStackTrace();
}
return bimage;
}
protected void onPostExecute(Bitmap result) {
imageView.setImageBitmap(result);
}
}
I want to create a progress bar that will detect the loading of the image I download from the internet.
How to do it?
This is how it's done:
public class DownloadImageFromInternet extends AsyncTask<String, Void, Bitmap> {
private ImageView imageView;
private ProgressDialog pd;
public DownloadImageFromInternet(ImageView imageView) {
this.imageView = imageView;
}
protected void onPreExecute() {
pd = new ProgressDialog(); //Create dialog
pd.show(); // show dialog
}
protected Bitmap doInBackground(String... urls) {
...
..
return bimage;
}
protected void onPostExecute(Bitmap result) {
pd.dismiss();
...
}
}
I am trying to download image on button click through Async Task but the image is not downloading. Is there any problem with the download link in the String "image_url"?
Logcat - skia: --- SkImageDecoder::Factory returned null
public class DownloadImageAsyncTask extends AppCompatActivity {
Button button;
ImageView imageView;
String image_url = "http://www.freegreatdesign.com/files/images/6/2921-large-apple-icon-png-1.jpg";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.download_image_async_task);
button = (Button) findViewById(R.id.bDownload);
imageView = (ImageView) findViewById(R.id.downImage);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DownloadTask downloadTask = new DownloadTask();
downloadTask.execute(image_url);
}
});
}
class DownloadTask extends AsyncTask<String, Integer, String>
{
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(DownloadImageAsyncTask.this);
progressDialog.setTitle("Download in progress...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMax(100);
progressDialog.setProgress(0);
progressDialog.show();
}
#Override
protected String doInBackground(String... params) {
String path = params[0];
int file_length = 0;
try {
URL url = new URL(path);
URLConnection urlConnection = url.openConnection();
urlConnection.connect();
file_length = urlConnection.getContentLength();
File new_folder = new File("sdcard/photoalbum");
if(!new_folder.exists())
{
new_folder.mkdir();
}
File input_file = new File(new_folder, "downloaded_image.jpg");
InputStream inputStream = new BufferedInputStream(url.openStream(), 8192);
byte[] data = new byte[1024];
int total = 0;
int count = 0;
OutputStream outputStream = new FileOutputStream(input_file);
while((count=inputStream.read())!=-1)
{
total+=count;
outputStream.write(data, 0, count);
int progress = (int) total*100/file_length;
publishProgress(progress);
}
inputStream.close();
outputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "Download Complete...";
}
#Override
protected void onProgressUpdate(Integer... values) {
progressDialog.setProgress(values[0]);
}
#Override
protected void onPostExecute(String result) {
progressDialog.hide();
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show();
String path = "sdcard/photoalbum/downloaded_image.jpg";
imageView.setImageDrawable(Drawable.createFromPath(path));
}
}
}
when I tried to load only one image from url, it is working, but when I tried to load two images, it's just loading the last image.
This is what I've tried so far:
ProgressDialog pd;
private ImageView imgView1, imgView2;
private String strURLJohnA = "sample1.jpg";
private String strURLJohnR = "sample2.jpg";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.info);
back = (Button) findViewById (R.id.btBack);
back.setOnClickListener(this);
imgView1 = (ImageView) findViewById(R.id.ivInfo1);
imgView2 = (ImageView) findViewById (R.id.ivInfo2);
// Create an object for subclass of AsyncTask
GetXMLTask task = new GetXMLTask();
// Execute the task
task.execute(new String[] { strURLJohnA, strURLJohnR });
}
private class GetXMLTask extends AsyncTask<String, Void, Bitmap> {
#Override
protected Bitmap doInBackground(String... urls) {
Bitmap map = null;
for (String url : urls) {
map = downloadImage(url);
}
return map;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
pd = ProgressDialog.show(Info.this, "Please wait", "Downloading content", false, true);
}
// Sets the Bitmap returned by doInBackground
#Override
protected void onPostExecute(Bitmap result) {
imgView1.setImageBitmap(result);
imgView2.setImageBitmap(result);
pd.dismiss();
}
// Creates Bitmap from InputStream and returns it
private Bitmap downloadImage(String url) {
Bitmap bitmap = null;
InputStream stream = null;
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inSampleSize = 1;
try {
stream = getHttpConnection(url);
bitmap = BitmapFactory.
decodeStream(stream, null, bmOptions);
stream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return bitmap;
}
// Makes HttpURLConnection and returns InputStream
private InputStream getHttpConnection(String urlString)
throws IOException {
InputStream stream = null;
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
try {
HttpURLConnection httpConnection = (HttpURLConnection) connection;
httpConnection.setRequestMethod("GET");
httpConnection.connect();
if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
stream = httpConnection.getInputStream();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return stream;
}
}
Any ideas how to resolve the issue? I'd greatly appreciate your help. Thanks.
You a list instead as follows:
private class GetXMLTask extends AsyncTask<String, Void, ArrayList<Bitmap>> {
#Override
protected ArrayList<Bitmap> doInBackground(String... urls) {
ArrayList<Bitmap> map = new ArrayList<Bitmap>();
for (String url : urls) {
map.add(downloadImage(url));
}
return map;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
pd = ProgressDialog.show(Info.this, "Please wait", "Downloading content", false, true);
}
// Sets the Bitmap returned by doInBackground
#Override
protected void onPostExecute(ArrayList<Bitmap> result) {
imgView1.setImageBitmap(result.get(0));
imgView2.setImageBitmap(result.get(1));
pd.dismiss();
}
...
...
...
You need to return a list of Bitmap objects like I have shown in the code above. Then set the imageView to its respective bitmap.
(String... urls) is Var args. You dont need to pass a string array to it. Use as following code:
task.execute( strURLJohnA, strURLJohnR );
private class GetXMLTask extends AsyncTask<String, Void, ArrayList<Bitmap>> {
#Override
protected ArrayList<Bitmap> doInBackground(String... urls) {
ArrayList<Bitmap> map = new ArrayList<Bitmap>();
map.add(downloadImage(urls[0]));// I used as this for you to understand. You can use for each loop
map.add(downloadImage(urls[1]));
return map;
}
#Override
protected void onPostExecute(ArrayList<Bitmap> result) {
imgView1.setImageBitmap(result.get(0));
imgView2.setImageBitmap(result.get(1));
}
ProgressDialog pd;
private ImageView imgView1, imgView2;
//we can store any number of urls in a string array and load them at a time
private String[] str={"http://www.bogotobogo.com/images/rodin.jpg","http://www.bogotobogo.com/images/smalltiger.gif"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imgView1=(ImageView)findViewById(R.id.imageView1);
imgView2=(ImageView)findViewById(R.id.imageView2);
// Create an object for subclass of AsyncTask
GetXMLTask task = new GetXMLTask ();
// Execute the task
task.execute(str);
}
private class GetXMLTask extends AsyncTask<String, Void, ArrayList<Bitmap>> {
#Override
protected ArrayList<Bitmap> doInBackground(String... urls) {
ArrayList<Bitmap> map = new ArrayList<Bitmap>();
//enhanced for statement, mainly used for arrays
for (String url : urls) {
map.add(downloadImage(url));
}
return map;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
pd = ProgressDialog.show(Info.this, "Please wait", "Downloading content", false, true);
}
// Sets the Bitmap returned by doInBackground
#Override
protected void onPostExecute(ArrayList<Bitmap> result) {
imgView1.setImageBitmap(result.get(0));
imgView2.setImageBitmap(result.get(1));
pd.dismiss();
}
I currently have multiple activity that needs to perform an asynctask for http post and I wish to make the asynctask as another class file so that the different activity can call the asynctask to perform the http post request and onPostExecute, call the method httpResult(result) in the activity that called the asynctask. I have tried to pass the activity in but I am unable to call the method in onPostExecute. How can I do that?
public class MyActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_MyActivity);
//logic here...
AsyncHttpPost asyncHttpPost = new AsyncHttpPost("someContent", this, dialog);
JSONObject data = new JSONObject();
data.put("key", "value");
try {
asyncHttpPost.execute(data);
}
catch (Exception ex){
ex.printStackTrace();
}
}
public static void httpResult(String result) {
//this method has to get called by asynctask to make changes to the UI
}
}
AsyncHttpPost.java
public class AsyncHttpPost extends AsyncTask<JSONObject, String, String> {
String recvdjson;
String mData="";
private ProgressDialog dialog;
private Activity activity;
public AsyncHttpPost(String data, Activity activity, ProgressDialog dialog) {
mData = data;
this.activity = activity;
this.dialog = dialog;
}
protected void onPreExecute()
{
dialog.show();
}
#Override
protected String doInBackground(JSONObject... params) {
//logic to do http request
return "someStringResult";
}
protected void onPostExecute(String result) {
dialog.dismiss();
activity.httpResult(result); //This line gives me error : The method httpResult(String) is undefined for the type Activity
}
}
Create an Interface called HttpResponseImpl in a seperate file and add the required method httpResult
interface HttpResponseImpl{
public void httpResult(String result);
}
Now implement this interface by you Activity class
public class MyActivity extends Activity implements HttpResponseImpl{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_MyActivity);
//logic here...
AsyncHttpPost asyncHttpPost = new AsyncHttpPost("someContent", this, dialog);
JSONObject data = new JSONObject();
data.put("key", "value");
try {
asyncHttpPost.execute(data);
}
catch (Exception ex){
ex.printStackTrace();
}
}
public void httpResult(String result){
//this method has to get called by asynctask to make changes to the UI
}
}
And your AsyncHttpPost class would be.
public class AsyncHttpPost extends AsyncTask<JSONObject, String, String> {
String recvdjson;
String mData="";
private ProgressDialog dialog;
private HttpResponseImpl httpResponseImpl;
public AsyncHttpPost(String data, HttpResponseImpl httpResponseImpl, ProgressDialog dialog) {
mData = data;
this.httpResponseImpl = httpResponseImpl;
this.dialog = dialog;
}
protected void onPreExecute()
{
dialog.show();
}
#Override
protected String doInBackground(JSONObject... params) {
//logic to do http request
return "someStringResult";
}
protected void onPostExecute(String result) {
dialog.dismiss();
httpResponseImpl.httpResult(result);
}
}
Implements this HttpResponseImpl interface with all you Activity class from which you want to do HttpRequest.
Generic AsyncTask Example
Call it like
new RetrieveFeedTask(new OnTaskFinished()
{
#Override
public void onFeedRetrieved(String feeds)
{
//do whatever you want to do with the feeds
}
}).execute("http://enterurlhere.com");
RetrieveFeedTask.class
class RetrieveFeedTask extends AsyncTask<String, Void, String>
{
String HTML_response= "";
OnTaskFinished onOurTaskFinished;
public RetrieveFeedTask(OnTaskFinished onTaskFinished)
{
onOurTaskFinished = onTaskFinished;
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
#Override
protected String doInBackground(String... urls)
{
try
{
URL url = new URL(urls[0]); // enter your url here which to download
URLConnection conn = url.openConnection();
// open the stream and put it into BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
while ((inputLine = br.readLine()) != null)
{
// System.out.println(inputLine);
HTML_response += inputLine;
}
br.close();
System.out.println("Done");
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return HTML_response;
}
#Override
protected void onPostExecute(String feed)
{
onOurTaskFinished.onFeedRetrieved(feed);
}
}
OnTaskFinished.java
public interface OnTaskFinished
{
public void onFeedRetrieved(String feeds);
}
i want to donload image from server asynchronously but when i run it force close....and gives msg on log cat... An error occured while executing doInBackground()...whats the problem pls help me..pls pls
public class artspacedetailShowingNow extends Activity implements OnClickListener {
private int imageCounter = 0;
private ProgressDialog bar;
private ImageView imageLoader;
private String[] imageList = {"http://www.artealdiaonline.com/var/artealdia_com/storage/images/argentina/directorio/galerias/ruth_benzacar/artistas/martin_di_girolamo._diosas/198915-1-esl-AR/MARTIN_DI_GIROLAMO._Diosas.jpg","http://www.artealdiaonline.com/var/artealdia_com/storage/images/argentina/directorio/galerias/ruth_benzacar/artistas/jorge_macchi._la_espera/198929-1-esl-AR/JORGE_MACCHI._La_espera.jpg","http://www.artealdiaonline.com/var/artealdia_com/storage/images/argentina/directorio/galerias/ruth_benzacar/artistas/leon_ferrari._hongo_nuclear/198950-1-esl-AR/LEON_FERRARI._Hongo_Nuclear.jpg","http://www.artealdiaonline.com/var/artealdia_com/storage/images/argentina/directorio/galerias/ruth_benzacar/artistas/martin_sastre._fiebre/198922-1-esl-AR/MARTIN_SASTRE._Fiebre.jpg"};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.showingnow);
imageLoader = (ImageView) findViewById(R.id.imageLoader);
//imageLoader.setImageResource(image1);
Button next = (Button) findViewById(R.id.next);
Button back = (Button) findViewById(R.id.back);
next.setOnClickListener(this);
back.setOnClickListener(this);
back.setEnabled(false);
new ImageDownload().execute(imageList[imageCounter]);
}
#Override
public void onClick(View v)
{
String imagePath = null;
// imagePath = imageList[imageCounter];
}
new ImageDownload().execute(imagePath);
}
private void loadImage(String imagePath)
{
try {
/* Open a new URL and get the InputStream to load data from it. */
URL aURL = new URL(imagePath);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
/* Buffered is always good for a performance plus. */
BufferedInputStream bis = new BufferedInputStream(is);
/* Decode url-data to a bitmap. */
Bitmap bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
imageLoader.setImageBitmap(bm);
imageLoader.setImageBitmap(bm);
} catch (IOException e)
{
Log.e("DEBUGTAG", "Remote Image Exception", e);
}
}
private class ImageDownload extends AsyncTask<String , Void, Void>
{
#Override
protected Void doInBackground(String... params) {
loadImage(params[0]);
return null;
}
#Override
protected void onPostExecute(Void result) {
}
#Override
protected void onPreExecute() {
}
}
}
try this
private class ImageDownload extends AsyncTask<String , Void, Void>
{
Bitmap imBitmap;
#Override
protected Void doInBackground(String... params) {
try {
/* Open a new URL and get the InputStream to load data from it. */
URL aURL = new URL(params[0]);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
/* Buffered is always good for a performance plus. */
BufferedInputStream bis = new BufferedInputStream(is);
/* Decode url-data to a bitmap. */
Bitmap bm = BitmapFactory.decodeStream(bis);
imBitmap=bm;
bis.close();
is.close();
} catch (IOException e)
{
Log.e("DEBUGTAG", "Remote Image Exception", e);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
imageLoader.setImageBitmap(imBitmap);
imageLoader.setImageBitmap(imBitmap);
}
#Override
protected void onPreExecute() {
}
}
you cant use imageLoader.setImageBitmap(imBitmap); in doinBackground.
You look like you are accessing your ImageView from within doInBackground. That is not allowed.
Manipulating UI elements can only be done from the UI thread.
If you read AsyncTask, you'll see that doInBackground is executed in another thread, while onPreExecute, onProgressUpdate and onPostExecute is executed in the UI thread.
Handle UI elements in the methods I mentioned above, or post a runnable like TofferJ suggested.
You need to use the UI Thread when doing things that affects the UI. Depending on where the background thread is started from either use:
runOnUiThread(new Runnable() {
#Override
public void run() {
imageLoader.setImageBitmap(bm);
imageLoader.setImageBitmap(bm);
}
});
or
imageLoader.post(new Runnable() {
#Override
public void run() {
imageLoader.setImageBitmap(bm);
imageLoader.setImageBitmap(bm);
}
});
Both of the snippets above will make sure that the correct thread is used to update your UI. Make sure to always do this when modifying the UI (setting images, updating texts etc) from another tread and you will stay out of trouble. :)