Не удается отобразить файл PDF из папки ресурсов, так как MODE_WORLD_READABLE больше не поддерживается
Следующий код работает абсолютно нормально на устройствах с API 22, но на устройствах с API 24 выдает следующую ошибку:
java.lang.SecurityException: MODE_WORLD_READABLE no longer supported
Вот мой код:
private void CopyReadAssets(String filename) {
AssetManager assetManager = getAssets();
InputStream in = null;
OutputStream out = null;
File file = new File(getFilesDir(), filename);
try {
in = assetManager.open(filename);
out = openFileOutput(file.getName(), Context.MODE_WORLD_READABLE);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),"application/pdf");
startActivity(intent);
} catch (Exception e)
{
Log.e("cra",e.toString());
Toast.makeText(PdfFilesList.this, "cra: "+e.toString(), Toast.LENGTH_SHORT).show();
}
}
Если я изменю MODE_WORLD_READABLE на MODE_PRIVATE, он перестанет работать на всех устройствах. устройства с API 22 выдают следующую ошибку
11-16 12:00:53.133 16531-31103/? E/DisplayData: openFd: java.io.FileNotFoundException: Permission denied
11-16 12:00:53.134 16531-31103/? E/PdfLoader: Can't load file (doesn't open) Display Data [PDF : 818 New Jeevan Nidhi.pdf] +FileOpenable, uri: file:///data/data/com.user.plansmart/files/818%20New%20Jeevan%20Nidhi.pdf
Устройство с API 24 выдает следующее исключение
11-16 12:05:00.100 2682-2682/com.user.plansmart E/cra: android.os.FileUriExposedException: file:///data/user/0/com.user.plansmart/files/827%20Jeevan%20Rakshak.pdf exposed beyond app through Intent.getData()
Может ли кто-нибудь помочь мне в решении проблемы.
Благодарю.
2 ответа
Вы должны использовать FileProvider для обслуживания ваших файлов с Intent.ACTION_VIEW.
Код, делающий так, вы можете найти много на этом сайте.
Нашел обходной путь вместо использования MODE_WORLD_READABLE, так как смотрите здесь
int MODE_WORLD_READABLE Эта константа устарела на уровне API-17. Создание общедоступных файлов очень опасно и может привести к дырам в безопасности приложений. Настоятельно не рекомендуется; вместо этого приложения должны использовать более формальный механизм взаимодействия, такой как ContentProvider, BroadcastReceiver и Service. Нет никаких гарантий, что этот режим доступа останется в файле, например, когда он проходит резервное копирование и восстановление.
private void CopyReadAssets(String filename) {
AssetManager assetManager = getAssets();
InputStream in;
OutputStream out;
try {
in = assetManager.open(filename);
String outDir = Environment.getExternalStorageDirectory().getAbsolutePath();
File outFile = new File(outDir, filename);
if(outFile.createNewFile()){
return;
}
out = new FileOutputStream(outFile);
copyFile(in, out);
in.close();
out.flush();
out.close();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(outFile), "application/pdf");
startActivity(intent);
} catch (Exception e) {
Log.e("cra", e.toString());
Toast.makeText(this, "cra: " + e.toString(), Toast.LENGTH_SHORT).show();
}
}
Для устройств после M вам нужно спросить разрешение отдельно.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission
.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
102);
}
} else {
CopyReadAssets("yourpdf.pdf");
}
Затем в onRequestPermissionsResult реализуйте, ваш код.
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case 102:
CopyReadAssets("yourpdf.pdf");
break;
}
}
Надеюсь это поможет