Android的库中不支持PDF。有没有办法在Android应用程序中呈现PDF文件?
当前回答
我从这篇文章和其他类似文章的一些答案中得出了一个混合的方法:
此解决方案检查PDF阅读器应用程序是否已安装,并执行以下操作: —如果设备上安装了PDF阅读器,请将PDF文件下载到设备上,并打开PDF阅读器应用 —如果没有安装阅读器,请询问用户是否希望通过谷歌Drive在线查看PDF文件
注意!这个解决方案使用了在API9 (Android 2.3或Gingerbread)中引入的Android DownloadManager类。这意味着它不能在Android 2.2或更早的版本上运行。
我在这里写了一篇关于它的博客文章,但为了完整性,我在下面提供了完整的代码:
public class PDFTools {
private static final String GOOGLE_DRIVE_PDF_READER_PREFIX = "http://drive.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
*/
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
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.
openPDF( context, Uri.fromFile( tempFile ) );
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.pdf_show_local_progress_content ), 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 ) {
openPDF( context, Uri.fromFile( tempFile ) );
}
}
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 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.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.setDataAndType( Uri.fromFile( tempFile ), PDF_MIME_TYPE );
return context.getPackageManager().queryIntentActivities( i, PackageManager.MATCH_DEFAULT_ONLY ).size() > 0;
}
}
其他回答
我有GoogleDrive选项的问题,有时它会无法加载文档和“com.github.barteksc:android-pdf-viewer:2.7.0”,虽然它的文档使它看起来很容易从链接加载文档,但我未能使它工作。它总是抛出一个FileNotFoundException异常,因此经过进一步研究,我了解到它下载pdf,因此您必须使它指向该文档,我发现这有点乏味。
你可以试试这个库。它非常容易使用,并且至今仍在维护,我不知道几年之后他们是否会停止更新它。它会缓存文档,你甚至不需要跟踪它的路径。
https://levelup.gitconnected.com/open-pdf-files-in-android-without-webviews-or-intents-3cc960752cca
public class MyPdfViewActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView mWebView=new WebView(MyPdfViewActivity.this);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setPluginsEnabled(true);
mWebView.loadUrl("https://docs.google.com/gview?embedded=true&url="+LinkTo);
setContentView(mWebView);
}
}
以下是如何在不使用任何第三方库的情况下从PDF文件中获得位图缩略图的方法。
private fun loadThumbnailFromPdfFile(file:File, thumbnailImageView: ImageView) {
Log.d(TAG, "loadThumbnailFromPdfFile: ")
val mFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY)
// This is the PdfRenderer we use to render the PDF.
val mPdfRenderer = PdfRenderer(mFileDescriptor)
//check if pdf have no pages then we can't show pdf thumbnail
if (mPdfRenderer.pageCount <= 0) {
//No pages in pdf, can't show thumbnail
Log.d(TAG, "loadThumbnailFromPdfFile: No pages in pdf")
} else {
//There are page(s) in pdf, can show pdf thumbnail
//Use `openPage` to open a specific page in PDF.
val mCurrentPage = mPdfRenderer.openPage(0)
// Important: the destination bitmap must be ARGB (not RGB).
val bitmap = Bitmap.createBitmap(mCurrentPage.width, mCurrentPage.height, Bitmap.Config.ARGB_8888)
// Here, we render the page onto the Bitmap.
// To render a portion of the page, use the second and third parameter. Pass nulls to get
// the default result.
// Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
// We are ready to show the Bitmap to user.
thumbnailImageView.setImageBitmap(bitmap)
}
}
我从这篇文章和其他类似文章的一些答案中得出了一个混合的方法:
此解决方案检查PDF阅读器应用程序是否已安装,并执行以下操作: —如果设备上安装了PDF阅读器,请将PDF文件下载到设备上,并打开PDF阅读器应用 —如果没有安装阅读器,请询问用户是否希望通过谷歌Drive在线查看PDF文件
注意!这个解决方案使用了在API9 (Android 2.3或Gingerbread)中引入的Android DownloadManager类。这意味着它不能在Android 2.2或更早的版本上运行。
我在这里写了一篇关于它的博客文章,但为了完整性,我在下面提供了完整的代码:
public class PDFTools {
private static final String GOOGLE_DRIVE_PDF_READER_PREFIX = "http://drive.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
*/
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
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.
openPDF( context, Uri.fromFile( tempFile ) );
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.pdf_show_local_progress_content ), 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 ) {
openPDF( context, Uri.fromFile( tempFile ) );
}
}
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 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.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.setDataAndType( Uri.fromFile( tempFile ), PDF_MIME_TYPE );
return context.getPackageManager().queryIntentActivities( i, PackageManager.MATCH_DEFAULT_ONLY ).size() > 0;
}
}
下载源代码在这里(显示PDF文件在我的android应用程序)
在你的年级中添加这个依赖项: 编译com.github.barteksc: android-pdf-viewer: 2.0.3
activity_main.xml
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@color/colorPrimaryDark"
android:text="View PDF"
android:textColor="#ffffff"
android:id="@+id/tv_header"
android:textSize="18dp"
android:gravity="center"></TextView>
<com.github.barteksc.pdfviewer.PDFView
android:id="@+id/pdfView"
android:layout_below="@+id/tv_header"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
MainActivity.java
import android.app.Activity;
import android.database.Cursor;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener;
import com.github.barteksc.pdfviewer.listener.OnPageChangeListener;
import com.github.barteksc.pdfviewer.scroll.DefaultScrollHandle;
import com.shockwave.pdfium.PdfDocument;
import java.util.List;
public class MainActivity extends Activity implements OnPageChangeListener,OnLoadCompleteListener{
private static final String TAG = MainActivity.class.getSimpleName();
public static final String SAMPLE_FILE = "android_tutorial.pdf";
PDFView pdfView;
Integer pageNumber = 0;
String pdfFileName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pdfView= (PDFView)findViewById(R.id.pdfView);
displayFromAsset(SAMPLE_FILE);
}
private void displayFromAsset(String assetFileName) {
pdfFileName = assetFileName;
pdfView.fromAsset(SAMPLE_FILE)
.defaultPage(pageNumber)
.enableSwipe(true)
.swipeHorizontal(false)
.onPageChange(this)
.enableAnnotationRendering(true)
.onLoad(this)
.scrollHandle(new DefaultScrollHandle(this))
.load();
}
@Override
public void onPageChanged(int page, int pageCount) {
pageNumber = page;
setTitle(String.format("%s %s / %s", pdfFileName, page + 1, pageCount));
}
@Override
public void loadComplete(int nbPages) {
PdfDocument.Meta meta = pdfView.getDocumentMeta();
printBookmarksTree(pdfView.getTableOfContents(), "-");
}
public void printBookmarksTree(List<PdfDocument.Bookmark> tree, String sep) {
for (PdfDocument.Bookmark b : tree) {
Log.e(TAG, String.format("%s %s, p %d", sep, b.getTitle(), b.getPageIdx()));
if (b.hasChildren()) {
printBookmarksTree(b.getChildren(), sep + "-");
}
}
}
}
推荐文章
- 在Android Studio中改变矢量资产的填充颜色
- 在构建中编写注释的语法是什么?gradle文件?
- 如何以编程方式添加按钮色调
- 用Android Studio进行调试永远停留在“等待调试器”状态
- Java 8流和数组操作
- Java Regex捕获组
- Openssl不被视为内部或外部命令
- 如何添加自定义方法到Spring Data JPA
- 如何在Ubuntu中设置Java环境路径
- 无法执行dex:在Eclipse中超过GC开销限制
- 有人能解释一下JPA和Hibernate中的mappedBy吗?
- 是什么导致JNI调用变慢?
- Java中的&和&&有什么区别?
- 使用Java的Collections.singletonList()?
- 如何以编程方式将视图添加到视图