Решение phreed в нижней половине вопроса в основном верно.Я попытаюсь добавить некоторые подробности здесь.
Когда вы выполните getContentResolver().openInputStream(...)
, преобразователь контента перейдет к вашему поставщику контента и вызовет его метод openFile
.Вот как openFile
выглядит в ContentProvider.java :
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
throw new FileNotFoundException("No files supported by provider at "
+ uri);
}
Так что это объясняет, откуда именно возникает ошибка «Файлы не поддерживаются ...»!Вы можете обойти это, переопределив метод openFile
в своем подклассе и предоставив собственную реализацию.Это аккуратно: вы получаете полный контроль над тем, где находятся ваши файлы, когда любой клиент делает openInputStream
или openOutputStream
.
Пример кода в вопросе Фрида подсказывает, как может выглядеть реализация.Вот моя слегка измененная версия, которая также создает каталоги и файлы по мере необходимости.Я новичок в этом деле, так что, возможно, это не оптимальный способ ведения дел, но это дает представление.Во-первых, он, вероятно, должен проверить, доступно ли внешнее хранилище.
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
File root = new File(Environment.getExternalStorageDirectory(),
"/Android/data/com.example.myapp/cache");
root.mkdirs();
File path = new File(root, uri.getEncodedPath());
// So, if the uri was content://com.example.myapp/some/data.xml,
// we'll end up accessing /Android/data/com.example.myapp/cache/some/data.xml
int imode = 0;
if (mode.contains("w")) {
imode |= ParcelFileDescriptor.MODE_WRITE_ONLY;
if (!path.exists()) {
try {
path.createNewFile();
} catch (IOException e) {
// TODO decide what to do about it, whom to notify...
e.printStackTrace();
}
}
}
if (mode.contains("r")) imode |= ParcelFileDescriptor.MODE_READ_ONLY;
if (mode.contains("+")) imode |= ParcelFileDescriptor.MODE_APPEND;
return ParcelFileDescriptor.open(path, imode);
}