Открыть файл в директории кеша с помощью ACTION_VIEW
Я искал это некоторое время, но я не могу заставить это работать правильно. Позволь мне объяснить.
У меня есть приложение для Android, которое сохраняет файлы (изображения, документы,...) в каталоге кеша. Сначала я привык getExternalCacheDir()
метод и сохранить их там, но потому что это должно быть кэшировано на устройствах, которые не имеют SD-карты, я должен использовать getCacheDir()
,
Когда я привык getExternalCacheDir()
метод, это не было проблемой, чтобы открыть эти файлы в другом приложении, как это:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), mimetype);
Но при использовании getCacheDir()
эти файлы сохраняются в изолированной программной среде приложения и недоступны извне приложения. Так что я погуглил его и пришел на ** ContentProvider. ContentProvider позволяет открывать личные файлы с помощью внешних приложений. Но когда я пытаюсь это реализовать, это не работает.
Я попытался реализовать ContentProvider благодаря этому сообщению: Как открыть личные файлы, сохраненные во внутреннем хранилище, с помощью Intent.ACTION_VIEW? но безуспешно
package com.myapplication.providers;
import java.io.File;
import java.io.FileNotFoundException;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
public class FileProvider extends ContentProvider {
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
File privateFile = new File(getContext().getCacheDir(), uri.getPath());
return ParcelFileDescriptor.open(privateFile, ParcelFileDescriptor.MODE_READ_ONLY);
}
@Override
public int delete(Uri arg0, String arg1, String[] arg2) {
return 0;
}
@Override
public String getType(Uri arg0) {
return null;
}
@Override
public Uri insert(Uri arg0, ContentValues arg1) {
return null;
}
@Override
public boolean onCreate() {
return false;
}
@Override
public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
String arg4) {
return null;
}
@Override
public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
return 0;
}
}
Добавил этого провайдера в манифест приложения
<provider
android:name="com.myapplication.providers.FileProvider"
android:authorities="com.myapplication"
android:exported="true" />
И используя этот код, чтобы открыть файл:
Uri uri = Uri.parse("content://com.myapplication/" + filename);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(uri, mimetype);
Заранее спасибо!
1 ответ
Я узнал, что я должен делать вещи по-другому.
Вместо создания собственного ContentProvider библиотека поддержки v4 предлагает класс FileProvider, который можно использовать.
В AndroidManifest.xml
добавлять
<application ...>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="be.myapplication"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
FILE_PROVIDER_PATHS - это XML-файл, который описывает, какие файлы могут быть прочитаны другими приложениями.
Поэтому я добавил файл file_paths.xml в папку res/xml.
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path name="my_cache" path="." />
</paths>
И единственное, что вам нужно сделать, это создать и запустить намерение показать файл.
File file = new File(getCacheDir(), "test.pdf");
Uri uri = FileProvider.getUriForFile(context, "be.myapplication", file);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(uri, "application/pdf");
startActivity(intent);
И на самом деле это все.
ВАЖНО: пожалуйста, не забудьте настройки
FLAG_GRANT_READ_URI_PERMISSION
флаги для намерения. Иначе это не сработает.