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

自分の携帯電話を含む一部のAndroidデバイスで見られる問題は、クエリから取得したカーソルにonCreate()、実際のフルサイズの画像ファイル(JPGまたはPNG)が欠落しているエントリがいくつか含まれていることです。(私の電話の場合、画像はインポートされ、その後iPhotoによって消去されました)。

孤立したエントリには、AWOL時に実際のメディアファイルの前にサムネイルが生成されたかどうかに応じて、サムネイルが含まれる場合と含まれない場合があります。その結果、アプリは実際には存在しない画像のサムネイルを表示します。

少し質問があります:

  1. MediaStore返されたメディアが欠落している画像を除外するコンテンツプロバイダーに対して行うことができるクエリはありますCursorか?
  2. MediaStoreを強制的に再スキャンし、孤立したエントリを削除する手段またはAPIはありますか?私の電話では、USBにマウントしてから、外部メディアをアンマウントしました。これにより、再スキャンがトリガーされます。しかし、孤立したエントリは残ります。
  3. それとも、この問題を引き起こしている私のアプローチに根本的に何か問題がありますか?

ありがとう。

4

2 に答える 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代わりにを使用してください。

これにより、元のフルサイズの画像への参照がぶら下がっているサムネイルを見つける問題も解決されました。

于 2011-02-11T22:08:55.870 に答える
7

状況はまもなく変更されることに注意してください。managedQueryメソッドは非推奨になりました。代わりにCursorLoaderを使用してください(APIレベル11以降)。

于 2011-08-25T08:33:01.540 に答える