0

I´m using that way of cache Bitmaps in my app Using DiskLruCache in android 4.0 does not provide for openCache method

Thing is that I´m using that line in onCreate()

DiskLruImageCache dlic=new DiskLruImageCache(getApplicationContext(),"bckgCache", CACHESIZE, CompressFormat.PNG, 70);

and I´m pretty sure that It is overwriting my DiskLruCache everytime the app is opened "as new", so I´m not being able to recover some Bitmaps I catch las time user opened the app. So here is the question

How can I check I there´s already a DislLruCache created for an specific App so I will only create It If It doesn´t exist?

That's the class I'm using from the above URL

 public class DiskLruImageCache {

private DiskLruCache mDiskCache;
private CompressFormat mCompressFormat = CompressFormat.PNG;
private int mCompressQuality = 70;
private static final int APP_VERSION = 1;
private static final int VALUE_COUNT = 1;
private static final String TAG = "DiskLruImageCache";

public DiskLruImageCache( Context context,String uniqueName, int diskCacheSize,
    CompressFormat compressFormat, int quality ) {
    try {
            final File diskCacheDir = getDiskCacheDir(context, uniqueName );
            mDiskCache = DiskLruCache.open( diskCacheDir, APP_VERSION, VALUE_COUNT, diskCacheSize );
            mCompressFormat = compressFormat;
            mCompressQuality = quality;
        } catch (IOException e) {
            e.printStackTrace();
        }
}

private boolean writeBitmapToFile( Bitmap bitmap, DiskLruCache.Editor editor )
    throws IOException, FileNotFoundException {
    BufferedOutputStream out = null;
    try {
        out = new BufferedOutputStream( editor.newOutputStream( 0 ), Utils.IO_BUFFER_SIZE );
        return bitmap.compress( mCompressFormat, mCompressQuality, out );
    } finally {
        if ( out != null ) {
            out.close();
        }
    }
}

private File getDiskCacheDir(Context context, String uniqueName) {

// Check if media is mounted or storage is built-in, if so, try and use external cache dir
// otherwise use internal cache dir
    final String cachePath =
        Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||
                !Utils.isExternalStorageRemovable() ?
                Utils.getExternalCacheDir(context).getPath() :
                context.getCacheDir().getPath();

    return new File(cachePath + File.separator + uniqueName);
}

public void put( String key, Bitmap data ) {

    DiskLruCache.Editor editor = null;
    try {
        editor = mDiskCache.edit( key );
        if ( editor == null ) {
            return;
        }

        if( writeBitmapToFile( data, editor ) ) {               
            mDiskCache.flush();
            editor.commit();
            if ( BuildConfig.DEBUG ) {
               Log.d( "cache_test_DISK_", "image put on disk cache " + key );
            }
        } else {
            editor.abort();
            if ( BuildConfig.DEBUG ) {
                Log.d( "cache_test_DISK_", "ERROR on: image put on disk cache " + key );
            }
        }   
    } catch (IOException e) {
        if ( BuildConfig.DEBUG ) {
            Log.d( "cache_test_DISK_", "ERROR on: image put on disk cache " + key );
        }
        try {
            if ( editor != null ) {
                editor.abort();
            }
        } catch (IOException ignored) {
        }           
    }

}

public Bitmap getBitmap( String key ) {

    Bitmap bitmap = null;
    DiskLruCache.Snapshot snapshot = null;
    try {

        snapshot = mDiskCache.get( key );
        if ( snapshot == null ) {
            return null;
        }
        final InputStream in = snapshot.getInputStream( 0 );
        if ( in != null ) {
            final BufferedInputStream buffIn = 
            new BufferedInputStream( in, Utils.IO_BUFFER_SIZE );
            bitmap = BitmapFactory.decodeStream( buffIn );              
        }   
    } catch ( IOException e ) {
        e.printStackTrace();
    } finally {
        if ( snapshot != null ) {
            snapshot.close();
        }
    }

    if ( BuildConfig.DEBUG ) {
        Log.d( "cache_test_DISK_", bitmap == null ? "" : "image read from disk " + key);
    }

    return bitmap;

}

public boolean containsKey( String key ) {

    boolean contained = false;
    DiskLruCache.Snapshot snapshot = null;
    try {
        snapshot = mDiskCache.get( key );
        contained = snapshot != null;
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if ( snapshot != null ) {
            snapshot.close();
        }
    }

    return contained;

}

public void clearCache() {
    if ( BuildConfig.DEBUG ) {
        Log.d( "cache_test_DISK_", "disk cache CLEARED");
    }
    try {
        mDiskCache.delete();
    } catch ( IOException e ) {
        e.printStackTrace();
    }
}

public File getCacheFolder() {
    return mDiskCache.getDirectory();
}

And this is what I'm doing into my Activity, wich doesn't works. If you try offline works the first time, second It doesn't (null pointer in OnPause because It can't find any Bitmap in the folder). If you try Online always works, but, if you try online, and then offline, instead load the previous downloaded image, is stops (null pointer), so, main problem is that It, for whatever reason, doesn't records or reads anything in the cache folder

 public class Portada extends Activity {
private LinearLayout linearLayout;
private BitmapDrawable drawableBitmap;
private Bitmap b;
private DiskLruImageCache dlic;
private final String urlFondo="http://adapp.hostei.com/img/portada.jpg";
private final int MAXMEMORY = (int) (Runtime.getRuntime().maxMemory() / 1024);
private final int CACHESIZE = MAXMEMORY / 8;
private final String KEYPORTADA="bckportada";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_portada);
    linearLayout=(LinearLayout)findViewById(R.id.fondoPortada);

    Log.i("OnCreate","Starting");

     File cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"bckgCache");

     if(!cacheDir.exists()){ // check if it exits. if not create one
         Log.i("OnCreate","Create not exsisting folder");
         cacheDir.mkdirs(); 
         dlic=new DiskLruImageCache(Portada.this,cacheDir.getName(), CACHESIZE, CompressFormat.PNG, 70);
     }
     else{
         dlic=new DiskLruImageCache(Portada.this,cacheDir.getName(), CACHESIZE, CompressFormat.PNG, 70);
     } 
}   



