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

mpo*_*isf 37 media android image android-contentprovider

我正在尝试提供一个应用内活动,该活动会在设备的媒体商店中显示照片的缩略图,并允许用户选择一个.用户进行选择后,应用程序将读取原始的全尺寸图像并使用它执行操作.

我正在使用以下代码创建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.");
    }
}
Run Code Online (Sandbox Code Playgroud)

以下代码加载缩略图图像(显示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);
}
Run Code Online (Sandbox Code Playgroud)

以下代码在用户进行选择后从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;
}
Run Code Online (Sandbox Code Playgroud)

我在某些Android设备上看到的问题,包括我自己的个人手机,是我从查询中获得的光标onCreate()包含一些缺少实际全尺寸图像文件(JPG或PNG)的条目.(对于我的手机,图像已导入并随后被iPhoto删除).

孤立的条目可能有也可能没有缩略图,具体取决于在AWOL时是否在实际媒体文件之前生成的缩略图.最终结果是应用程序显示实际不存在的图像的缩略图.

我有几个问题:

  1. 我可以向MediaStore内容提供商发出一个查询,过滤掉返回的媒体中缺少媒体的图片Cursor吗?
  2. 是否存在强制MediaStore重新扫描和消除孤立条目的方法或API ?在我的手机上,我安装了USB,然后卸下外部媒体,这应该会触发重新扫描.但孤儿条目仍然存在.
  3. 或者我的方法是否会导致这个问题根本出现问题?

谢谢.

mpo*_*isf 61

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

onCreate()方法中,我有这条线:

mImageCursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
                             projection, selection, selectionArgs, null );
Run Code Online (Sandbox Code Playgroud)

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

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

mImageCursor = managedQuery( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                             projection, selection, selectionArgs, null );
Run Code Online (Sandbox Code Playgroud)

这将返回包含系统上所有全尺寸图像的光标.然后你可以打电话:

Bitmap bm = MediaStore.Images.Thumbnails.getThumbnail(context.getContentResolver(),
        imageId, MediaStore.Images.Thumbnails.MINI_KIND, null);
Run Code Online (Sandbox Code Playgroud)

它将返回相关全尺寸图像的中等大小缩略图,并在必要时生成它.要获得微型缩略图,请MediaStore.Images.Thumbnails.MICRO_KIND改用.

这也解决了找到悬挂引用原始全尺寸图像的缩略图的问题.


Tam*_*mas 7

请注意,事情很快就会改变,不推荐使用managedQuery方法.改为使用CursorLoader(因为api级别为11).