如何查询 Android MediaStore 内容提供程序,避免孤立图像?

37

我正在尝试提供一个应用内活动,显示设备媒体库中照片的缩略图,并允许用户选择其中的一张。用户选择后,应用程序会读取原始的全尺寸图像并对其进行操作。

我正在使用以下代码在外部存储上创建一个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);
}

一旦用户选择了图片,使用如下代码从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;
}

我在一些安卓设备上,包括我的个人手机上遇到的问题是:在onCreate()中查询所得的光标包含一些实际完整大小的图像文件(JPG或PNG)缺失的条目。(在我手机的情况下,这些图片已被导入并随后被iPhoto删除。)

这些孤立的条目可能有缩略图,也可能没有,这取决于在实际媒体文件缺失时是否生成了缩略图。最终结果是应用程序会显示不存在的图像的缩略图。

我有几个问题:

  1. 是否有一种查询可以从返回的Cursor中过滤出具有缺失媒体的图像的MediaStore内容提供者?
  2. 是否有一种方法或API可以强制MediaStore重新扫描并消除孤立的条目?在我的手机上,我将外部媒体进行了USB挂载和卸载,这应该会触发重新扫描。但是这些孤立的条目仍然存在。
  3. 还是我的方法有根本性的问题导致了这个问题?

谢谢。

2个回答

61

好的,我已经找到了这个代码示例的问题所在。

onCreate()方法中,我有这样一行代码:

mImageCursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
                             projection, selection, selectionArgs, null );

这里的问题是正在查询缩略图而不是实际图像。HTC设备上的相机应用程序默认情况下不会创建缩略图,因此此查询将无法返回尚未计算缩略图的图像。

相反,查询实际的图像本身:

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即可。

这也解决了查找具有指向原始全尺寸图像的悬空引用的缩略图的问题。


7
请注意,一些事情即将发生改变,managedQuery方法已经被弃用。请使用CursorLoader替代(自api级别11以来)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接