关于腾讯tbs的介绍,请查看官网:https://x5.tencent.com/tbs/product/tbs.html
官网接入文档:https://x5.tencent.com/tbs/guide/sdkInit.html
官网上对文件预览写的并不详细,这篇主要讲解文件预览服务. 网络下载框架使用的是okGo.
compile ‘com.lzy.net:okgo:3.0.4’
需要将官网下载的jar包放入libs文件夹下
使用腾讯tbs需要在Application中注册.
QbSdk.initX5Environment(this,null);
这个也没有在github上写demo,所以就直接用目前项目的(跟项目隐私相关的代码已去除)
布局文件的加载等待框用的是开源的AVLoadingIndicatorView
下面是布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/rl_root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_wangsu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="当前网速:0KB/s"
android:layout_marginTop="10dp"
android:layout_centerInParent="true"
android:gravity="center"
android:textSize="10sp"
android:textColor="@color/colorAccent"
/>
<com.wang.avi.AVLoadingIndicatorView
android:id="@+id/avi"
style="@style/AVLoadingIndicatorView.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
app:indicatorColor="@color/colorAccent"
android:layout_centerInParent="true"
android:layout_below="@+id/tv_wangsu"
app:indicatorName="BallClipRotateMultipleIndicator" />
<TextView
android:id="@+id/tv_proess"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="当前进度:0%"
android:layout_marginTop="10dp"
android:layout_below="@+id/avi"
android:gravity="center"
android:textSize="10sp"
android:textColor="@color/colorAccent"
/>
</RelativeLayout>
主要代码:
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.example.huanhang.henanapp.R;
import com.example.huanhang.henanapp.util.FileUtils;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.FileCallback;
import com.lzy.okgo.model.Progress;
import com.lzy.okgo.model.Response;
import com.tencent.smtt.sdk.TbsReaderView;
import com.wang.avi.AVLoadingIndicatorView;
import java.io.File;
import java.text.DecimalFormat;
/**
* @author lei
* @desc 使用腾讯TBS阅览
* @date 2018/10/31 0031 -- 上午 8:54.
*/
public class ShowPdf2Activity extends AppCompatActivity implements TbsReaderView.ReaderCallback {
AVLoadingIndicatorView avi;
TextView pro;
TextView wangSu;
private TbsReaderView mTbsReaderView;
private String mFileName;
private String mUrl;
private RelativeLayout mRlRoot;
private String path = Environment.getExternalStorageDirectory() + "/tbsTest/" + "/File/";
public static String getDataSize(long size) {
if (size < 0) {
size = 0;
}
DecimalFormat formater = new DecimalFormat("####.00");
if (size < 1024) {
return size + "b";
} else if (size < 1024 * 1024) {
float kbsize = size / 1024f;
return formater.format(kbsize) + "k";
} else if (size < 1024 * 1024 * 1024) {
float mbsize = size / 1024f / 1024f;
return formater.format(mbsize) + "M";
} else if (size < 1024 * 1024 * 1024 * 1024) {
float gbsize = size / 1024f / 1024f / 1024f;
return formater.format(gbsize) + "G";
} else {
return String.valueOf(size);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_pdf2);
initView();
String pdfPath = getIntent().getStringExtra("pdfPath");
mUrl = FILE_BASE_URL + pdfPath;
//预览文件相关类
mTbsReaderView = new TbsReaderView(ShowPdf2Activity.this, this);
mRlRoot.addView(mTbsReaderView, new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mFileName = parseName(mUrl);
checkSDCardPermission();
boolean existsDir = FileUtils.createOrExistsDir(path);
//首先判断本地是否有该文件,有就直接打开,否则就先下载
if (existsDir) {
if (isLocalExist()) {
displayFile();
} else {
downLoad(mUrl, path, mFileName);
}
}
}
private String parseName(String url) {
String fileName = null;
try {
fileName = url.substring(url.lastIndexOf("/") + 1);
} finally {
if (TextUtils.isEmpty(fileName)) {
fileName = String.valueOf(System.currentTimeMillis());
}
}
return fileName;
}
@Override
protected void onDestroy() {
super.onDestroy();
mTbsReaderView.onStop();
FileUtils.deleteFile(getLocalFile());
}
private void displayFile() {
//解决部分手机无法预览问题
String bsReaderTemp = "/storage/emulated/0/TbsReaderTemp";
File file = new File(bsReaderTemp);
if (!file.exists()) {
boolean mkdirs = file.mkdirs();
if (!mkdirs) {
Toast.makeText(this, "创建/storage/emulated/0/TbsReaderTemp失败!", Toast.LENGTH_SHORT).show();
}
}
Bundle bundle = new Bundle();
bundle.putString("filePath", getLocalFile().getPath());
bundle.putString("tempPath", Environment.getExternalStorageDirectory()+ "/" + "TbsReaderTemp");
boolean result = mTbsReaderView.preOpen(parseFormat(mFileName), false);
if (result) {
mTbsReaderView.openFile(bundle);
}
}
private File getLocalFile() {
return new File(path, mFileName);
}
private String parseFormat(String fileName) {
return fileName.substring(fileName.lastIndexOf(".") + 1);
}
private void initView() {
mRlRoot = (RelativeLayout) findViewById(R.id.rl_root);
pro = (TextView) findViewById(R.id.tv_proess);
avi = (AVLoadingIndicatorView) findViewById(R.id.avi);
wangSu = (TextView) findViewById(R.id.tv_wangsu);
}
private void downLoad(String url, String destFileDir, String destFileName) {
OkGo.<File>get(url).headers("user", mFileName)
.execute(new FileCallback(destFileDir, destFileName) {
@Override
public void downloadProgress(Progress progress) {
super.downloadProgress(progress);
pro.setText("当前进度:" + Math.round(progress.fraction * 100) + "%");
wangSu.setText("当前网速:" + getDataSize(progress.speed) + "/s");
}
@Override
public void onSuccess(Response<File> response) {
Log.d("EasyHttpActivity", "下载完成");
avi.setVisibility(View.GONE);
pro.setText("下载完成,正在加载...");
wangSu.setVisibility(View.GONE);
displayFile();
}
});
}
@Override
public void onCallBackAction(Integer integer, Object o, Object o1) {
}
private void checkSDCardPermission() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0x01);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 0x01) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//获取权限
downLoad(mUrl, path, mFileName);
} else {
Toast.makeText(this, "权限被禁止,无法下载文件!", Toast.LENGTH_SHORT).show();
}
}
}
private boolean isLocalExist() {
return getLocalFile().exists();
}
}
这就是整个文件预览流程,代码可直接拿来用,来说下中间使用的坑
有用户反应在他平板上无法打开文件,android8.0,在我手机上没问题(android6.0),查看了代码,主要有两点原因
- 没初始化
- 无TbsReaderTemp文件夹
代码里已解决