PDF文件大家应该不陌生,说的简单点,其实我认为就是一个全图片的Word,里面的每个页面都可以看做是一张带文字的图片,接下来我们看看在Android应用里如何读取和查看PDF文件内容。
compile 'com.joanzapata.pdfview:android-pdfview:1.0.4@aar'
先看看布局文件代码
其中PDFView控件就是pdfview库里面的查看PDF的控件,接下来声明并初始化后查看本地Asserts资源下的PDF文件,代码如下
pdf.fromAsset("abcd.pdf") .defaultPage(1) .showMinimap(false) .enableSwipe(true) .onPageChange(this) .load();
这样就可以查看pdf文件内容了,但是如果是网上在线查看PDF文件该如何实现呢?
我的思路是这样:
第一步,把PDF文件下载下来;
第二步,把文件保存在手机存储中;
第三步,读取手机SD卡的PDF文件。
接下来就一步一步实现,当然下载、保存、读取SD卡的内容首先就得有权限,相关权限的申请就不多说了,基本功你懂得!
下载的话方式很多,你可以用任何可以下载文件的网络框架,我用的是okhttp下载的,代码如下
/** * 下载 */ private void downloadFile() { OkHttpUtils.build().download(path, savePath, new OkHttpUtils.OnDownloadListener() { @Override public void onDownloadSuccess(File file) { tvPage.setText("加载完成正在打开.."); showPdf(file.getPath()); } @Override public void onDownloading(int progress) { Log.i("JAVA", "onDownloading"+progress); tvPage.setText("正在加载("+progress+"/100)"); } @Override public void onDownloadFailed() { Log.i("JAVA", "onDownloadFailed"); tvPage.setText("加载失败.."); } }); }
下载方法中path是网络上PDF文件的额下载全路径,savePath是下载下来的文件保存的目录,onDownloadSuccess是下载完成后的回调方法,回调的是下载的文件,file.getPath()可以获取这个文件保存的路径地址,okhttp我自己封装了一个工具类,代码奉上
** * OkHttp3工具类 * 2018/9/11 */ public class OkHttpUtils { private static OkHttpClient client; private static OkHttpUtils okHttpUtils; private OkHttpCallback callback; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 1://异常 IOException e = (IOException) msg.obj; LogUtils.i("ruin", "e--> " + e.toString()); callback.onError(e); break; case 2://成功 String result = (String) msg.obj; callback.onResponse(result); break; } } }; /** * http请求 */ public static OkHttpUtils build() { OkHttpClient.Builder sBuilder = new OkHttpClient.Builder(); client = sBuilder.build(); okHttpUtils = new OkHttpUtils(); return okHttpUtils; } //设置回调方法 public OkHttpUtils setCallback(OkHttpCallback callback) { this.callback = callback; return okHttpUtils; } //post请求 public OkHttpUtils postOkHttp(String url, Mapparams) { FormBody.Builder builder = new FormBody.Builder(); String temp = ""; for (String key : params.keySet()) { builder.add(key, String.valueOf(params.get(key))); temp += (key + "=" + String.valueOf(params.get(key)) + "&"); } LogUtils.i("LogUtils", "url =" + url + "?" + temp); FormBody formBody = builder.build(); Request request = new Request.Builder() .url(url) .post(formBody) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Message msg = Message.obtain(); msg.what = 1; msg.obj = e; handler.sendMessage(msg); } @Override public void onResponse(Call call, Response response) throws IOException { String result = response.body().string(); Message msg = Message.obtain(); msg.what = 2; msg.obj = result; handler.sendMessage(msg); } }); return okHttpUtils; } public OkHttpUtils postAsync(String url, Map params) { RequestBody requestBody; if (params == null) { params = new HashMap<>(); } /** * OKhttp3.0之后版本 */ FormBody.Builder builder = new FormBody.Builder(); /** * 在这对添加的参数进行遍历,map遍历有四种方式,如果想要了解的可以网上查找 */ String temp = ""; for (Map.Entry map : params.entrySet()) { String key = map.getKey(); Object value; value = map.getValue() == null ? "" : map.getValue(); builder.add(key, String.valueOf(value)); temp += (key + "=" + String.valueOf(value)); } LogUtils.i("LogUtils", "url =" + url + "?" + temp); requestBody = builder.build(); final Request request = new Request.Builder().url(url).post(requestBody).build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Message msg = Message.obtain(); msg.what = 1; msg.obj = e; handler.sendMessage(msg); } @Override public void onResponse(Call call, Response response) throws IOException { String result = response.body().string(); Message msg = Message.obtain(); msg.what = 2; msg.obj = result; handler.sendMessage(msg); } }); return okHttpUtils; } //请求回调接口 public interface OkHttpCallback { void onError(Exception e); void onResponse(String result); } /** * 判断是否有网络连接 */ private boolean isNetworkConnected(@NonNull Context context) { ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo(); return mNetworkInfo != null && mNetworkInfo.isAvailable(); } /** * @param url 下载连接 * @param saveDir 储存下载文件的SDCard目录 * @param listener 下载监听 */ public void download(final String url, final String saveDir, final OnDownloadListener listener) { Request request = new Request.Builder().url(url).build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // 下载失败 listener.onDownloadFailed(); } @Override public void onResponse(Call call, Response response) throws IOException { InputStream is = null; byte[] buf = new byte[2048]; int len = 0; FileOutputStream fos = null; // 储存下载文件的目录 String savePath = isExistDir(saveDir); try { is = response.body().byteStream(); long total = response.body().contentLength(); File file = new File(savePath, getNameFromUrl(url)); fos = new FileOutputStream(file); long sum = 0; while ((len = is.read(buf)) != -1) { fos.write(buf, 0, len); sum += len; int progress = (int) (sum * 1.0f / total * 100); // 下载中 listener.onDownloading(progress); } fos.flush(); // 下载完成 listener.onDownloadSuccess(file); } catch (Exception e) { listener.onDownloadFailed(); } finally { try { if (is != null) { is.close(); } } catch (IOException e) { } try { if (fos != null) { fos.close(); } } catch (IOException e) { } } } }); } /** * 判断下载目录是否存在 */ private String isExistDir(String saveDir) throws IOException { // 下载位置 File downloadFile = new File(Environment.getExternalStorageDirectory(), saveDir); if (!downloadFile.mkdirs()) { downloadFile.createNewFile(); } String savePath = downloadFile.getAbsolutePath(); return savePath; } /** * 从下载连接中解析出文件名 */ @NonNull private String getNameFromUrl(String url) { return url.substring(url.lastIndexOf("/") + 1); } public interface OnDownloadListener { /** * 下载成功 */ void onDownloadSuccess(File file); /** * 下载进度 */ void onDownloading(int progress); /** * 下载失败 */ void onDownloadFailed(); } }
当然要用okhttp下载需要添加okhttp库文件,我用的是okhttp3
compile 'com.squareup.okhttp3:okhttp:3.9.0'
在上面下载成功的回调方法里传入下载的PDF文件路径打开文件 showPdf(file.getPath());
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() { @Override public 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); } } }
打开之后就可以查看了,和查看Asserts资源下的PDF文件基本一样了,有一个点差点忘了就是实现OnPageChangeListener接口,然后在重写的onPageChanged方法中显示当前查看的页面是多少页和一共有多少页
@Override public void onPageChanged(int page, int pageCount) { String pager = "页码(" + page + "/" + pageCount + ")"; tvPage.setText(pager); }
好了,pdf文件查看就这样完成了,谁有更好的方法可以互相推荐学习。