/** * Filename: DownloadImageTask.java (in org.repin.android.net) * This file is part of the Redpin project. * * Redpin is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * any later version. * * Redpin is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Redpin. If not, see <http://www.gnu.org/licenses/>. * * (c) Copyright ETH Zurich, Luba Rogoleva, Pascal Brogle, Philipp Bolliger, 2010, ALL RIGHTS RESERVED. * * www.redpin.org */ package org.redpin.android.net; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.security.MessageDigest; import org.redpin.android.ApplicationContext; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Bitmap.CompressFormat; import android.os.AsyncTask; import android.util.Log; import android.view.WindowManager.BadTokenException; /** * {@link AsyncTask} for downloading images in the background and saving them * locally if not yet cached. * * @author Pascal Brogle (broglep@student.ethz.ch) * @author Luba Rogoleva (lubar@student.ethz.ch) * */ public class DownloadImageTask extends AsyncTask<String, Void, String> { private static final String TAG = DownloadImageTask.class.getSimpleName(); private static final String FILE_EXT = ".jpg"; private Context context = ApplicationContext.get(); private DownloadImageTaskCallback callback; private String url; public DownloadImageTask() { } public DownloadImageTask(DownloadImageTaskCallback callback) { this.callback = callback; } /** * Checks if images is already cached. If not downloads the images and * caches it. * * @param params * URL of image to be downloaded (only first is considered) * @return Absolute file path to the cached image */ @Override protected String doInBackground(String... params) { Bitmap bm = null; if (params.length == 0) return null; String urlStr = params[0]; url = urlStr; String md5 = ""; try { md5 = md5(urlStr); File f = context.getFileStreamPath(md5 + FILE_EXT); if (f.exists()) { return f.getAbsolutePath(); } } catch (FileNotFoundException fnf) { } catch (Exception e1) { } InputStream is = null; try { if (urlStr != null && url.indexOf("http://{HOST}:{PORT}") != -1) { urlStr = urlStr.replace("{HOST}", ConnectionHandler.host); urlStr = urlStr.replace("{PORT}", ConnectionHandler.port + ""); } URL url = new URL(urlStr); URLConnection conn = url.openConnection(); conn.connect(); is = conn.getInputStream(); bm = BitmapFactory.decodeStream(is); } catch (IOException e) { Log.i(TAG, "Download of image failed: " + e.getMessage()); } finally { if (is != null) { try { is.close(); } catch (IOException e) { } } } if (bm != null) { FileOutputStream fos = null; try { fos = context.openFileOutput(md5 + FILE_EXT, Context.MODE_WORLD_READABLE); bm.compress(CompressFormat.JPEG, 90, fos); } catch (Exception e) { Log.e(TAG, "Storage of image failed: " + e.getMessage()); } finally { if (fos != null) { try { fos.flush(); fos.close(); } catch (IOException e) { } } if (bm != null) { bm.recycle(); } } } File f = context.getFileStreamPath(md5 + FILE_EXT); if (f.exists()) { return f.getAbsolutePath(); } return null; } /** * Calls the callback (if supplied) after the image is downloaded * * @param result * Absolute file path of cached image */ @Override protected void onPostExecute(String result) { if (callback != null) { try { if (result != null) { callback.onImageDownloaded(url, result); } else { callback.onImageDownloadFailure(url); } } catch (BadTokenException e) { Log.w(TAG, "Callback failed, caught BadTookenException: " + e.getMessage(), e); } catch (Exception e) { Log.w(TAG, "Callback failed, caught Exception: " + e.getMessage(), e); } callback = null; url = null; context = null; } } /** * * @param s * URL of image * @return md5 hash value of image URL * @throws Exception */ static protected String md5(String s) throws Exception { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(s.getBytes()); byte digest[] = md.digest(); StringBuffer result = new StringBuffer(); for (int i = 0; i < digest.length; i++) { result.append(Integer.toHexString(0xFF & digest[i])); } return result.toString(); } /** * Callback Interface for {@link DownloadImageTask} * * @author Pascal Brogle (broglep@student.ethz.ch) * */ public interface DownloadImageTaskCallback { /** * * @param url * URL of the image that was downloaded * @param path * Absolute path of the downloaded and cached image */ public void onImageDownloaded(String url, String path); public void onImageDownloadFailure(String url); } }