如何查询Android MediaStore Content Provider,避免孤立的图像?
我试图提供一个应用内活动,在设备的媒体商店中显示照片的缩略图,并允许用户select一个。 用户进行select后,应用程序将读取原始的全尺寸图像,并对其进行处理。
我使用以下代码在外部存储上的所有映像上创build一个Cursor
:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView( R.layout.image_select ); mGridView = (GridView) findViewById( R.id.image_select_grid ); // Query for all images on external storage String[] projection = { MediaStore.Images.Media._ID }; String selection = ""; String [] selectionArgs = null; mImageCursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null ); // Initialize an adapter to display images in grid if ( mImageCursor != null ) { mImageCursor.moveToFirst(); mAdapter = new LazyCursorAdapter(this, mImageCursor, R.drawable.image_select_default); mGridView.setAdapter( mAdapter ); } else { Log.i(TAG, "System media store is empty."); } }
下面的代码加载缩略图(Android 2.x代码显示):
// ... // Build URI to the main image from the cursor int imageID = cursor.getInt( cursor.getColumnIndex(MediaStore.Images.Media._ID) ); Uri uri = Uri.withAppendedPath( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, Integer.toString(imageID) ); loadThumbnailImage( uri.toString() ); // ... protected Bitmap loadThumbnailImage( String url ) { // Get original image ID int originalImageId = Integer.parseInt(url.substring(url.lastIndexOf("/") + 1, url.length())); // Get (or create upon demand) the micro thumbnail for the original image. return MediaStore.Images.Thumbnails.getThumbnail(mContext.getContentResolver(), originalImageId, MediaStore.Images.Thumbnails.MICRO_KIND, null); }
以下代码用于在用户进行select时从URL加载原始图像:
public Bitmap loadFullImage( Context context, Uri photoUri ) { Cursor photoCursor = null; try { // Attempt to fetch asset filename for image String[] projection = { MediaStore.Images.Media.DATA }; photoCursor = context.getContentResolver().query( photoUri, projection, null, null, null ); if ( photoCursor != null && photoCursor.getCount() == 1 ) { photoCursor.moveToFirst(); String photoFilePath = photoCursor.getString( photoCursor.getColumnIndex(MediaStore.Images.Media.DATA) ); // Load image from path return BitmapFactory.decodeFile( photoFilePath, null ); } } finally { if ( photoCursor != null ) { photoCursor.close(); } } return null; }
我在一些Android设备(包括我自己的个人电话)上看到的问题是,我从onCreate()
中的查询中获得的光标包含几个实际完整大小的图像文件(JPG或PNG)缺失的条目。 (在我的手机的情况下,图像已导入,然后由iPhoto擦除)。
孤立条目可能有也可能没有缩略图,具体取决于缩略图是在AWOL之前在实际媒体文件之前生成的。 最终的结果是,应用程序显示的图像,实际上不存在的缩略图。
我有几个问题:
- 是否有可以对
MediaStore
内容提供商进行查询,以便在返回的Cursor
滤除缺less媒体的图像? - 有没有办法,或强制的
MediaStore
API重新扫描,并消除孤儿条目? 在我的手机上,我安装了USB,然后卸下外部媒体,这应该会触发重新扫描。 但孤儿条目仍然存在。 - 或者是我的方法有什么根本性的错误导致这个问题?
谢谢。
好的,我发现这个代码示例的问题。
在onCreate()
方法中,我有这样的一行:
mImageCursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null );
这里的问题是查询缩略图,而不是实际的图像。 HTC设备上的相机应用默认情况下不会创build缩略图,因此此查询将无法返回尚未计算缩略图的图像。
相反,查询自己的实际图像:
mImageCursor = managedQuery( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null );
这将返回一个光标,其中包含系统上所有的全尺寸图像。 然后你可以打电话给:
Bitmap bm = MediaStore.Images.Thumbnails.getThumbnail(context.getContentResolver(), imageId, MediaStore.Images.Thumbnails.MINI_KIND, null);
这将返回相关的全尺寸图像的中等大小的缩略图,如果需要的话生成它。 要获得微缩尺寸缩略图,请改用MediaStore.Images.Thumbnails.MICRO_KIND
。
这也解决了寻找具有原始全尺寸图像的悬挂引用的缩略图的问题。
请注意,事情很快就会改变,managedQuery方法已被弃用。 改用CursorLoader(自api级别11)。