Fast scanning of SD card on Android
I am trying to write an algorithm for fastest scanning of whole SD card. What I try to achieve is something in the line with QuickPic, which has "normal speed" initial scanning of SD card, but any subsequent refresh is incredibly fast.
I have tried several things, and I have some more ideas which I have not tested
1) Always scan entires SD card. I tried this...it's a bit slower on initial scan. but all subsequent scans are faster, but not as fast as QucikPic.
2) After initial scan add FileObserver to all folders. Although it only increases memory of application by approximately 1 MB, I am afraid this will affect performance or even drain battery, since it must run all the time. Also, I have database on SD card and I am constantly getting events for journal file being created/deleted. I am sure when working with other apps there will be other folders/files for which I will get constant notification. Not sure this is OK performance wise.
3) Using data from MediaStore. Unfortunately it seems that on my HTC Desire Media store is not always up to date with what's on SD card (not sure why), but that's not good enough.
3) Using ContentObserver. Haven't tried this yet, and must check documentation, but I have a feeling that if MediaStore doesn't have an image in it's DB, then I won't ge开发者_高级运维t it from ContentObserver either.
Do you guys have any other suggestion? Basically what I need is to know about all image files on SD card at some point. Initial scan can take a bit longer, subsequent scans should be as fast as possible (I know it depends on number of folders/files on SD card) but QuickPic scans (or whatever it does) entire SD card in about 0.6-0.8 seconds, and I just can't do it that fast.
Bona fide apps like QuickPic are undoubtedly using the MediaStore for their source. Here is an example that finds all the external image files in the MediaStore and their thumbnails.
Note that the DATA column in the MediaStore refers to the file's full path.
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.provider.MediaStore;
import androidx.loader.content.CursorLoader;
import java.io.IOException;
import java.util.ArrayList;
class ImageFileInfo
{
ImageFileInfo(String fileFullPath, Bitmap image, Bitmap thumbnail)
{
this.fileFullPath = fileFullPath;
this.image = image;
this.thumbnail = thumbnail;
}
String fileFullPath;
Bitmap image;
Bitmap thumbnail;
}
public class GetImageInfos
{
static ArrayList<ImageFileInfo> getImageInfos(Context context)
{
ArrayList<ImageFileInfo> list = new ArrayList<>();
final String[] cols = {
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DATA };
CursorLoader loader = new CursorLoader(context);
loader.setUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
loader.setProjection(cols);
loader.setSelection(null);
loader.setSortOrder(MediaStore.Images.Media.DATA);
Cursor cursor = loader.loadInBackground();
ContentResolver resolver = context.getContentResolver();
for (int i = 0; i < cursor.getCount(); i++)
{
cursor.moveToPosition(i);
int imagePathCol = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
String imagePath = cursor.getString(imagePathCol);
int imageIdCol = cursor.getColumnIndex(MediaStore.Images.Media._ID);
int imageId = cursor.getInt(imageIdCol);
Bitmap image = BitmapFactory.decodeFile(imagePath);
Bitmap thumb = MediaStore.Images.Thumbnails.getThumbnail(
resolver, imageId, MediaStore.Images.Thumbnails.MINI_KIND, null);
list.add(new ImageFileInfo(imagePath, image, thumb));
}
return list;
}
}
精彩评论