I am fetching a lot of thumbnails in my application from a remote server and lazy-loading these in a list view.
The image fetches run in a background AsynTask and when completed the fetched images are stored in a HashMap using SoftReferences.
This works just fine but when the images in the cache gets GC’d, the fetches have to be rerun.
I could have stored them on the SD card so there would be no re-fetching.
But I did not take this approach because of the clutter it would create on the SD card.
Are there perhaps alternatives to these sorta like temporary folders that can be cleared when activity/app finishes/exits?
What is the "ideal place" to cache images? Any advice, example projects, or pointers would be appreciated.
You should check files data storage options:
http://developer.android.com/guide/topics/data/data-storage.html
Files are being saved in the applications directory, so there is no mess anywhere. Files will be finally removed with the app. You can also implement some method which will clear the cache when the app starts (for example remove files older than 2 weeks).
You should be able to locate a SQLite DB on the SD card. This would let you have a fairly clean interface/cache space while keeping data off the very limited internal phone memory. You can specify the location of the DB by calling openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory). It may be more work than you'd like to put in, but you should be able to clear ou the DB when you application is unloaded with a line or two of code.
More from the documentation here:
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
Related
I have an app that downloads many images that are about 50k to 100k in size. The full database can be anywhere from 50MB to 500MB.
We are currently using sqlite, but it has slow inserts. We did a test writing files and that was slow as well. It seems to be taking about 300 to 800ms per image to write - which comes out to about 250kb/sec (slower than the network speed). I did a benchmark with A1 benchmark and it says my write speed is 14MB/sec, so i'm not sure why my app is so slow?
Here are the primary requirements:
1) Fast writes
2) Fast reads/lookups via an custom integer key (this can be converted a file path for individual files)
3) Prevents user from easily accessing the images (if we save as images they can connect the external storage to their computer and browser, but we can write the files in reverse byte order)
hopefully we can still use the sqllite solution, as i like one file, but either way it seems like a storage issue?
As suggested in the comments, I think you are better off using the private memory storage for the actual images. This will have better speed then storing BLOBs in SQLite.
If you still need to keep a DB, for example for complex image searches or such, I suggest you just replace the BLOB field in your DB with a string with the actual location of the image file.
Another solution is to keep the images as app assets, but this assumes the images are always the same and can't change dynamically, and I doubt this is your use case.
My app collects data which it stores in arrays, and I need to be able to access the data from outside the app. The tablet I am using has no SD card, so I'm thinking the best way to transfer data would be to save to 'external' system memory. I have found tutorials to save data on internal storage and for specific data types like pictures onto SD cards, but I can't figure out how to write an arbitrary file to an arbitrary location. Thanks.
This sounds like a perfect time to use a SQLite database. Android comes with SQLite support built in so its easy to set up. You can just create a database and store your array data there (you can even store pictures too as a byte[]). There are a number of tutorials that show how to do this. Here is 1 and 2. It should be pretty easy from there.
I'm not sure that you can write to an arbitrary place on the Android system. You could write to a file in /data/data// and then email that file to yourself.
What I'm trying to do right now within my app is modify the ImageDownloader class that Google put out last year in one of their tutorials that asynchronously downloads and caches images for ImageViews without leaking the context.
In other words, since I'm using a global cache singleton object which provides references to my Bitmap HashMaps, I just need to know: since I have to cache images separately depending on certain aspects of my app (client requirement), should I have pairs of hard and soft HashMaps for each of those types of Bitmaps, or would it be more efficient to have only one soft HashMap in which the other hard caches move their files to when they are pressed for space?
I've encountered a similar problem on an app we worked on. We hard cache images we pull in an SQLite blob. The wrapper will check the cache's existance, or go pull over the network, so even if someone clears the app data, it'll work (a bit slower until images are cached again). Since it's in SQLite the app data can easily be moved around to the SD card and back without having to worry about file paths being changed.
Consider using something like:
ConcurrentHashMap<String, SoftReference<Bitmap>> image_cache =
newConcurrentHashMap<String, SoftReference<Bitmap>>( 1 );
For the memory portion of your cache. The SoftReference's will be garbage collected as the device needs memory. This will allow your application to keep as many images in memory as possible without causing memory issues.
You can choose to back this cache with a file cache either on the SD card with a root path using:
Environment.getExternalStorageDirectory();
or using the cache space provided by android using a path of:
context.getCacheDir();
The cache space is private whereby the SD card images could be retrieved by a user or modified by a 3rd party program. The cache space is on the internal storage of the device and it shows up in the application manager statistics. The user can also clear this cache easily from their settings->application manager screen.
You will need to fill in the algorithm that checks the memory cache first, checks the soft reference if found, checks the file system if not found, and then finally fetches from the network, saves to a file, and puts it in the memory cache. You can then add additional requirements for the cache based on your client requirements on top of this structure.
I have an android application that allows users to upload images to their account. Im storing the images as longblob files in a mysql db and pulling them from that but I have read on here and other places that its more efficient to store your images in a file system. I know it will work for my alpha to show but its already sucking up space in the db.
Ive seen plenty of people on here and other places mentioning file systems over using a db however....no one makes any references to specific file system software or set ups. Ideally I need a system that would allow for the fastest retrieval of images from it and it has to work with a query from php.
Any tips on the matter would be awesome :)
You could store the images on the file system, and use the database to keep a file-pointer, which is simply the path to the location of the image on your system. Then, use a query to fetch the location, and use that as you would for any image.
This thread on DaniWeb shows how uploads could be handled:
http://www.daniweb.com/web-development/php/threads/162230
Also, use relative paths in case you wish to move the location of the images in the future, as mentioned in the chosen answer here:
When storing Images in the File System, Use relative paths or absolute paths?
I am new to android and I was wondering what the correct way is to manage and set some maximum limit for your application's data storage. For instance, I have an image cache and a database file with some information. I do not want it to potentially become extremely big. Is there a built in a way that android provides so I can manage the size of how much data is stored? Thanks again
I don't think so. You will have to manually do that. Your image cache would have a database and a cache folder. So, there is no custom method or class that you could use to set limits to the DB or the folder.