gpt4 book ai didi

Android ContentProvider 光标问题

转载 作者:行者123 更新时间:2023-11-29 20:58:33 26 4
gpt4 key购买 nike

我正在尝试为我的应用程序编写一个内容提供程序,以允许访问我的应用程序存储在 SD 卡上的某些文件。文件的名称是其内容 URI 的哈希值,因此例如 content://my.app.files/test.pdf 将位于 /sdcard/data/Android/my.app/cache/MD5(my.app.files/test.pdf) 其中 MD5() 是 MD5 哈希。

我的内容提供者看起来像这样:

public class CacheContentProvider extends ContentProvider {
private static final String[] COLUMNS= { OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE };
public static final Uri CONTENT_URI = Uri.parse("content://my.app.files/");
private DiskCache mCache;

@Override
public boolean onCreate() {
PotDroidApplication.initImageLoader(getContext());
final ImageLoader il = ImageLoader.getInstance();
mCache = il.getDiskCache();
return true;
}

@Override
public String getType(Uri uri) {
final File file = getFileForUri(uri);

final int lastDot = file.getName().lastIndexOf('.');
if (lastDot >= 0) {
final String extension = file.getName().substring(lastDot + 1);
final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
if (mime != null) {
return mime;
}
}

return "application/octet-stream";
}

@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
final File f = getFileForUri(getContentUriFromUrlOrUri(uri.toString()));

if (f.exists()) {
return ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
}

throw new FileNotFoundException(uri.getPath());
}

private File getFileForUri(Uri uri) {
return DiskCacheUtils.findInCache(uri.toString(), mCache);
}

@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
final File file = getFileForUri(uri);

if (projection == null) {
projection = COLUMNS;
}

String[] cols = new String[projection.length];
Object[] values = new Object[projection.length];
int i = 0;
for (String col : projection) {
if (OpenableColumns.DISPLAY_NAME.equals(col)) {
cols[i] = OpenableColumns.DISPLAY_NAME;
values[i++] = uri.getLastPathSegment();
} else if (OpenableColumns.SIZE.equals(col)) {
cols[i] = OpenableColumns.SIZE;
values[i++] = file.length();
}
}
cols = copyOf(cols, i);
values = copyOf(values, i);
final MatrixCursor cursor = new MatrixCursor(cols, 1);
cursor.addRow(values);
return cursor;
}

@Override
public Uri insert(Uri uri, ContentValues initialValues) {
throw new RuntimeException("Operation not supported");
}

@Override
public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
throw new RuntimeException("Operation not supported");
}

@Override
public int delete(Uri uri, String where, String[] whereArgs) {
throw new RuntimeException("Operation not supported");
}

public static Uri getContentUriFromUrlOrUri(String rawUrl) {
if(rawUrl.startsWith(CONTENT_URI.toString()))
return Uri.parse(rawUrl);
try {
URL url = new URL(rawUrl.replace("%20","+"));
return Uri.parse(CONTENT_URI + url.getHost() + url.getPath());
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
}

private static String[] copyOf(String[] original, int newLength) {
final String[] result = new String[newLength];
System.arraycopy(original, 0, result, 0, newLength);
return result;
}

private static Object[] copyOf(Object[] original, int newLength) {
final Object[] result = new Object[newLength];
System.arraycopy(original, 0, result, 0, newLength);
return result;
}

public static class HashFileNameGenerator extends Md5FileNameGenerator {
@Override
public String generate(String url) {
Uri uri = getContentUriFromUrlOrUri(url);
if(uri == null)
return super.generate(url);
return super.generate(uri.toString());
}
}

}

Provider 似乎可以很好地解析 content:// URI 并与某些应用程序共享,例如 Dropbox,也可以正常工作。但是,当我尝试与某些应用程序共享我的文件时,某些应用程序会抛出异常,例如 Acrobat PDF 转换器。异常(exception)情况如下:

Caused by: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetString(Native Method)
at android.database.CursorWindow.getString(CursorWindow.java:434)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
...

因此,显然,该应用程序正在寻找我通过 query() 方法返回的 Cursor 中不存在的某些列。我究竟做错了什么?我基本上是从 Android 的原生 FileProvider 复制了 query() 方法。

最佳答案

如果您在 ContentProvider 中公开媒体文件,那么它的 query() 方法应该返回 MediaStore.MediaColumns

关于Android ContentProvider 光标问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26882181/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com