@Override
protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();
    Log.i("OnResume","Starting");

    //checks if there's already a background image on cache
    boolean hayportada=comprobarSiHayPortadaEnCache();

    //creates a bckImage from R.drawable image if there's any already in cache
    //this should only occurs once, the very first time the App runs
    if(!hayportada){
        b=BitmapFactory.decodeResource(getResources(), R.drawable.portada);
        dlic.put(KEYPORTADA, b);
        Log.i("onResume","Creates bckgImage from R.drawable");
    }


    //checks if there's any connection and if yes, loads the url image into cache and puts It as background
    //if not load the image of the previous if
    if(CheckOnline.isOnline(Portada.this)){
        cargarPortadaUrl(urlFondo);//loads image from url and stores in cache
        cargarImagenPortada(b);//put image as layout background
        Log.i("onResume","there is online, down img");
    }
    else{
        b=dlic.getBitmap(KEYPORTADA);
        cargarImagenPortada(b);
        Log.i("onResume","there's not online ");
    }
}

@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    dlic.put(KEYPORTADA, b);//just in case, It's already done in OnResume;
    Log.i("onPause","stores Bitmap");
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_portada, menu);
    return true;
}

/**
 * Takes an image from url and stores It in cache
 * 
 */
public void cargarPortadaUrl(String urlFondo){
    DownloadImageTask dit=new DownloadImageTask();//Async task that downloads an img
    try {
        b=dit.execute(urlFondo).get();
        dlic.put(KEYPORTADA, b);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}


//loads a Bitmap as Layout Background image
public void cargarImagenPortada(Bitmap bitm){
    drawableBitmap=new BitmapDrawable(bitm);
    linearLayout.setBackgroundDrawable(drawableBitmap); 
}

//checks if there's any 
public boolean comprobarSiHayPortadaEnCache(){
    b=dlic.getBitmap(KEYPORTADA);
    if(b==null)return false;
    else return true;
}

}

Community
  • 1
  • 1
MBRebaque
  • 359
  • 2
  • 5
  • 13

1 Answers1

2

Check if sd card is mounted. Get the path of the sdcard. Check if the folder under sdcard already exists, if not create one.

