@Override
 public void downloadFinished(URI uri) {
   if (!TiResponseCache.peek(uri)) {
     // The requested image did not make it into our TiResponseCache,
     // possibly because it had a header forbidding that. Now get it
     // via the "old way" (not relying on cache).
     synchronized (imageTokenGenerator) {
       token = imageTokenGenerator.incrementAndGet();
       if (uri.toString().equals(currentUrl)) {
         makeImageSource(uri.toString())
             .getBitmapAsync(new BgImageLoader(requestedWidth, requestedHeight, token));
       }
     }
   } else {
     firedLoad = false;
     if (uri.toString().equals(currentUrl)) {
       ImageArgs imageArgs =
           new ImageArgs(
               makeImageSource(uri.toString()),
               getParentView(),
               requestedWidth,
               requestedHeight,
               true,
               false);
       BackgroundImageTask task = new BackgroundImageTask();
       try {
         task.execute(imageArgs);
       } catch (RejectedExecutionException e) {
         Log.e(TAG, "Cannot load the image. Loading too many images at the same time.");
       }
     }
   }
 }
  public static InputStream openCachedStream(URI uri) {
    TiResponseCache rc = (TiResponseCache) TiResponseCache.getDefault();
    if (rc == null) {
      return null;
    }

    if (rc.cacheDir == null) {
      return null;
    }

    String hash = DigestUtils.shaHex(uri.toString());
    File hFile = new File(rc.cacheDir, hash + HEADER_SUFFIX);
    File bFile = new File(rc.cacheDir, hash + BODY_SUFFIX);

    if (!bFile.exists() || !hFile.exists()) {
      return null;
    }

    try {
      return new FileInputStream(bFile);
    } catch (FileNotFoundException e) {
      // Fallback to URL download?
      return null;
    }
  }
  public void postOnCreate() {
    TiConfig.LOGD = systemProperties.getBool("ti.android.debug", false);

    // Register the default cache handler
    File cacheDir = new File(new TiFileHelper(this).getDataDirectory(false), "remote-image-cache");
    if (!cacheDir.exists()) {
      cacheDir.mkdirs();
    }
    TiResponseCache.setDefault(new TiResponseCache(cacheDir.getAbsoluteFile(), this));
  }
    @Override
    protected Bitmap doInBackground(final ImageArgs... params) {
      final ImageArgs imageArgs = params[0];

      recycle = imageArgs.mRecycle;
      mNetworkURL = imageArgs.mNetworkURL;
      Bitmap bitmap = null;

      mUrl = imageArgs.mImageref.getUrl();

      if (mNetworkURL) {
        boolean getAsync = true;
        try {
          String imageUrl = TiUrl.getCleanUri(imageArgs.mImageref.getUrl()).toString();

          URI uri = new URI(imageUrl);
          getAsync = !TiResponseCache.peek(uri); // expensive, don't want to do in UI thread
        } catch (URISyntaxException e) {
          Log.e(TAG, "URISyntaxException for url " + imageArgs.mImageref.getUrl(), e);
          getAsync = false;
        } catch (NullPointerException e) {
          Log.e(TAG, "NullPointerException for url " + imageArgs.mImageref.getUrl(), e);
          getAsync = false;
        } catch (Exception e) {
          Log.e(TAG, "Caught exception for url" + imageArgs.mImageref.getUrl(), e);
        }
        if (getAsync) {
          //
          // We've got to start the download back on the UI thread, if we do it on one
          // of the AsyncTask threads it will throw an exception.
          //
          mAsync = true;

          TiMessenger.getMainMessenger()
              .post(
                  new Runnable() {
                    @Override
                    public void run() {
                      imageArgs.mImageref.getBitmapAsync(imageDownloadListener);
                    }
                  });

        } else {
          bitmap =
              (imageArgs.mImageref)
                  .getBitmap(
                      imageArgs.mView, imageArgs.mRequestedWidth, imageArgs.mRequestedHeight);
        }
      } else {
        bitmap =
            (imageArgs.mImageref)
                .getBitmap(imageArgs.mView, imageArgs.mRequestedWidth, imageArgs.mRequestedHeight);
      }
      return bitmap;
    }
  public static void remove(URI uri) {
    TiResponseCache rc = (TiResponseCache) TiResponseCache.getDefault();
    if (rc == null) return;
    if (rc.cacheDir == null) return;

    String hash = DigestUtils.shaHex(uri.toString());
    File hFile = new File(rc.cacheDir, hash + HEADER_SUFFIX);
    File bFile = new File(rc.cacheDir, hash + BODY_SUFFIX);
    if (bFile.exists()) bFile.delete();
    if (hFile.exists()) hFile.delete();
  }
  public static boolean peek(URI uri) {
    TiResponseCache rc = (TiResponseCache) TiResponseCache.getDefault();
    if (rc == null) return false;
    if (rc.cacheDir == null) return false;

    String hash = DigestUtils.shaHex(uri.toString());
    File hFile = new File(rc.cacheDir, hash + HEADER_SUFFIX);
    File bFile = new File(rc.cacheDir, hash + BODY_SUFFIX);
    if (!bFile.exists() || !hFile.exists()) return false;
    return true;
  }
  @Override
  public void processProperties(KrollDict d) {
    TiImageView view = getView();
    if (view == null) {
      return;
    }

    if (d.containsKey(TiC.PROPERTY_WIDTH)) {
      requestedWidth = TiConvert.toTiDimension(d, TiC.PROPERTY_WIDTH, TiDimension.TYPE_WIDTH);
    }
    if (d.containsKey(TiC.PROPERTY_HEIGHT)) {
      requestedHeight = TiConvert.toTiDimension(d, TiC.PROPERTY_HEIGHT, TiDimension.TYPE_HEIGHT);
    }

    if (d.containsKey(TiC.PROPERTY_IMAGES)) {
      setImageSource(d.get(TiC.PROPERTY_IMAGES));
      setImages();
    } else if (d.containsKey(TiC.PROPERTY_URL)) {
      Log.w(LCAT, "The url property of ImageView is deprecated, use image instead.");
      if (!d.containsKey(TiC.PROPERTY_IMAGE)) {
        d.put(TiC.PROPERTY_IMAGE, d.get(TiC.PROPERTY_URL));
      }
    }
    if (d.containsKey(TiC.PROPERTY_CAN_SCALE)) {
      view.setCanScaleImage(TiConvert.toBoolean(d, TiC.PROPERTY_CAN_SCALE));
    }
    if (d.containsKey(TiC.PROPERTY_ENABLE_ZOOM_CONTROLS)) {
      view.setEnableZoomControls(TiConvert.toBoolean(d, TiC.PROPERTY_ENABLE_ZOOM_CONTROLS));
    }
    if (d.containsKey(TiC.PROPERTY_DEFAULT_IMAGE)) {
      Object defaultImage = d.get(TiC.PROPERTY_DEFAULT_IMAGE);
      try {
        Object image = d.get(TiC.PROPERTY_IMAGE);

        if (image instanceof String) {
          String imageUrl = (String) image;
          URI imageUri = new URI(imageUrl);
          if (URLUtil.isNetworkUrl(imageUrl) && !TiResponseCache.peek(imageUri)) {
            setDefaultImageSource(defaultImage);
          }

        } else if (image == null) {
          setDefaultImageSource(defaultImage);
        }

      } catch (URISyntaxException e) {
        setDefaultImageSource(defaultImage);
      }
    }
    if (d.containsKey(TiC.PROPERTY_IMAGE)) {
      // processProperties is also called from TableView, we need check if we changed before
      // re-creating the
      // bitmap
      boolean changeImage = true;
      Object newImage = d.get(TiC.PROPERTY_IMAGE);
      TiDrawableReference source = makeImageSource(newImage);
      if (imageSources != null && imageSources.size() == 1) {
        if (imageSources.get(0).equals(source)) {
          changeImage = false;
        }
      }
      if (changeImage) {
        setImageSource(source);
        firedLoad = false;
        setImage(false);
      }

    } else {
      if (!d.containsKey(TiC.PROPERTY_IMAGES)) {
        getProxy().setProperty(TiC.PROPERTY_IMAGE, null);
        if (defaultImageSource != null) {
          setDefaultImage();
        }
      }
    }

    super.processProperties(d);
  }
 private void setImage(boolean recycle) {
   if (imageSources == null
       || imageSources.size() == 0
       || imageSources.get(0) == null
       || imageSources.get(0).isTypeNull()) {
     if (defaultImageSource != null) {
       setDefaultImage();
     } else {
       setImage(null);
     }
     return;
   }
   if (imageSources.size() == 1) {
     if (imageViewProxy.inTableView()) {
       Bitmap currentBitmap = imageViewProxy.getBitmap();
       if (currentBitmap != null) {
         // If the image proxy has the default image currently cached, we need to
         // load the downloaded URL instead. TIMOB-4814
         ArrayList<TiDrawableReference> proxySources = imageViewProxy.getImageSources();
         if (proxySources != null && !proxySources.contains(defaultImageSource)) {
           setImage(currentBitmap);
           return;
         }
       }
     }
     TiDrawableReference imageref = imageSources.get(0);
     if (imageref.isNetworkUrl()) {
       if (defaultImageSource != null) {
         setDefaultImage();
       } else {
         TiImageView view = getView();
         if (view != null) {
           view.setImageDrawable(null, recycle);
         }
       }
       boolean getAsync = true;
       try {
         URI uri = new URI(imageref.getUrl());
         getAsync = !TiResponseCache.peek(uri);
       } catch (URISyntaxException e) {
         Log.e(LCAT, "URISyntaxException for url " + imageref.getUrl(), e);
         getAsync = false;
       }
       if (getAsync) {
         imageref.getBitmapAsync(downloadListener);
       } else {
         Bitmap bitmap = imageref.getBitmap(getParentView(), requestedWidth, requestedHeight);
         if (bitmap != null) {
           setImage(bitmap);
           if (!firedLoad) {
             fireLoad(TiC.PROPERTY_IMAGE);
             firedLoad = true;
           }
         } else {
           retryDecode(recycle);
         }
       }
     } else {
       setImage(imageref.getBitmap(getParentView(), requestedWidth, requestedHeight));
       if (!firedLoad) {
         fireLoad(TiC.PROPERTY_IMAGE);
         firedLoad = true;
       }
     }
   } else {
     setImages();
   }
 }
  @Override
  public void processProperties(KrollDict d) {
    TiImageView view = getView();
    View parentView = getParentView();

    if (view == null) {
      return;
    }

    if (d.containsKey(TiC.PROPERTY_WIDTH)) {
      if (TiC.LAYOUT_FILL.equals(d.getString(TiC.PROPERTY_WIDTH)) && parentView != null) {
        // Use the parent's width when it's fill
        requestedWidth =
            TiConvert.toTiDimension(parentView.getMeasuredWidth(), TiDimension.TYPE_WIDTH);
      } else {
        requestedWidth = TiConvert.toTiDimension(d, TiC.PROPERTY_WIDTH, TiDimension.TYPE_WIDTH);
      }
    }
    if (d.containsKey(TiC.PROPERTY_HEIGHT)) {
      // Use the parent's height when it's fill
      if (TiC.LAYOUT_FILL.equals(d.getString(TiC.PROPERTY_HEIGHT)) && parentView != null) {
        requestedHeight =
            TiConvert.toTiDimension(parentView.getMeasuredHeight(), TiDimension.TYPE_HEIGHT);
      } else {
        requestedHeight = TiConvert.toTiDimension(d, TiC.PROPERTY_HEIGHT, TiDimension.TYPE_HEIGHT);
      }
    }

    if (d.containsKey(TiC.PROPERTY_IMAGES)) {
      setImageSource(d.get(TiC.PROPERTY_IMAGES));
      setImages();
    } else if (d.containsKey(TiC.PROPERTY_URL)) {
      Log.w(TAG, "The url property of ImageView is deprecated, use image instead.");
      if (!d.containsKey(TiC.PROPERTY_IMAGE)) {
        d.put(TiC.PROPERTY_IMAGE, d.get(TiC.PROPERTY_URL));
      }
    }
    if (d.containsKey(TiC.PROPERTY_CAN_SCALE)) {
      view.setCanScaleImage(TiConvert.toBoolean(d, TiC.PROPERTY_CAN_SCALE));
    }
    if (d.containsKey(TiC.PROPERTY_ENABLE_ZOOM_CONTROLS)) {
      view.setEnableZoomControls(TiConvert.toBoolean(d, TiC.PROPERTY_ENABLE_ZOOM_CONTROLS));
    }
    if (d.containsKey(TiC.PROPERTY_DEFAULT_IMAGE)) {
      Object defaultImage = d.get(TiC.PROPERTY_DEFAULT_IMAGE);
      try {
        Object image = d.get(TiC.PROPERTY_IMAGE);

        if (image instanceof String) {
          String imageUrl = TiUrl.getCleanUri((String) image).toString();
          URI imageUri = new URI(imageUrl);
          if (URLUtil.isNetworkUrl(imageUrl) && !TiResponseCache.peek(imageUri)) {
            setDefaultImageSource(defaultImage);
          }

        } else if (image == null) {
          setDefaultImageSource(defaultImage);
        }

      } catch (URISyntaxException e) {
        setDefaultImageSource(defaultImage);
      } catch (NullPointerException e) {
        setDefaultImageSource(defaultImage);
      }
    }
    if (d.containsKey(TiC.PROPERTY_IMAGE)) {
      // processProperties is also called from TableView, we need check if we changed before
      // re-creating the
      // bitmap
      boolean changeImage = true;
      Object newImage = d.get(TiC.PROPERTY_IMAGE);
      TiDrawableReference source = makeImageSource(newImage);

      // Check for orientation only if they specified an image
      if (d.containsKey(TiC.PROPERTY_AUTOROTATE)) {
        source.setAutoRotate(d.getBoolean(TiC.PROPERTY_AUTOROTATE));
      }

      if (imageSources != null && imageSources.size() == 1) {
        if (imageSources.get(0).equals(source)) {
          changeImage = false;
        }
      }

      if (changeImage) {
        setImageSource(source);
        firedLoad = false;
        setImage(false);
      }

    } else {
      if (!d.containsKey(TiC.PROPERTY_IMAGES)) {
        getProxy().setProperty(TiC.PROPERTY_IMAGE, null);
        if (defaultImageSource != null) {
          setDefaultImage();
        }
      }
    }

    super.processProperties(d);
  }