下面介绍几种可行性较高的方案

一.PDFView

这个比较早,有几年没更新了,但可以满足一般的需求,手势放大缩小,左右滑动,体积也较小,对于Android版本可以兼容到较低版本,缺点也比较明显,不能查看带有水印和超链接的PDF

1.添加依赖 compile 'com.joanzapata.pdfview:android-pdfview:1.0.4@aar'

2.适用场景:加载本地asserts中的资源;加载内存中的文件(其实在线预览也就是先下载,然后查看)

3.show code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:id="@+id/tv_page"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="@color/colorAccent"android:textSize="18sp" /><com.joanzapata.pdfview.PDFViewandroid:id="@+id/pdf"android:layout_width="match_parent"android:layout_height="match_parent" />
</LinearLayout>
 
 
 
public class PdfReadActivity extends AppCompatActivity implements OnPageChangeListener {public static final String APP_NAME = "my/pdf";public static final String IS_LOAD_COMPLETE = "is_load_complete";public static final int LOAD_CANCEL = 0;public static final int LOAD_ERROR = 1;private MyHandler myHandler;private PDFView pdf;private TextView tvPage;private AsyncTask<String, Integer, String> task;private String pdfName;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_pdf_read);pdf = (PDFView) findViewById(R.id.pdf);tvPage = (TextView) findViewById(R.id.tv_page);//Asserts资源查看
//        pdf.fromAsset("sample.pdf")
//                .defaultPage(1)
//                .showMinimap(false)
//                .enableSwipe(true)
//                .onPageChange(this)
//                .load();
//String path = getIntent().getStringExtra("path");myHandler = new MyHandler(this);if (TextUtils.isEmpty(path)) {Toast.makeText(this, "文件不存在", Toast.LENGTH_SHORT).show();finish();}startOpenPdf(path);}private void startOpenPdf(String path) {getPdfName(path);boolean isLoadComplete = SharedPreferencesUtils.getBooleanParam(this, IS_LOAD_COMPLETE, false);String pdfPath = checkApkExist();//若存在pdf文件...不存在则直接下载if (!TextUtils.isEmpty(pdfPath)) {if (isLoadComplete) {showPdf(pdfPath);} else {File file = new File(FileUtils.getRootFilePath() + APP_NAME, pdfName);FileUtils.deleteFile(file);task = new DownPdfFileTask().execute(path);}} else {task = new DownPdfFileTask().execute(path);}}private void getPdfName(String path) {try {URL url = new URL(path);String urlPath = url.getPath();pdfName = urlPath.substring(urlPath.lastIndexOf("/") + 1);} catch (Exception e) {e.printStackTrace();}}private String checkApkExist() {String path = FileUtils.getRootFilePath() + APP_NAME;File file = new File(path, pdfName);return file.exists() ? path + "/" + pdfName : "";}private class DownPdfFileTask extends AsyncTask<String, Integer, String> {private File pdfFile;String result = null;@Overrideprotected String doInBackground(String... params) {InputStream input = null;FileOutputStream fos = null;try {URL url = new URL(params[0]);String urlPath = url.getPath();pdfName = urlPath.substring(urlPath.lastIndexOf("/") + 1);url = new URL("http://resourcetest.com/" + URLEncoder.encode(pdfName));HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setConnectTimeout(10000);connection.setRequestMethod("GET");if (HttpURLConnection.HTTP_OK != connection.getResponseCode()) {return null;}String pdkDir = FileUtils.getRootFilePath() + APP_NAME;FileUtils.createDirectory(pdkDir);pdfFile = new File(pdkDir, pdfName);input = new BufferedInputStream(connection.getInputStream());fos = new FileOutputStream(pdfFile);int count;byte buf[] = new byte[1024];while ((count = input.read(buf)) != -1) {if (isCancelled()) {break;}fos.write(buf, 0, count);}result = pdkDir + "/" + pdfName;} catch (IOException e) {e.printStackTrace();if (pdfFile != null && pdfFile.exists()) {pdfFile.delete();result = null;}myHandler.sendEmptyMessage(LOAD_ERROR);} finally {if (null != fos) {try {fos.flush();fos.close();} catch (IOException e) {e.printStackTrace();}}if (null != input) {try {input.close();} catch (IOException e) {e.printStackTrace();}}}return result;}@Overrideprotected void onPostExecute(String s) {super.onPostExecute(s);if (!TextUtils.isEmpty(s)) {Message message = new Message();Bundle bundle = new Bundle();bundle.putString("path", s);message.setData(bundle);myHandler.sendMessage(message);}}}private void showPdf(String fileName) {if (TextUtils.isEmpty(fileName)) {Toast.makeText(this, "文件不存在", Toast.LENGTH_SHORT).show();} else {try {pdf.fromFile(new File(fileName)).defaultPage(1).showMinimap(false).enableSwipe(true).onLoad(new OnLoadCompleteListener() {@Overridepublic void loadComplete(int nbPages) {float pageWidth = pdf.getOptimalPageWidth();float viewWidth = pdf.getWidth();pdf.zoomTo(viewWidth / pageWidth);pdf.loadPages();}}).onPageChange(this).load();} catch (FileNotFoundException e) {Toast.makeText(this, "文件不存在", Toast.LENGTH_SHORT).show();File file = new File(fileName);FileUtils.deleteFile(file);}}}@Overridepublic void onPageChanged(int page, int pageCount) {tvPage.setText(getString(R.string.page_count, page, pageCount));}static class MyHandler extends Handler {private WeakReference<PdfReadActivity> weakReference;MyHandler(PdfReadActivity activity) {weakReference = new WeakReference<>(activity);}@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);PdfReadActivity activity = weakReference.get();int what = msg.what;if (null != activity) {if (LOAD_ERROR == what) {Toast.makeText(activity, "文件读取失败,请重试", Toast.LENGTH_SHORT).show();} else if (LOAD_CANCEL == what) {SharedPreferencesUtils.saveBooleanParam(activity, IS_LOAD_COMPLETE, false);}Bundle data = msg.getData();if (null != data) {String path = (String) data.get("path");SharedPreferencesUtils.saveBooleanParam(activity, IS_LOAD_COMPLETE, true);activity.showPdf(path);}}}}@Overrideprotected void onDestroy() {if (task != null && task.getStatus() == AsyncTask.Status.RUNNING) {SharedPreferencesUtils.saveBooleanParam(this, IS_LOAD_COMPLETE, false);task.cancel(true);}super.onDestroy();}
}
 
 
 
//文件工具类
 
public class FileUtils { public static boolean hasSDCard() { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);  }
 
 
public static String getRootFilePath() { if (hasSDCard()) { // filePath:/sdcard/  return Environment.getExternalStorageDirectory().getAbsolutePath() + "/";  } else { // filePath: /data/data/  return Environment.getDataDirectory().getAbsolutePath() + "/data/";  } }
 

补充:compile 'com.lidong.pdf:android_pdf:1.0.1'

这个是也算是上者的升级版,内部封装好了Retrofit 网络下载,也做了缓存,一次只能缓存一个,主要是通过文件名是否一致来判断,所以喜欢简单的,也可以试试,毕竟一行代码解决很吸引人

二.Android自带PdfRenderer

这个是Google的,对于apk不会增加体积为0,乍看很有诱惑,但是可惜的是最低支持5.0系统,核心是转换成图片然后显示

1.适用场景:同上

2.show code

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ImageViewandroid:id="@+id/iv"android:layout_width="match_parent"android:layout_height="match_parent" /><Buttonandroid:id="@+id/btn_previous"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:text="上一页" /><Buttonandroid:id="@+id/btn_next"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_alignParentRight="true"android:text="下一页" /></RelativeLayout>
 
 
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public class AndroidPdfViewActivity extends AppCompatActivity implements View.OnClickListener { /**  * Key string for saving the state of current page index.  */  private static final String STATE_CURRENT_PAGE_INDEX = "current_page_index";   /**  * The filename of the PDF.  */  private static final String FILENAME = "sample.pdf";    /**  * File descriptor of the PDF.  */  private ParcelFileDescriptor mFileDescriptor;   /**  * Page that is currently shown on the screen.  */  private PdfRenderer.Page mCurrentPage;   /**  * PDF page index  */  private int mPageIndex;   /**  * {@link android.graphics.pdf.PdfRenderer} to render the PDF.  */  private PdfRenderer mPdfRenderer;  private ImageView mImageView;  private Button btnPrevious;  private Button btnNext;   @Override  protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState);  if (null != mCurrentPage) { outState.putInt(STATE_CURRENT_PAGE_INDEX, mCurrentPage.getIndex());  } } @Override  protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState);  setContentView(R.layout.activity_third_pdf_view);  mImageView = (ImageView) findViewById(R.id.iv);  btnPrevious = (Button) findViewById(R.id.btn_previous);  btnNext = (Button) findViewById(R.id.btn_next);   btnPrevious.setOnClickListener(this);  btnNext.setOnClickListener(this);  mPageIndex = 0;  // If there is a savedInstanceState (screen orientations, etc.), we restore the page index.  if (null != savedInstanceState) { mPageIndex = savedInstanceState.getInt(STATE_CURRENT_PAGE_INDEX, 0);  } } @Override  protected void onStart() { super.onStart();  try { openRenderer(this);  showPage(mPageIndex);  } catch (IOException e) { e.printStackTrace();  Toast.makeText(this, "Error! " + e.getMessage(), Toast.LENGTH_SHORT).show();  } } /**  * Sets up a {@link android.graphics.pdf.PdfRenderer} and related resources.  */  private void openRenderer(Context context) throws IOException { // In this sample, we read a PDF from the assets directory.  File file = new File(context.getCacheDir(), FILENAME);  if (!file.exists()) { // Since PdfRenderer cannot handle the compressed asset file directly, we copy it into  // the cache directory.  InputStream asset = getAssets().open(FILENAME);  FileOutputStream output = new FileOutputStream(file);  final byte[] buffer = new byte[1024];  int size;  while ((size = asset.read(buffer)) != -1) { output.write(buffer, 0, size);  } asset.close();  output.close();  } mFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);  // This is the PdfRenderer we use to render the PDF.  if (mFileDescriptor != null) { mPdfRenderer = new PdfRenderer(mFileDescriptor);  } } /**  * Shows the specified page of PDF to the screen.  *  * @param index The page index.  */  private void showPage(int index) { if (mPdfRenderer.getPageCount() <= index) { return;  } // Make sure to close the current page before opening another one.  if (null != mCurrentPage) { mCurrentPage.close();  } // Use `openPage` to open a specific page in PDF.  mCurrentPage = mPdfRenderer.openPage(index);  // Important: the destination bitmap must be ARGB (not RGB).  Bitmap bitmap = Bitmap.createBitmap(mCurrentPage.getWidth(), mCurrentPage.getHeight(),  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.  mImageView.setImageBitmap(bitmap);  updateUi();  } /**  * Closes the {@link android.graphics.pdf.PdfRenderer} and related resources.  *  * @throws java.io.IOException When the PDF file cannot be closed.  */  private void closeRenderer() throws IOException { if (null != mCurrentPage) { mCurrentPage.close();  } mPdfRenderer.close();  mFileDescriptor.close();  } @Override  protected void onDestroy() { try { closeRenderer();  } catch (IOException e) { e.printStackTrace();  } super.onDestroy();  } @Override  protected void onPause() { try { closeRenderer();  } catch (IOException e) { e.printStackTrace();  } super.onPause();  } /**  * Updates the state of 2 control buttons in response to the current page index.  */  private void updateUi() { int index = mCurrentPage.getIndex();  int pageCount = mPdfRenderer.getPageCount();  btnPrevious.setEnabled(0 != index);  btnNext.setEnabled(index + 1 < pageCount); // setTitle(getString(R.string.app_name_with_index, index + 1, pageCount));  } /**  * Gets the number of pages in the PDF. This method is marked as public for testing.  *  * @return The number of pages.  */  public int getPageCount() { return mPdfRenderer.getPageCount();  } @Override  public void onClick(View v) { switch (v.getId()) { case R.id.btn_previous: { // Move to the previous page  showPage(mCurrentPage.getIndex() - 1);  break;  } case R.id.btn_next: { // Move to the next page  showPage(mCurrentPage.getIndex() + 1);  break;  } } } }

