无法在存储中打开PDF文件,安卓10。

huangapple go评论74阅读模式
英文:

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,&quot;KK.pdf&quot;);

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri= FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID+&quot;.provider&quot;,file1);
            
intent.setDataAndType(uri, &quot;application/pdf&quot;);                
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);

my manifest :

 &lt;provider
        android:name=&quot;androidx.core.content.FileProvider&quot;
        android:authorities=&quot;${applicationId}.provider&quot;
        android:exported=&quot;false&quot;
        android:grantUriPermissions=&quot;true&quot;&gt;
        &lt;meta-data
            android:name=&quot;android.support.FILE_PROVIDER_PATHS&quot;
            android:resource=&quot;@xml/provider_paths&quot;/&gt;
  &lt;/provider&gt;

provider paths :

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;paths xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
 &lt;external-path name=&quot;external_files&quot; path=&quot;Download/&quot;/&gt;
 &lt;files-path name=&quot;files&quot; path=&quot;files/&quot; /&gt;
&lt;/paths&gt;

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(&quot;pdf&quot;));
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 &amp;&amp; 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, &quot;file download: &quot; + fileSizeDownloaded + &quot; of &quot; + fileSize);
}
outputStream.flush();
openFileWithIntent(uri,&quot;pdf&quot;, 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 &gt;= 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);
}
}

huangapple
  • 本文由 发表于 2020年9月17日 15:43:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63933432.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定