Remember to add permission in manifest file

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
if(android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
{
  File cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"MyFolder");

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

You can use the below. Found this on developer site in the below link

File cacheDir = getDiskCacheDir(ActivityName.this, "thumbnails");  
if(!cacheDir.exists()) // check if it exits. if not create one
 {
    cacheDir.mkdirs(); 
 } 

public static File getDiskCacheDir(Context context, String uniqueName) {
// Check if media is mounted or storage is built-in, if so, try and use external cache dir
// otherwise use internal cache dir
final String cachePath =
        Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||
                !isExternalStorageRemovable() ? getExternalCacheDir(context).getPath() :
                        context.getCacheDir().getPath();

return new File(cachePath + File.separator + uniqueName);
}

For more information check the link below

http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

I see you have used getAppliactionContext(). Check the link below

When to call activity context OR application context?. Get to know when to use activity context and getApplicationContext()

Edit:

   File cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"MyFolder");
 if(!cacheDir.exists()) // check if it exits. if not create one
  {
   cacheDir.mkdirs(); 
   DiskLruImageCache dlic=new DiskLruImageCache(ActivityName.this,cacheDir, CACHESIZE, CompressFormat.PNG, 70);
  }
  else
   {
      DiskLruImageCache dlic=new DiskLruImageCache(ActivityName.this,cacheDir, CACHESIZE, CompressFormat.PNG, 70);
   } 

Edit: 2

As you can see below you are just passing the file not creating a new one.

private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize) {
    this.directory = directory;
    this.appVersion = appVersion;
    this.journalFile = new File(directory, JOURNAL_FILE);
    this.journalFileTmp = new File(directory, JOURNAL_FILE_TMP);
    this.valueCount = valueCount;
    this.maxSize = maxSize;
}

public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
        throws IOException {
    if (maxSize <= 0) {
        throw new IllegalArgumentException("maxSize <= 0");
    }
    if (valueCount <= 0) {
        throw new IllegalArgumentException("valueCount <= 0");
    }

    // prefer to pick up where we left off
    DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
    if (cache.journalFile.exists()) {
        try {
            cache.readJournal();
            cache.processJournal();
            cache.journalWriter = new BufferedWriter(new FileWriter(cache.journalFile, true),
                    IO_BUFFER_SIZE);
            return cache;
        } catch (IOException journalIsCorrupt) {
             System.logW("DiskLruCache " + directory + " is corrupt: "
                    + journalIsCorrupt.getMessage() + ", removing");
            cache.delete();
        }
    }

    // create a new empty cache
    directory.mkdirs();
    cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
    cache.rebuildJournal();
    return cache;
}
svarog
  • 8,471
  • 4
  • 55
  • 66
Raghunandan
  • 129,147
  • 24
  • 216
  • 249
  • Ok, thank you very much, I will try that when I get home. The use of context is a mistake, It should be Activity Context, thanks for point It. I will tell you If It worked in about 10 hours. – MBRebaque Apr 17 '13 at 07:53
  • ok. try it if it helps come back later and accept the answer. – Raghunandan Apr 17 '13 at 07:56
  • Ok, I tried It. Your way is nice but is not working with DiskLruImageCache class. Problem is I need an instance of this class to work with, and only way of have It is creating one, wich means overwrite the cache folder I alreday might have. Any solution or recomendation? – MBRebaque Apr 17 '13 at 18:27
  • I din't get your point. You can create a class with methods. Have that class instantiated and call appropriate methods. The above checks if the folder exists if not creates one. You can also pass context and other data to the constructor of the class. – Raghunandan Apr 17 '13 at 18:39
  • Yes sorry, I explained myself very bad. Thing is that, even existing the folder, I need a DiskLruImageCache object to put Bitmaps inside. Problem is that I can't instantiate a DiskLruImageCache to do It without overwrite the folder. Look the url in the question to see the constructor. – MBRebaque Apr 17 '13 at 18:45
  • I think I might have a solution but I need to know If DiskLruCache.open() (CAUTION: DiskLruImageCache inherits from DiskLruCache) overwrites the folder If it exists – MBRebaque Apr 17 '13 at 18:50
  • check the edit above. pass the file cacheDir and write bitmaps to the file – Raghunandan Apr 17 '13 at 18:54
  • that's the problem, doing that you're overwritting the existing folder and ereasing all Bitmaps inside. You don't need to do that mkdir() thing. Constructor creates It Itself using DiskLruCache – MBRebaque Apr 17 '13 at 18:56
  • you will using the path of the folder. So i don't under how you will create the folder again with the same name. http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html. Try the example in the link – Raghunandan Apr 17 '13 at 18:59
  • Ok, but this DiskLruImageCache (wich is different class than thee example link) doesn't not use file path, use a string (name) for construct the File. Anyway I think I can solve It if I can figure out if DiskLruCache.open() (your url class) overwrites all inside the folder everytime is called – MBRebaque Apr 17 '13 at 19:06
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/28391/discussion-between-raghunandan-and-mbrebaque) – Raghunandan Apr 17 '13 at 19:07