java - MediaStore.Images.Thumbnails.getThumbnail 返回错误的缩略图而不是 NULL

标签 java android mediastore android-cursor android-cursorloader

考虑下图中的场景:

Native Galery

三张照片,其中一张是大型 GIF 文件 (3MP)。

我正在查询 MediaStore 以检索对应的缩略图。如果我使用此 sortOrder 通过 CursorLoader 初始化 Cursor:

MediaStore.Images.Media.DATE_ADDED + " DESC""

发生了什么:MediaStore 返回之前成功检索的缩略图:

DESC

预期行为:当 MediaStore 由于某种原因无法检索给定图像的缩略图时,它必须返回 NULL,根据其 Javadoc:“...返回一个位图实例。它如果与 origId 关联的原始图像不存在或内存不足,则可能为 null。”

如果我用这个 sortOrder 初始化游标:

MediaStore.Images.Media.DATE_ADDED + " ASC""

它运行得很好:

ASC

但是我不能简单地更改 sortOrder,因为要求是首先显示最新的图片。

下面是我的示例代码和here is the complete sample project以及the three images used to reproduce .

package com.example.getimagefrommediastore;

import android.app.Activity;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.content.CursorLoader;
import android.widget.ImageView;
import android.widget.TextView;

public class GetThumbnailsFromMediaStoreSampleActivity extends Activity {

TextView mThumb_id_01;
TextView mThumb_id_02;
TextView mThumb_id_03;
ImageView mImg_01;
ImageView mImg_02;
ImageView mImg_03;
boolean isThumb01 = true; // Simple flag to control this example
boolean isThumb02 = true;
Cursor mCursorLoader;
int mColumnIndex;
long mOrigId; // Original image id associated with thumbnail of interest

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Just initializing views
    mThumb_id_01 = (TextView) findViewById(R.id.thumb_id_01);
    mThumb_id_02 = (TextView) findViewById(R.id.thumb_id_02);
    mThumb_id_03 = (TextView) findViewById(R.id.thumb_id_03);
    mImg_01 = (ImageView) findViewById(R.id.thumb_01);
    mImg_02 = (ImageView) findViewById(R.id.thumb_02);
    mImg_03 = (ImageView) findViewById(R.id.thumb_03);

    // Initializing CursorLoader
    mCursorLoader = initializeCursorLoader();
    mColumnIndex = mCursorLoader.getColumnIndex(MediaStore.Images.Media._ID);

    // Go thru all the images in the device (EXTERNAL_CONTENT_URI)
    // In this example there are only three images
    for (int i = 0; i < mCursorLoader.getCount(); i++) {
        mCursorLoader.moveToPosition(i);
        mOrigId = mCursorLoader.getInt(mColumnIndex);

        // Update views
        chooseViewToUpdate();
    }
}

private Cursor initializeCursorLoader() {
    String[] COLUMNS = {
            MediaStore.Images.Thumbnails._ID, MediaStore.Images.Media.DATA
    };

    CursorLoader cursorLoader = new CursorLoader(
    GetThumbnailsFromMediaStoreSampleActivity.this, // Context
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, // Uri
    COLUMNS, // Projection
    null, // Selection
    null, // Selection Args

    // Sort Order: DESC = newest first
    // Sort Order: ASC = oldest first

    MediaStore.Images.Media.DATE_ADDED + " DESC");

    // *** NOTE ***
    // With:
    //
    // MediaStore.Images.Media.DATE_ADDED + " ASC"
    //
    // It runs just fine (MediaStore returns 'null' for invalid thumbnails)
    // The problem seems to reside on the " DESC" tag.
    //
    // How bizarre is that?

    return cursorLoader.loadInBackground();
}

private void chooseViewToUpdate() {
    if (isThumb01) {
        updateUI(mThumb_id_01, mImg_01);
        isThumb01 = false;
    } else if (isThumb02) {
        updateUI(mThumb_id_02, mImg_02);
        isThumb02 = false;
    } else {
        updateUI(mThumb_id_03, mImg_03);
    }
}

private void updateUI(TextView textView, ImageView imgView) {
    textView.setText("ID:" + String.valueOf(mOrigId));

    Bitmap mediaStoreThumbmail = MediaStore.Images.Thumbnails.getThumbnail(
            this.getContentResolver(),
            mOrigId,
            MediaStore.Images.Thumbnails.MICRO_KIND, null);

    if (mediaStoreThumbmail != null) {
        imgView.setImageBitmap(mediaStoreThumbmail);
    }
}

我错过了什么吗?有谁知道可能出了什么问题?

I filled a bug against Android anyway .

编辑

这个问题好像是fixed in Lollipop. (该线程的最后评论)。

最佳答案

我只是在猜测。当您要求 MICRO_KIND 时,操作系统正在创建一个新图像,该图像在 DESC 光标上排成一行,再次产生相同的图像。

解决方法是为图像 ID 加载一个 ArrayList。然后从 ArrayList 获取缩略图。

使用 MINI_KIND 和 bmoptions.inSampleSize = 2 尝试您的代码的可能性;

 final BitmapFactory.Options bmOptions = new BitmapFactory.Options();
            bmOptions.inSampleSize =2;



                    Bitmap bm = MediaStore.Images.Thumbnails.getThumbnail(
                            context.getContentResolver(), newImageId,
                            MediaStore.Images.Thumbnails.MINI_KIND,
                            bmOptions);

关于java - MediaStore.Images.Thumbnails.getThumbnail 返回错误的缩略图而不是 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13651871/

相关文章:

android - MediaStore.MediaColumns#DATE_TAKEN 是否仅适用于 API 级别 29?

android - 从手机存储中获取和调整位图大小的最佳方法

java - 从数组中删除括号

android - GCM 默认发件人ID

java - 比较两个对象时 equals 方法如何返回 false : e1. equals(e2)

android - ImageView背景

android - 通过 ADB 在 Android 上发送短信

android - 更新 Poweramp 播放列表

java - 如何将 Double[] 转换为 double...?

java - 无法连接到服务器,getResponseCode() 返回-1