我使用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时,这会给我一个错误,就像文件不存在一样。这是怎么回事?我错过了什么?操纵/访问缩略图的方式是什么?
答案 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;
}
}
这个课程的主要工作发生在init
和getCursorPosition
方法中,我现在不打算在这里解释,毕竟它们并不是很复杂。
要使用这个类,只需使用
Cursor cursor = new CursorWithDefectiveRows(loadedCursor, CursorWithDefectiveRows.DefectiveCursorRowChecker.IMAGE_FILE_EXISTS_CHECKER)
并且此结果光标会跳过所有错误文件,它可以立即与CursorAdapter
一起使用