英文:
Can't Open PDF file in the storage android 10
问题
我在Download Storage中有一个PDF文件,并尝试使用意图(intent)显示它,我已经安装了三个PDF查看器应用,但它们都无法成功显示该文件,但如果我通过文件浏览器直接打开PDF文件,则可以正常显示。
以下是我的代码:
File kuda = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File file1 = new File(kuda, "KK.pdf");
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID + ".provider", file1);
intent.setDataAndType(uri, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
以下是我的清单文件(manifest):
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
以下是provider_paths.xml文件的内容:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="Download/"/>
<files-path name="files" path="files/" />
</paths>
我正在使用Android 10版本。
请帮忙看看,谢谢。
英文:
I have a pdf file in the Download Storage and I try show it using intent, I already have three PDF viewer apps, but none of them sucessfully show the file, but if I open the pdf directly via file explorer its show just fine.
here is my code :
File kuda = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File file1 = new File(kuda,"KK.pdf");
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri= FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID+".provider",file1);
intent.setDataAndType(uri, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
my manifest :
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
provider paths :
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="Download/"/>
<files-path name="files" path="files/" />
</paths>
I'm using android 10
please help. thanks
答案1
得分: 1
是的,在OS 10之后,需要以新的方式编写逻辑。以下是使用Retrofit获取某些响应并使用byte[]的示例,适用于我的应用程序。将此代码放入您的Android组件(例如活动)中。调用viewModel.getPdfBytes()将从后端获得响应!
private static final int CREATE_FILE = 23;
private void saveFileToStorageIntent() {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf"));
intent.putExtra(Intent.EXTRA_TITLE, getString(R.string.text_export_pdf_file_first) + getDateString() + getString(R.string.text_export_pdf_file));
startActivityForResult(intent, CREATE_FILE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CREATE_FILE) {
if (resultCode == Activity.RESULT_OK && data != null) {
writePDFToFile(data.getData(), viewModel.getPdfBytes());
}
}
}
private void writePDFToFile(Uri uri, ResponseBody body){
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = getContentResolver().openOutputStream(uri);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Logger.print(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
}
outputStream.flush();
openFileWithIntent(uri, "pdf", getString(R.string.open_file));
} catch (Exception e) {
Logger.print(TAG, e.getMessage());
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void openFileWithIntent(Uri fileUri, String typeString, String openTitle) {
Intent target = new Intent(Intent.ACTION_VIEW);
target.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
target.setDataAndType(
fileUri,
MimeTypeMap.getSingleton().getMimeTypeFromExtension(typeString)
); // For now there is only type 1 (PDF).
Intent intent = Intent.createChooser(target, openTitle);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
if (BuildConfig.DEBUG) e.printStackTrace();
Toast.makeText(context, getString(R.string.error_no_pdf_app), Toast.LENGTH_SHORT).show();
FirebaseCrashlytics.getInstance().log(getString(R.string.error_no_pdf_app));
FirebaseCrashlytics.getInstance().recordException(e);
}
}
英文:
Yea, things changed after OS 10, you have to write logic in new way. Sample where we get some response using retrofit and using those byte[], working in my apps. Put this code in your android component(activity for example). Invoking viewModel.getPdfBytes() is response from backend!
private static final int CREATE_FILE = 23;
private void saveFileToStorageIntent() {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf"));
intent.putExtra(Intent.EXTRA_TITLE, getString(R.string.text_export_pdf_file_first) + getDateString() + getString(R.string.text_export_pdf_file));
startActivityForResult(intent, CREATE_FILE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CREATE_FILE) {
if (resultCode == Activity.RESULT_OK && data != null) {
writePDFToFile(data.getData(), viewModel.getPdfBytes());
}
}
}
private void writePDFToFile(Uri uri, ResponseBody body){
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = getContentResolver().openOutputStream(uri);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Logger.print(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
}
outputStream.flush();
openFileWithIntent(uri,"pdf", getString(R.string.open_file));
} catch (Exception e) {
Logger.print(TAG, e.getMessage());
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void openFileWithIntent(Uri fileUri, String typeString, String openTitle) {
Intent target = new Intent(Intent.ACTION_VIEW);
target.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
target.setDataAndType(
fileUri,
MimeTypeMap.getSingleton().getMimeTypeFromExtension(typeString)
); // For now there is only type 1 (PDF).
Intent intent = Intent.createChooser(target, openTitle);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
if (BuildConfig.DEBUG) e.printStackTrace();
Toast.makeText(context, getString(R.string.error_no_pdf_app), Toast.LENGTH_SHORT).show();
FirebaseCrashlytics.getInstance().log(getString(R.string.error_no_pdf_app));
FirebaseCrashlytics.getInstance().recordException(e);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论