最近有一个预览pdf的功能要去实现,就是纯展示 。同时附带介绍了计时器的实现,即在阅读的时候计算一下用户读了多久 就是为了展示一个阅读时间。
首先就是在build.gradle中添加依赖
//pdfView
implementation 'com.github.barteksc:android-pdf-viewer:2.7.0-beta.1'
接下来是在xml中的引用
<com.github.barteksc.pdfviewer.PDFView
android:id="@+id/pdfView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
注意:pdfView的高一定要match_parent 撑满整个屏幕
最后是Activity的引用
//在Activity的一些绑定布局 绑定id就省略掉了
//需要定义的一些相关字段
private String cacheUrl;
private Handler handler;
private String pdfName;
String pdfPath;
boolean flag = false;
boolean isFirst = true;
//------------------------------------------------------------
//计时器相关定义
private int seconds = 0;
private boolean running = false; //计时状态
private boolean wasRunning = false; //保存running的状态
private int trainId;//文件id
//onCreate中做如下操作 picUrl 只是测试使用 最后需要对接你们后端给的相关接口
String picUrl = "http://www.nuaa.edu.cn//_upload/article/files/3d/8d/78ed42f44031bcb6793b0eb27af1/8e6ad93b-4902-4fd8-bba5-bfabaf852885.pdf";
pdfPath = picUrl;
dowloadPDF(picUrl);
//查看pdf的方法
public void seePdf(File file) {
pdfView.fromFile(file)
.enableSwipe(true)
.swipeHorizontal(false)
.enableDoubletap(true)
.defaultPage(0)
.enableAnnotationRendering(true)
.password(null)
.onPageScroll(new OnPageScrollListener() {
@Override
public void onPageScrolled(int page, float positionOffset) {//当pdf开始滑动就开始计时,如果不需要 这个方法可以不要
if (flag) {
if (isFirst) {
Log.e("ping", "开始倒计时");
running = true;//这里插入了一个倒计时的方法 为的是知道用户阅读了多久 显示一个时间
isFirst = false;
}
} else {
flag = true;
}
}
})
.load();
}
//下载pdf的方法
public void dowloadPDF(String str) {
this.cacheUrl = getCacheDir().getAbsolutePath();
String str2 = this.pdfPath;
if (str2 == null) {
Log.e("ping", "暂无文件");
return;
}
String[] split = this.pdfPath.split("/");
if (split == null || split.length <= 0) {
this.pdfName = SystemClock.currentThreadTimeMillis() + ".pdf";
} else {
this.pdfName = split[split.length - 1];
}
final File file = new File(this.cacheUrl, this.pdfName);
if (file.exists()) {
seePdf(file);
return;
}
new OkHttpClient().newCall(new Request.Builder().url(str).build()).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.e("ping", "下载失败");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
Log.e("ping", "下载完成");
BufferedSink bufferedSink = null;
try {
if (!file.exists()) {
file.createNewFile();
}
bufferedSink = Okio.buffer(Okio.sink(file));
bufferedSink.writeAll(response.body().source());
bufferedSink.close();
if (TrainDetailActivity.this.handler == null) {
TrainDetailActivity.this.handler = new Handler(Looper.getMainLooper());
}
TrainDetailActivity.this.handler.post(new Runnable() {
public void run() {
TrainDetailActivity.this.seePdf(file);
}
});
if (bufferedSink == null) {
return;
}
} catch (Exception e) {
e.printStackTrace();
if (0 == 0) {
return;
}
} catch (Throwable th) {
if (0 != 0) {
bufferedSink.close();
}
throw th;
}
bufferedSink.close();
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
//另一种加载方式的释放
QbSdk.closeFileReader(this);
}
//-----------------------------------------------下面是计时器的实现
//app进入后台 暂停计时
@Override
protected void onStop() {
super.onStop();
wasRunning = running;
running = false;
}
//重新进入app,开始计时
@Override
protected void onStart() {
super.onStart();
if (wasRunning) running = true;
}
//失去焦点(如分屏),暂停计时
@Override
protected void onPause() {
super.onPause();
wasRunning = running;
running = false;
}
//获得焦点,重新开始计时
@Override
protected void onResume() {
super.onResume();
if (wasRunning) running = true;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//获取保存的状态
if (savedInstanceState != null) {
seconds = savedInstanceState.getInt("seconds");
running = savedInstanceState.getBoolean("running");
wasRunning = savedInstanceState.getBoolean("wasRunning");
}
runTime();
}
/**
* 保存状态
*/
@Override
public void onSaveInstanceState(Bundle saveInstanceState) {
super.onSaveInstanceState(saveInstanceState);
saveInstanceState.putInt("seconds", seconds);
saveInstanceState.putBoolean("running", running);
saveInstanceState.putBoolean("wasRunning", wasRunning);
}
/**
* 注意 ui线程不能被堵塞,因此不能在ui线程中调用sleep方法
* 只允许ui线程更新界面,不能在后台线程更新界面
* <p>
* ** 使用ui线程的Handler定时更新 **
* 将任务封装到 Runnable的run方法中 ,通过Handler的
* post(立即提交任务)或postDelayed(实现定时调度)方法提交到ui线程
*/
private void runTime() {
final Handler handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
/* int hour = seconds / 3600 % 24;
int minute = seconds % 3600 / 60;
String time = String.format("%02d:%02d:%02d", hour, minute, seconds % 60);*/
if (running) seconds++;
handler.postDelayed(this, 1000);
}
}
);
}
网友评论