简体   繁体   中英

Android Java Coding: How To Access Downloaded Images For List View

Working learning by modifying tutorial code to try different things. I'm still in the serious learning phase here so please excuse the question if it sounds ignorant. I have the following code I'm working with to download image files via a parsed XML file (from a tutorial/example):

public class ImageDownloader {

Map<String,Bitmap> imageCache;

public ImageDownloader(){
    imageCache = new HashMap<String, Bitmap>();

}

//download function
public void download(String url, ImageView imageView) {
     if (cancelPotentialDownload(url, imageView)) {

         //Caching code right here
         String filename = url.substring(url.lastIndexOf('/') + 1);
         File f = new File(getCacheDirectory(imageView.getContext()), filename);

          // Is the bitmap in our memory cache?
         Bitmap bitmap = null;

          bitmap = (Bitmap)imageCache.get(f.getPath());

          if(bitmap == null){

              bitmap = BitmapFactory.decodeFile(f.getPath());

              if(bitmap != null){
                  imageCache.put(f.getPath(), bitmap);
              }

          }
          //No? download it
          if(bitmap == null){
              BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
              DownloadedDrawable downloadedDrawable = new   DownloadedDrawable(task);
              imageView.setImageDrawable(downloadedDrawable);
              task.execute(url);
          }else{
              //Yes? set the image
              imageView.setImageBitmap(bitmap);
          }
     }
}

//cancel a download (internal only)
private static boolean cancelPotentialDownload(String url, ImageView imageView) {
    BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

    if (bitmapDownloaderTask != null) {
        String bitmapUrl = bitmapDownloaderTask.url;
        if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
            bitmapDownloaderTask.cancel(true);
        } else {
            // The same URL is already being downloaded.
            return false;
        }
    }
    return true;
}

//gets an existing download if one exists for the imageview
private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
    if (imageView != null) {
        Drawable drawable = imageView.getDrawable();
        if (drawable instanceof DownloadedDrawable) {
            DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
            return downloadedDrawable.getBitmapDownloaderTask();
        }
    }
    return null;
}

//our caching functions
// Find the dir to save cached images
private static File getCacheDirectory(Context context){
    String sdState = android.os.Environment.getExternalStorageState();
    File cacheDir;

    if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
        File sdDir = android.os.Environment.getExternalStorageDirectory();  

        //TODO : Change your diretcory here
        cacheDir = new File(sdDir,"data/fresh/images");
    }
    else
        cacheDir = context.getCacheDir();

    if(!cacheDir.exists())
        cacheDir.mkdirs();
        return cacheDir;
}

private void writeFile(Bitmap bmp, File f) {
      FileOutputStream out = null;

      try {
        out = new FileOutputStream(f);
        bmp.compress(Bitmap.CompressFormat.PNG, 80, out);
      } catch (Exception e) {
        e.printStackTrace();
      }
      finally { 
        try { if (out != null ) out.close(); }
        catch(Exception ex) {} 
      }
}
///////////////////////

//download asynctask
public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
    private String url;
    private final WeakReference<ImageView> imageViewReference;

    public BitmapDownloaderTask(ImageView imageView) {
        imageViewReference = new WeakReference<ImageView>(imageView);
    }

    @Override
    // Actual download method, run in the task thread
    protected Bitmap doInBackground(String... params) {
         // params comes from the execute() call: params[0] is the url.
         url = (String)params[0];
         return downloadBitmap(params[0]);
    }

    @Override
    // Once the image is downloaded, associates it to the imageView
    protected void onPostExecute(Bitmap bitmap) {
        if (isCancelled()) {
            bitmap = null;
        }

        if (imageViewReference != null) {
            ImageView imageView = imageViewReference.get();
            BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
            // Change bitmap only if this process is still associated with it
            if (this == bitmapDownloaderTask) {
                imageView.setImageBitmap(bitmap);

                //cache the image

                String filename = url.substring(url.lastIndexOf('/') + 1);
                //String filename = String.valueOf(url.hashCode());
                File f = new File(getCacheDirectory(imageView.getContext()), filename);

                imageCache.put(f.getPath(), bitmap);

                writeFile(bitmap, f);
            }
        }
    }


}

static class DownloadedDrawable extends ColorDrawable {
    private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;

    public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
        super(Color.BLACK);
        bitmapDownloaderTaskReference =
            new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
    }

    public BitmapDownloaderTask getBitmapDownloaderTask() {
        return bitmapDownloaderTaskReference.get();
    }
}

//the actual download code
static Bitmap downloadBitmap(String url) {
    HttpParams params = new BasicHttpParams();
    params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
    HttpClient client = new DefaultHttpClient(params);
    final HttpGet getRequest = new HttpGet(url);

    try {
        HttpResponse response = client.execute(getRequest);
        final int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != HttpStatus.SC_OK) { 
            Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url); 
            return null;
        }

        final HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream inputStream = null;
            try {
                inputStream = entity.getContent(); 
                final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                return bitmap;
            } finally {
                if (inputStream != null) {
                    inputStream.close();  
                }
                entity.consumeContent();
            }
        }
    } catch (Exception e) {
        // Could provide a more explicit error message for IOException or IllegalStateException
        getRequest.abort();
        Log.w("ImageDownloader", "Error while retrieving bitmap from " + url + e.toString());
    } finally {
        if (client != null) {
            //client.close();
        }
    }
    return null;
}
}

