PDF文件大家应该不陌生,说的简单点,其实我认为就是一个全图片的Word,里面的每个页面都可以看做是一张带文字的图片,接下来我们看看在Android应用里如何读取和查看PDF文件内容。
1 在项目的gradle中增加如下代码:
compile 'com.joanzapata.pdfview:android-pdfview:1.0.4@aar'
先看看布局文件代码
<?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">
<include layout="@layout/title_all" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.joanzapata.pdfview.PDFView
android:id="@+id/pdf"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/tv_page"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textColor="@color/colorAccent"
android:layout_alignParentTop="true"
android:textSize="18sp" />
</RelativeLayout>
</LinearLayout>
其中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, Map<String, Object> params) {
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<String, Object> params) {
RequestBody requestBody;
if (params == null) {
params = new HashMap<>();
}
/**
* OKhttp3.0之后版本
*/
FormBody.Builder builder = new FormBody.Builder();
/**
* 在这对添加的参数进行遍历,map遍历有四种方式,如果想要了解的可以网上查找
*/
String temp = "";
for (Map.Entry<String, Object> 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文件查看就这样完成了,谁有更好的方法可以互相推荐学习。