如何查询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之前在实际媒体文件之前生成的。 最终的结果是,应用程序显示的图像,实际上不存在的缩略图。

我有几个问题:

  1. 是否有可以对MediaStore内容提供商进行查询,以便在返回的Cursor滤除缺less媒体的图像?
  2. 有没有办法,或强制的MediaStore API重新扫描,并消除孤儿条目? 在我的手机上,我安装了USB,然后卸下外部媒体,这应该会触发重新扫描。 但孤儿条目仍然存在。
  3. 或者是我的方法有什么根本性的错误导致这个问题?

谢谢。

好的,我发现这个代码示例的问题。

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)。