我正在尝试提供一个应用内 Activity ,该 Activity 可在
设备的媒体存储区,并允许用户选择其中一个。用户制作完一个
选择后,应用程序将读取原始的全尺寸图像并对其进行处理。

我正在使用以下代码在外部所有图像上创建一个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;
}

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

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

我有几个问题:
  • 是否可以查询MediaStore内容提供程序以进行过滤
    返回的Cursor中缺少媒体的图像?
  • 是否有一种方法或API可以强制MediaStore重新扫描并消除孤立条目?在我的手机上,我先安装USB,然后卸载外部媒体,这应该会触发重新扫描。但是,孤儿条目仍然存在。
  • 还是我的方法存在根本上的问题而导致了此问题?

  • 谢谢。

    最佳答案

    好的,我发现了此代码示例的问题。

    onCreate()方法中,我有以下这一行:

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

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

    而是查询实际的图像本身:
    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即可。

    这也解决了查找与原始全尺寸图像相关的缩略图的问题。

    10-07 19:36
    查看更多