私はアンドロイドアプリケーションからPDFを開くためのカスタムクラスを使用しています。 PDFが既にダウンロードされているかどうかをチェックし、既存のPDFビューアアプリケーションを使用してPDFを開きます。 PDFビューアアプリケーションがない場合は、Googleドキュメントを使用してpdfを開こうとします。アンドロイドからPDFを開くアプリケーション
Android Studio 2.2.3から2.3.2へのアップグレードと24から25へのビルドツールのバージョンまで、クラスは正常に動作していました。ターゲットSDKは引き続きAPI 24です。問題の正確な根本原因を特定できません。
PDFクラス:
public class PDFTools {
private static final String GOOGLE_DRIVE_PDF_READER_PREFIX = "http://docs.google.com/viewer?url=";
private static final String PDF_MIME_TYPE = "application/pdf";
private static final String HTML_MIME_TYPE = "text/html";
/**
* If a PDF reader is installed, download the PDF file and open it in a reader.
* Otherwise ask the user if he/she wants to view it in the Google Drive online PDF reader.<br />
* <br />
* <b>BEWARE:</b> This method
* @param context
* @param pdfUrl
* @return
*/
public static void showPDFUrl(final Context context, final String pdfUrl) {
if (isPDFSupported(context)) {
downloadAndOpenPDF(context, pdfUrl);
} else {
askToOpenPDFThroughGoogleDrive(context, pdfUrl);
}
}
/**
* Downloads a PDF with the Android DownloadManager and opens it with an installed PDF reader app.
* @param context
* @param pdfUrl
*/
public static void downloadAndOpenPDF(final Context context, final String pdfUrl) {
// Get filename
final String filename = pdfUrl.substring(pdfUrl.lastIndexOf("/") + 1);
// The place where the downloaded PDF file will be put
final File tempFile = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), filename);
if (tempFile.exists()) {
// If we have downloaded the file before, just go ahead and show it.
Uri uri = null;
File docPath = new File(context.getExternalFilesDir(null), "Download");
File newFile = new File(docPath, filename);
uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", newFile);
openPDF(context, uri);
return;
}
// Show progress dialog while downloading
final ProgressDialog progress = ProgressDialog.show(context, context.getString(R.string.pdf_show_local_progress_title),
context.getString(R.string.message_please_wait), true);
// Create the download request
DownloadManager.Request r = new DownloadManager.Request(Uri.parse(pdfUrl));
r.setDestinationInExternalFilesDir(context, Environment.DIRECTORY_DOWNLOADS, filename);
final DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
BroadcastReceiver onComplete = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (!progress.isShowing()) {
return;
}
context.unregisterReceiver(this);
progress.dismiss();
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
Cursor c = dm.query(new DownloadManager.Query().setFilterById(downloadId));
if (c.moveToFirst()) {
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
Uri uri = null;
try {
uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", tempFile);
}catch (IllegalArgumentException iae) {
iae.printStackTrace();
}
if (uri !=null) {
openPDF(context, uri);
}
}
}
c.close();
}
};
context.registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
// Enqueue the request
dm.enqueue(r);
}
/**
* Show a dialog asking the user if he wants to open the PDF through Google Drive
* @param context
* @param pdfUrl
*/
public static void askToOpenPDFThroughGoogleDrive(final Context context, final String pdfUrl) {
new AlertDialog.Builder(context)
.setTitle(R.string.pdf_show_online_dialog_title)
.setMessage(R.string.pdf_show_online_dialog_question)
.setNegativeButton(R.string.pdf_show_online_dialog_button_no, null)
.setPositiveButton(R.string.pdf_show_online_dialog_button_yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
openPDFThroughGoogleDrive(context, pdfUrl);
}
})
.show();
}
/**
* Launches a browser to view the PDF through Google Drive
* @param context
* @param pdfUrl
*/
public static void openPDFThroughGoogleDrive(final Context context, final String pdfUrl) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(Uri.parse(GOOGLE_DRIVE_PDF_READER_PREFIX + pdfUrl), HTML_MIME_TYPE);
context.startActivity(i);
}
/**
* Open a local PDF file with an installed reader
* @param context
* @param localUri
*/
public static final void openPDF(Context context, Uri localUri) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
i.setDataAndType(localUri, PDF_MIME_TYPE);
context.startActivity(i);
}
/**
* Checks if any apps are installed that supports reading of PDF files.
* @param context
* @return
*/
public static boolean isPDFSupported(Context context) {
Intent i = new Intent(Intent.ACTION_VIEW);
final File tempFile = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "test.pdf");
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
try {
i.setDataAndType(FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider" ,tempFile), PDF_MIME_TYPE);
}catch (IllegalArgumentException iae) {
}
return context.getPackageManager().queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
}
それは私がスタックオーバーフロー自体からこのサンプルをとっている
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/<PACKAGE>/files/Download/javascript_pdf_version.pdf
としてエラーがスローされます。これについてあなたの助けを感謝します。
質問を編集し、 'FileProvider'設定XMLリソースを投稿してください。このエラーに基づいて、正しく設定されていないようです。 – CommonsWare
Androidマニフェストで上記のように設定されたFileProviderパスXMLは、<?xml version = "1.0" encoding = "utf-8"?> <外部ファイル・パス名=" 外部」パス= "ダウンロード" /> –
user8133044
マニフェスト<プロバイダ アンドロイド:名= "android.support.v4.content.FileProvider" アンドロイド:当局= "$ {} APPLICATIONID .provider" アンドロイド:エクスポート= "false" を アンドロイド:grantUriPermissions = "真"> <メタデータ アンドロイド:名= "android.support.FILE_PROVIDER_PATHS" アンドロイド:リソース= "@ xml/provider_paths" /> <?xml version = "1.0" encoding = "utf-8"?> –
user8133044