Then I have a list view with the following code to get the images:

  String uri = "drawable/"+ downloadedImgs.get(position).get(KEY_ICON);
          int imageResource =   holwtt.getContext().getApplicationContext().getResources().getIdentifier(uri, null, holwtt.getContext().getApplicationContext().getPackageName());
          Drawable image = holwtt.getContext().getResources().getDrawable(imageResource);
          holder.firstImg.setImageDrawable(image);

I think I understand that using the getResources() is not what I need to access the images. Problem is everything I've tried does not work, getPath() etc. The images will be used in the app but will change so including them in the apk is not an option. Also trying to take into account whether a sd card is installed or not so there is the issue of not using hard-coded directory paths. I appreciate suggestions and comments.

There are a lot of things that aren't quite right in this code. As you're learning, I'm gonna give you some sample code so you can get started and keep you going with some better direction. Note that yourcode can be improved by the use of HttpUrlConnection instead of HttpClient as recommended by the Android docs. Also note, that the url of the images is converted to an integer hash so you can use that as the name of your file. Internal or external storage can be used as well. This is only the AsyncTask, I hope you dig a little more and get to create the image adapter yourself. Keep on!

public static class ImageCacher extends AsyncTask<String, String, Integer>{

    Context context;
    ImageView iv;
    Bitmap b;


    public ImageCacher(Context context, ImageView iv){
        this.context = context;
        this.iv = iv;
    }

    @Override
    protected Integer doInBackground(String... params) {

        for(String p:params){
            //Modification to get relative urls
            final String param;
            if(!p.startsWith("http")){
                param = URL_BASE+p;
            }else{
                param = p;
            }

            //check if already CACHED
            File file = getFileForCachedImage(param);

            b = getCachedImage(file);
            if(b != null){
                if(iv != null){
                    iv.post(new Runnable() {

                        public void run() {
                            String tag = (String) iv.getTag();
                            if(tag != null){
                                if(tag.matches(param))
                                    iv.setImageBitmap(b);
                            }

                        }
                    });
                }

                return 0;
            }else{
                file.delete();
            }

            //download
            //file = new File(context.getFilesDir(), filename); //OLD way
            file = getFileForCachedImage(param);
            b = saveImageFromUrl(context, param);
            if(b != null){
                if(iv != null){
                    iv.post(new Runnable() {

                        public void run() {
                            String tag = (String) iv.getTag();
                            if(tag != null){
                                if(tag.matches(param))
                                    iv.setImageBitmap(b);
                            }

                        }
                    });
                }
            }
        }

        return 0;
    }

}

/**
 * Gets an image given its url
 * @param param
 */
public static Bitmap saveImageFromUrl(Context context, String fullUrl) {
    Bitmap b = null;

    try {
        URL url = new URL(fullUrl);
        URLConnection conn = url.openConnection();
        conn.setDoInput(true);
        conn.connect();
        //save bitmap to file
        InputStream is = conn.getInputStream();
        //String filename = String.format("%d", fullUrl.hashCode()); //ORIGINAL way
        //File file = new File(context.getFilesDir(), filename);    //original way
        File file = getFileForCachedImage(fullUrl);
        if(file.exists()){
            //delete
            file.delete();
            file=null;
        }
        //file = new File(context.getFilesDir(), filename);  //ORIGINAL way
        file = getFileForCachedImage(fullUrl);

        FileOutputStream out = new FileOutputStream(file);
        byte buffer[] = new byte[256];
        while(true){
            int cnt = is.read(buffer);
            if(cnt <=0){
                break;
            }
            out.write(buffer,0, cnt);
        }

        out.flush();
        out.close();
        is.close();

        b = BitmapFactory.decodeFile(file.getAbsolutePath());

    } catch (Exception e) {
    //  e.printStackTrace();
    }

    return b;
}

/**
 * Gets the file to cache the image
 * @param url
 * @return
 */
public static File getFileForCachedImage(String url) {

    /**
     * Modification for relative urls
     */
    if(!url.startsWith("http")){
        url = URL_BASE+url;
    }

    String filename = String.format("%d.cached", url.hashCode());

    /**
     * External storage
     */
    File file = new File(Environment.getExternalStorageDirectory(), EXT_DIR_NAME+"/"+filename);  //EXTERNAL storage
    String parent = file.getParent();
    if(parent != null){
        new File(parent).mkdirs();
    }

    /**
     * Internal storage
     */
    //File file = new File(context.getFilesDir(), filename);  //INTERNAL storage

    return file;

}

/**
 * Returns a bitmap object if cached
 * @param file
 * @return
 */
public static Bitmap getCachedImage(File file) {

    try {
        return BitmapFactory.decodeFile(file.getAbsolutePath());
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM