2010-09-09 77 views
36

我試圖提供一個應用內活動,它在 設備的媒體商店中顯示照片的縮略圖,並允許用戶選擇一個。在用戶進行 選擇後,應用程序將讀取原始的全尺寸圖像並執行相關操作。如何查詢Android MediaStore Content Provider,避免孤立圖像?

我使用以下代碼來創建一個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的代碼示出) :

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; 
} 

// ... 
// 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的原始圖像

我在包括我自己的個人電話在內的一些Android設備上看到的問題是,我在onCreate()的查詢中得到的 光標包含幾個實際完整大小的圖像文件(JPG或PNG)不見了。 (在我的手機中,圖像已被導入並隨後由iPhoto擦除)。

孤立條目可能有也可能沒有縮略圖,具體取決於在AWOL時是否在實際媒體文件之前生成的縮略圖。最終的結果是,應用程序會顯示實際不存在的圖像的縮略圖。

我有幾個問題:

  1. 有一個查詢我可以對MediaStore內容提供商將篩選出 圖像與在返回Cursor缺少的媒體?
  2. 是否有方法或API來強制MediaStore重新掃描並消除孤立條目?在我的手機上,我安裝了USB,然後卸下外部媒體,這應該會觸發重新掃描。但孤兒條目仍然存在。
  3. 或者是我的方法導致這個問題有什麼根本錯誤?

謝謝。

回答

60

好的,我發現這個代碼示例的問題。

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