三.Android PdfViewer

它是基于PdfiumAndroid解码PDF文件

compile 'com.github.barteksc:android-pdf-viewer:2.8.1'

1.适用场景很广,使用简单,唯一缺陷就是会明显增大包体积,所以就不多介绍了

Android应用内在线查看PDF文件相关推荐

  1. 小程序webview实现在线查看pdf文件

    long time no see,还是之前的webview项目新增需求,电子发票这块需要查看发票详情.针对这个需求,百度得出两种结论,一种是用小程序api调起文件,另一种是pdf插件.一开始我用的是p ...

  2. 浏览器在线查看pdf文件 pdf.js的使用教程

    谷歌浏览器可以直接在线查看pdf,而IE内核浏览器无法在线查看,默认是下载. 这里用到的是pdf.js,不仅支持IE内核浏览器,而且兼容手机查看pdf 官网地址:http://mozilla.gith ...

  3. h5移动端在线查看pdf文件 预览pdf文件 pdfh5.js

    要做移动端在线查看pdf的效果 最后选择了    pdfh5.js  强烈点赞   详情链接 https://www.gjtool.cn/articles/2019/09/04/15675716491 ...

  4. PDM solideworks 达索 在线查看PDF文件不完整的解决方式

    pdf文件显示不完整 solidworks出工程图转PDF字体乱码不显示的问题  百度的解决方式,在自己管理的PDM系统中这样的处理方式并未得到妥善解决.好歹哥们程序出身,架构也搞过一些.加工的部门的 ...

  5. Android通过WebView在线打开PDF文件(文中提供源码下载)

    这个是通过js解析,然后在webview中加载PDF文件,所以内库很小也就2兆多,体验也不错,不像Android别的第三方内库文件都很大,例如PDFview,MuPDF等,一个内库加进去,安装包要增加 ...

  6. Office Web App2013 在线查看PDF文件

    经常会有客户问,在SharePoint中,如何在浏览器中查看与编辑文档,通常给出的解决方案是集成Office Web App. 而在实际应用过程中,客户通常会要求实现PDF文件在线查看,对于PDF文件 ...

  7. java在线查看pdf文件,java 实现所有文件的在线查看(其他类型转pdf后用pdf.js显示)...

    js显示pdf插件demo下载: http://download.csdn.net/detail/heqinghua217/9685857 java 吧所有文档类文件转成pdf格式文件下载 http: ...

  8. 实现在线查看PDF文件

    效果图: 使用方法 引用所需两个文件 <script src="http://www.jq22.com/jquery/jquery-1.10.2.js"></sc ...

  9. php在线查看pdf文件

    readfile.php <?php if(!function_exists('read_pdf')) { function read_pdf($file) { if(strtolower(su ...

最新文章

  1. python3操作mysql教程_python3操作mysql教程
  2. 如何分析常见的TCP问题?
  3. mysql 之jdbc idea版
  4. 存储管理实验linux,07-存储管理器实验
  5. unity 显示、隐藏Android导航栏
  6. Atitit mysql 数据类型 5.7.9 目录 1.1. 数值类型 1 2. 字符串 2 3. 时间日期 2 4. 地理位置 2 5. 几何数据的存储,生成,分析,优化。 空间数据类型(存储)
  7. 华为路由器hilink怎么用_荣耀路由HiLink怎么实现一键组网?
  8. Spring Cloud 基础教程 - 程序猿DD
  9. 华为鸿蒙os logo,华为鸿蒙OS Logo曝光:Powered by HarmonyOS
  10. iPhone相机参数设置,苹果原相机也能拍出大片感
  11. AD10 BOM制作
  12. 百度推广关键字质量度优化指南
  13. win7空文件夹删不掉的原因及解决方法
  14. root用户无法启动vscode的解决方法
  15. ubuntu 下使用wireless拨号上网
  16. 6种不同画法画平行线_平行线的画法
  17. mysql压缩版安装教程 for Mac
  18. linux命令下载电影,Linux命令行用wget下载精彩电影
  19. 微信公众号开发---微信开发学习路线(及供参考)
  20. PO接收、检验、入库、退货-Interface+API-请求和在线完成

热门文章

  1. node.js(3):使用Express开发中的中间件
  2. Android Api Demos登顶之路(十)Overscan
  3. ps怎么保存一小块的图片_ps怎么复制图片的一部分
  4. QT 调用C语言生成的dll
  5. ElasticSearch权限控制实战
  6. IO操作 IO异常处理
  7. java电脑日历_Java中calendar对万年历的制作(同步电脑上的万年历日期格式)
  8. 玩转华为ENSP模拟器系列 | 配置Console用户界面举例
  9. Day0–MD语法+常用快捷键+常用dos命令
  10. 与领导说话要注意的几个方法