MediaStore返回了缩略图路径,但文件对象提供文件不存在 - Android

时间:2014-09-29 05:10:26

标签: android mediastore

我使用CursorLoader获取了视频的缩略图路径。 MediaStore给了我缩略图路径。现在当我检查缩略图路径是否存在时,它会给我file not exists

我找到了使用

的缩略图路径
Cursor c = new CursorLoader(getApplicationContext(), MediaStore.Video.Thumbnails.getContentUri("external"), project,  selection, selectionArgs, null).loadInBackground();
while(c.moveToNext()) {

    //Toast.makeText(getApplicationContext(), c.getString(1),Toast.LENGTH_LONG).show();
    paths=c.getString(1);
 }

显示类似

的路径的Toasts
/storage/emulated/0/DCIM/.thumbnails/1411810114902.jpg

所以我决定在用它做某事之前检查文件是否存在。

File file = new File(paths);
if (file.exists())
{
     Toast.makeText(getApplicationContext(), "YES",Toast.LENGTH_LONG).show();
}
else
{
    Toast.makeText(getApplicationContext(), "NO",Toast.LENGTH_LONG).show();
}

令人惊讶的是它显示NO如何!什么媒体商店给了我?我的主要目的是将缩略图操作或转换为 base64 字符串。但decodeFile方法出现File not exists错误,因此我尝试检查文件是否存在。

为什么当mediaStore给出filepath时,这会给我一个错误,就像文件不存在一样。这是怎么回事?我错过了什么?操纵/访问缩略图的方式是什么?

2 个答案:

答案 0 :(得分:1)

我几天前遇到过同样的问题。原因是由于某些内部内存管理过程,有时它会将图像存储在/storage/emulated/0/DCIM/storage/emulated/1/DCIM中。

为了解决此问题,它始终建议 创建新文件夹,以便从相机和相机中保存新捕获的图像。从该文件夹访问

此外,在真实设备上检查它可能因为没有用于模拟器和SD的SD卡。因此,如果内部存储器已满,则会混淆存储位置,以便跳转到SD卡dcim文件夹。

答案 1 :(得分:1)

当用户从文件管理器中删除图像文件时会发生这种情况,如果文件管理器没有发送正确的广播来通知媒体扫描程序,则此图像的缩略图信息仍会存在于提供程序中。

我有类似的问题,我只想获得sdcard上仍然存在的图像,因为我想在网格中显示所有图像,然后当用户点击一个项目时,让用户查看大图图像,但是有些图像只有拇指,而不是真实的图像。

首先值得注意的是,修改CursorLoader中的选择参数不起作用,因为我们无法让CursorLoader检查文件是否存在。 我的解决方法是使用自定义CursorWrapper来跳过包含错误文件的行

public class CursorWithDefectiveRows extends CursorWrapper {
    private static final String TAG = CursorWithDefectiveRows.class.getSimpleName();

    private Cursor mCursor;
    private DefectiveCursorRowChecker mChecker;
    private List<Integer> mGoodRowCounts;

    private Map<Integer, Integer> mCache;


    public static interface DefectiveCursorRowChecker {
        boolean isDefective(Cursor cursor);

        public static final DefectiveCursorRowChecker IMAGE_FILE_EXISTS_CHECKER = new DefectiveCursorRowChecker() {
            @Override
            public boolean isDefective(Cursor cursor) {
                File imageFile = new File(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)););
                return !(imageFile.exists() && imageFile.length() > 0);
            }
        };
    }


    public CursorWithDefectiveRows(Cursor cursor, DefectiveCursorRowChecker checker) {
        super(cursor);

        mCursor = cursor;
        mChecker = checker;

        init(cursor, checker);
    }

    private void init(Cursor cursor, DefectiveCursorRowChecker checker) {
        mGoodRowCounts = new ArrayList<>();


        mGoodRowCounts.add(0);

        for (int i = 0; i < cursor.getCount(); i++) {
            cursor.moveToPosition(i);
            if (checker.isDefective(cursor)) {
                mGoodRowCounts.add(mGoodRowCounts.get(i));
            } else {
                mGoodRowCounts.add(mGoodRowCounts.get(i) + 1);
            }
        }

        mCache = new HashMap<>();
    }

    public int getCompressedPosition(int cursorPosition) {
        return mGoodRowCounts.get(cursorPosition);
    }

    public int getCursorPosition(int compressedPosition) {
        if (compressedPosition < 0) {
            return -1;
        }

        if (compressedPosition > getCount() - 1) {
            return mCursor.getCount();
        }

        if (mCache.containsKey(compressedPosition)) {
            return mCache.get(compressedPosition);
        }

        int index = Collections.binarySearch(mGoodRowCounts, compressedPosition);
        if (index < 0) {
            return index;
        }

        while (index < mGoodRowCounts.size() - 1 && mGoodRowCounts.get(index).intValue() == mGoodRowCounts.get(index + 1).intValue()) {
            index++;
        }

        mCache.put(compressedPosition, index);
        return index;
    }

    @Override
    public int getCount() {
        return mGoodRowCounts.get(mGoodRowCounts.size() - 1);
    }

    @Override
    public int getPosition() {
        return getCompressedPosition(mCursor.getPosition());
    }

    @Override
    public boolean move(int offset) {
        return moveToPosition(getPosition() + offset);
    }

    @Override
    public boolean moveToPosition(int position) {
        return mCursor.moveToPosition(getCursorPosition(position));
    }

    @Override
    public boolean moveToFirst() {
        return moveToPosition(0);
    }

    @Override
    public boolean moveToLast() {
        return moveToPosition(getCount() - 1);
    }

    @Override
    public boolean moveToNext() {
        return moveToPosition(getPosition() + 1);
    }

    @Override
    public boolean moveToPrevious() {
        return moveToPosition(getPosition() - 1);
    }

    @Override
    public boolean isFirst() {
        return getPosition() == 0;
    }

    @Override
    public boolean isLast() {
        return getPosition() == getCount() - 1;
    }


    @Override
    public boolean requery() {
        boolean result = super.requery();

        if (result) {
            init(mCursor, mChecker);
        }

        return result;
    }



}

这个课程的主要工作发生在initgetCursorPosition方法中,我现在不打算在这里解释,毕竟它们并不是很复杂。 要使用这个类,只需使用

Cursor cursor = new CursorWithDefectiveRows(loadedCursor, CursorWithDefectiveRows.DefectiveCursorRowChecker.IMAGE_FILE_EXISTS_CHECKER)

并且此结果光标会跳过所有错误文件,它可以立即与CursorAdapter一起使用