Android集成騰訊X5實(shí)現(xiàn)文檔瀏覽功能
Android內(nèi)部沒有控件來直接顯示文檔,跳轉(zhuǎn)WPS或其他第三方文檔App體驗(yàn)性不好,使用騰訊X5內(nèi)核能很好的解決的這一問題。
一、下載騰訊X5內(nèi)核
1.前往https://x5.tencent.com/下載Android的內(nèi)核,新版本的騰訊X5可以直接在bulid.gradle集成 api 'com.tencent.tbs.tbssdk:sdk:43697',如果是在App里集成可以把a(bǔ)pi換成implementation

2.AndroidStudio導(dǎo)入騰訊X5
a.把下載好的jar包導(dǎo)入libs,然后run as,再把jnilibs導(dǎo)入main包下

b. module的build.gradle添加cpu適配

3.Application中騰訊X5初始化,在onCreate()方法調(diào)用init方法
QbSdk.initX5Environment(this, new QbSdk.PreInitCallback() {
@Override
public void onCoreInitFinished() {
}
@Override
public void onViewInitFinished(boolean b) {
Log.e("xxx","hasLoad"+b);
//此處將內(nèi)核加載是否成功的狀態(tài)保存到本地,SharePreference工具類可換為自己的
SharedPreferenceUtils.saveBoolean(getApplicationContext(),"hasLoad",b);
}
});
4.應(yīng)用內(nèi)調(diào)用,無論是否加載內(nèi)核,都是把在線的文檔下載到本地然后打開,不同的是,未加載內(nèi)核會(huì)借助QQ瀏覽器或其他App的文件瀏覽功能類似微信(這個(gè)調(diào)用,騰訊X5已自動(dòng)處理,我們無需關(guān)心),而加載內(nèi)核后,使用X5的TbsReaderView來打開文件,接下來就是具體代碼。
a.bulid.gradle中集成Retrofit,RxJava和進(jìn)度管理器ProgressManager
implementation 'io.reactivex:rxandroid:1.2.1' implementation 'com.squareup.retrofit2:converter-gson:2.3.0' implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0' implementation 'com.squareup.retrofit2:retrofit:2.3.0' implementation 'io.reactivex:rxjava:1.2.6' implementation 'me.jessyan:progressmanager:1.5.0'
寫網(wǎng)絡(luò)下載工具
public interface LoadFileApi {
@GET
Call<ResponseBody> loadPdfFile(@Url String fileUrl);
}
public class LoadFileModel {
//使用該方法來下載文件
public static void loadPdfFile(String url, Callback<ResponseBody> callback) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.baidu.com/")
.client(ProgressManager.getInstance().with(new OkHttpClient.Builder())
.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
LoadFileApi mLoadFileApi = retrofit.create(LoadFileApi.class);
if (!TextUtils.isEmpty(url)) {
Call<ResponseBody> call = mLoadFileApi.loadPdfFile(url);
call.enqueue(callback);
}
}
}
b.具體調(diào)用
首先注冊(cè)文件進(jìn)度下載監(jiān)聽
private ProgressDialog commonProgressDialog;//切換為自己的進(jìn)度控件
private ProgressInfo mLastDownloadingInfo;
ProgressManager.getInstance().addResponseListener(url, new ProgressListener() {
@Override
public void onProgress(ProgressInfo progressInfo) {
if (mLastDownloadingInfo == null) {
mLastDownloadingInfo = progressInfo;
}
//因?yàn)槭且哉?qǐng)求開始時(shí)的時(shí)間作為 Id ,所以值越大,說明該請(qǐng)求越新
if (progressInfo.getId() < mLastDownloadingInfo.getId()) {
return;
} else if (progressInfo.getId() > mLastDownloadingInfo.getId()) {
mLastDownloadingInfo = progressInfo;
}
int progress = mLastDownloadingInfo.getPercent();
commonProgressDialog.setProgress(progress);
Log.d("xxx", "--Download-- " + progress + " % " + mLastDownloadingInfo.getSpeed() + " byte/s " + mLastDownloadingInfo.toString());
if (mLastDownloadingInfo.isFinish()) {
//說明已經(jīng)下載完成
commonProgressDialog.dismiss();
Log.d("xxx", "--Download-- finish");
}
}
@Override
public void onError(long id, Exception e) {
e.printStackTrace();
new Handler().post(new Runnable() {
@Override
public void run() {
commonProgressDialog.dismiss();
}
});
}
});
}
然后打開文件
private static final String DOWN_DIR = Environment.getExternalStorageDirectory()
+ File.separator+"Download"; //文件下載的路徑,可以自定義
//打開文件
private void openFile(String filePath,String fileName) {
boolean hasLoad = SharedPreferenceUtils.getBoolean(mContext, "hasLoad");//是否記載內(nèi)核
if (hasLoad){
//展示文件的Activity
Intent intentDoc = new Intent(this,FileDisplayActivity.class);
intentDoc.putExtra("path",filePath);
intentDoc.putExtra("fileName",fileName);
startActivity(intentDoc);
}else {
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
Toast.makeText(this,"當(dāng)前SD不可用",Toast.LENGTH_LONG).show();
return;
}
try {
File file = new File(DOWN_DIR, fileName);
if (file.exists()){
QbSdk.openFileReader(this, file.getAbsolutePath(), null, new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.e("xxx",s);
}
});
} else {
downLoadFile(filePath,fileName);
}
} catch (Exception e) {
e.printStackTrace();
ToastUtils.showShortToast(mContext, "已下載過了");
}
}
}
private void downLoadFile(final String url, final String fileName) {
commonProgressDialog.show();
LoadFileModel.loadPdfFile(url, new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
InputStream is = null;
byte[] buf = new byte[2048];
int len;
FileOutputStream fos = null;
try {
ResponseBody responseBody = response.body();
if (responseBody != null) {
is = responseBody.byteStream();
final File file = new File(DOWN_DIR, fileName);
fos = new FileOutputStream(file);
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.flush();
//未加載內(nèi)核調(diào)用方法
QbSdk.openFileReader(mContext, file.getAbsolutePath(), null, new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
Log.e("xxx",s);
}
});
ToastUtils.showLongToast(MeetingDetailActivity.this, "下載成功,保存在Download文件夾下");
}
} catch (Exception e) {
commonProgressDialog.dismiss();
ProgressManager.getInstance().notifyOnErorr(url,e);
ToastUtils.showLongToast(MeetingDetailActivity.this, "下載失敗");
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
t.printStackTrace();
ToastUtils.showShortToast(MeetingDetailActivity.this, "下載失敗");
commonProgressDialog.dismiss();
}
});
}
FileDisplayActivity代碼,對(duì)于一些包名可以切換為自己的包名,還有一些第三方庫像進(jìn)度展示,也可以切換為自己的進(jìn)度控件
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import com.anshi.oatencentschool.R;
import com.anshi.oatencentschool.utils.DialogBuild;
import com.anshi.oatencentschool.utils.StatusBarUtils;
import com.anshi.oatencentschool.utils.ToastUtils;
import com.anshi.oatencentschool.utils.WeakHandler;
import com.anshi.oatencentschool.utils.filetool.LoadFileModel;
import com.anshi.oatencentschool.utils.filetool.SuperFileView2;
import com.kaopiz.kprogresshud.KProgressHUD;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import me.jessyan.progressmanager.ProgressListener;
import me.jessyan.progressmanager.ProgressManager;
import me.jessyan.progressmanager.body.ProgressInfo;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class FileDisplayActivity extends AppCompatActivity {
private String TAG = "FileDisplayActivity";
//Tencent 提供的TBS閱讀瀏覽功能,不借助第三方軟件打開office和pdf文件
private SuperFileView2 mSuperFileView;
private String filePath;
private TextView mTextView;
private static final String DOWN_DIR = Environment.getExternalStorageDirectory()
+ File.separator+"Download";
private String fileName;
private KProgressHUD commonProgressDialog;
private WeakHandler weakHandler = new WeakHandler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
int progress = msg.arg1;
if (progress==100){
commonProgressDialog.setProgress(progress);
commonProgressDialog.dismiss();
}else {
commonProgressDialog.setProgress(progress);
}
return true;
}
});
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_display);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON|WindowManager.LayoutParams.FLAG_FULLSCREEN);
commonProgressDialog = DialogBuild.getBuild().createCommonProgressDialog(this, "下載中");
init();
}
/**
* 初始化
*/
public void init() {
mTextView = (TextView) findViewById(R.id.file_album_name);
fileName = getIntent().getStringExtra("fileName");
int lastIndexOf = fileName.lastIndexOf(".");
String substring = fileName.substring(0, lastIndexOf);
mTextView.setText(substring);
mSuperFileView = (SuperFileView2) findViewById(R.id.mSuperFileView);
mSuperFileView.setOnGetFilePathListener(new SuperFileView2.OnGetFilePathListener() {
@Override
public void onGetFilePath(SuperFileView2 mSuperFileView2) {
getFilePathAndShowFile(mSuperFileView);
}
});
Intent intent = this.getIntent();
String path = (String) intent.getSerializableExtra("path");
if (!TextUtils.isEmpty(path)) {
Log.d(TAG, "文件path:" + path);
setFilePath(path);
}
mSuperFileView.show();
ProgressManager.getInstance().addResponseListener(path, new ProgressListener() {
@Override
public void onProgress(ProgressInfo progressInfo) {
int percent = progressInfo.getPercent();
Message obtain = Message.obtain();
obtain.arg1 = percent;
weakHandler.sendMessage(obtain);
}
@Override
public void onError(long id, Exception e) {
}
});
}
@Override
protected void onResume() {
super.onResume();
StatusBarUtils.setWindowStatusBarColor(this,R.color.color_main);
}
/**
* 顯示文件
* @param mSuperFileView2 控件
*/
private void getFilePathAndShowFile(SuperFileView2 mSuperFileView2) {
if (getFilePath().contains("http")&&!new File(DOWN_DIR, fileName).exists()) {//網(wǎng)絡(luò)地址要先下載
downLoadFile(getFilePath(),fileName,mSuperFileView2);
} else {
try {
mSuperFileView2.displayFile(new File(DOWN_DIR, fileName));
}catch (Exception e){
e.printStackTrace();
}
}
}
public void setFilePath(String fileUrl) {
this.filePath = fileUrl;
}
private String getFilePath() {
return filePath;
}
/**
* 回退上一級(jí)菜單
* @param view 控件
*/
public void onClick(View view) {
finish();
}
private void downLoadFile(final String url, final String fileName,final SuperFileView2 mSuperFileView2) {
commonProgressDialog.show();
LoadFileModel.loadPdfFile(url, new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
InputStream is = null;
byte[] buf = new byte[2048];
int len;
FileOutputStream fos = null;
try {
ResponseBody responseBody = response.body();
is = responseBody.byteStream();
final File file = new File(DOWN_DIR, fileName);
fos = new FileOutputStream(file);
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.flush();
mSuperFileView2.displayFile(file);
ToastUtils.showLongToast(FileDisplayActivity.this, "下載成功,保存在Download文件夾下");
} catch (Exception e) {
commonProgressDialog.dismiss();
ToastUtils.showLongToast(FileDisplayActivity.this, "下載失敗");
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
t.printStackTrace();
ToastUtils.showShortToast(FileDisplayActivity.this, "下載失敗");
commonProgressDialog.dismiss();
}
});
}
}
布局Layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_file_display"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="46dp"
android:background="@color/color_main"
android:id="@+id/file_toolbar"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/file_album_name"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:ellipsize="end"
android:textSize="14sp"
android:textColor="#FFF"
/>
</android.support.v7.widget.Toolbar>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/file_toolbar"
>
<com.anshi.oatencentschool.utils.filetool.SuperFileView2
android:id="@+id/mSuperFileView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_gravity="center|start"
android:layout_height="wrap_content">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:button="@null"
android:onClick="onClick"
android:id="@+id/back_icon"
android:drawableStart="@drawable/svg_left_back_blur"
android:layout_marginStart="10dp"
/>
</RelativeLayout>
<!--<RadioButton-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:button="@null"-->
<!--android:visibility="gone"-->
<!--android:layout_gravity="end|bottom"-->
<!--android:onClick="saveLocal"-->
<!--android:layout_marginBottom="10dp"-->
<!--android:layout_marginEnd="10dp"-->
<!--android:drawableStart="@drawable/vector_drawable_down_load"-->
<!--android:layout_marginStart="10dp"-->
<!--/>-->
</FrameLayout>
</RelativeLayout>
SuperFileView2代碼,這個(gè)自定義的類是從https://github.com/ZhongXiaoHong/superFileView導(dǎo)入
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.tencent.smtt.sdk.TbsReaderView;
import java.io.File;
/**
*
* Created by 12457 on 2017/8/29.
*/
public class SuperFileView2 extends FrameLayout {
private static String TAG = "SuperFileView";
private TbsReaderView mTbsReaderView;
private Context context;
public SuperFileView2(Context context) {
this(context, null, 0);
}
public SuperFileView2(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SuperFileView2(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mTbsReaderView = new TbsReaderView(context, new TbsReaderView.ReaderCallback() {
@Override
public void onCallBackAction(Integer integer, Object o, Object o1) {
}
});
this.addView(mTbsReaderView, new LinearLayout.LayoutParams(-1, -1));
this.context = context;
}
private OnGetFilePathListener mOnGetFilePathListener;
public void setOnGetFilePathListener(OnGetFilePathListener mOnGetFilePathListener) {
this.mOnGetFilePathListener = mOnGetFilePathListener;
}
private TbsReaderView getTbsReaderView(Context context) {
return new TbsReaderView(context, new TbsReaderView.ReaderCallback() {
@Override
public void onCallBackAction(Integer integer, Object o, Object o1) {
}
});
}
public void displayFile(File mFile) {
if (mFile != null && !TextUtils.isEmpty(mFile.toString())) {
//增加下面一句解決沒有TbsReaderTemp文件夾存在導(dǎo)致加載文件失敗
String bsReaderTemp = Environment.getExternalStorageDirectory()+ File.separator+"TbsReaderTemp";
File bsReaderTempFile =new File(bsReaderTemp);
if (!bsReaderTempFile.exists()) {
Log.d("xxx","準(zhǔn)備創(chuàng)建/storage/emulated/0/TbsReaderTemp??!");
boolean mkdir = bsReaderTempFile.mkdir();
if(!mkdir){
Log.d("xxx","創(chuàng)建/storage/emulated/0/TbsReaderTemp失?。。。。。?);
}
}
//加載文件
Bundle localBundle = new Bundle();
Log.d("xxx",mFile.toString());
localBundle.putString("filePath", mFile.toString());
localBundle.putString("tempPath", bsReaderTemp);
if (mTbsReaderView == null){
mTbsReaderView = getTbsReaderView(context.getApplicationContext());
String fileType = getFileType(mFile.toString());
boolean bool = mTbsReaderView.preOpen(fileType,false);
if (bool) {
try {
mTbsReaderView.openFile(localBundle);
}catch (Exception e){
e.printStackTrace();
}
}
}else {
String fileType = getFileType(mFile.toString());
boolean bool = mTbsReaderView.preOpen(fileType,false);
if (bool) {
try {
mTbsReaderView.openFile(localBundle);
}catch (Exception e){
e.printStackTrace();
}
}
}
} else {
Log.d("xxx","文件路徑無效!");
}
}
/***
* 獲取文件類型
*
* @param paramString
* @return
*/
private String getFileType(String paramString) {
String str = "";
if (TextUtils.isEmpty(paramString)) {
Log.d(TAG, "paramString---->null");
return str;
}
Log.d(TAG, "paramString:" + paramString);
int i = paramString.lastIndexOf('.');
if (i <= -1) {
Log.d(TAG, "i <= -1");
return str;
}
str = paramString.substring(i + 1);
Log.d(TAG, "paramString.substring(i + 1)------>" + str);
return str;
}
public void show() {
if(mOnGetFilePathListener!=null){
mOnGetFilePathListener.onGetFilePath(this);
}
}
/***
* 將獲取File路徑的工作,“外包”出去
*/
public interface OnGetFilePathListener {
void onGetFilePath(SuperFileView2 mSuperFileView2);
}
public void onStopDisplay() {
if (mTbsReaderView != null) {
mTbsReaderView.onStop();
}
}
}
加載內(nèi)核后打開文件

未加載內(nèi)核打開文件

總結(jié)
以上所述是小編給大家介紹的Android集成騰訊X5實(shí)現(xiàn)文檔瀏覽功能,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
- iOS Crash常規(guī)跟蹤方法及Bugly集成運(yùn)用詳細(xì)介紹
- Android 使用騰訊X5瀏覽器上傳圖片的示例
- Android 通過騰訊TBS實(shí)現(xiàn)文件預(yù)覽功能
- Android基于騰訊云實(shí)時(shí)音視頻仿微信視頻通話最小化懸浮
- Android自定義View仿騰訊TIM下拉刷新View
- Android在項(xiàng)目中接入騰訊TBS瀏覽器WebView的教程與注意的地方
- Android實(shí)現(xiàn)視頻播放--騰訊瀏覽服務(wù)(TBS)功能
- Android開發(fā)騰訊驗(yàn)證碼遇到的坑
- 騰訊、百度、華為、搜狗和滴滴Android面試題匯總
- Android如何快速集成騰訊Bugly
相關(guān)文章
Android面向切面基于AOP實(shí)現(xiàn)登錄攔截的場(chǎng)景示例
這篇文章主要為大家介紹了Android面向切面基于AOP實(shí)現(xiàn)登錄攔截的場(chǎng)景示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
Android開發(fā)之a(chǎn)ctiviti節(jié)點(diǎn)跳轉(zhuǎn)
這篇文章主要介紹了Android開發(fā)之a(chǎn)ctiviti節(jié)點(diǎn)跳轉(zhuǎn)的相關(guān)資料,需要的朋友可以參考下2016-04-04
Android中ListView分頁加載數(shù)據(jù)功能實(shí)現(xiàn)
本篇文章主要介紹了Android中ListView分頁加載數(shù)據(jù)功能實(shí)現(xiàn),具有一定的參考價(jià)值,有需要的可以了解一下。2016-11-11
Kotlin協(xié)程啟動(dòng)createCoroutine及創(chuàng)建startCoroutine原理
這篇文章主要為大家介紹了Kotlin協(xié)程啟動(dòng)createCoroutine及創(chuàng)建startCoroutine原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
Android自定義Button并設(shè)置不同背景圖片的方法
這篇文章主要介紹了Android自定義Button并設(shè)置不同背景圖片的方法,涉及Android自定義控件的功能實(shí)現(xiàn)與布局相關(guān)技巧,需要的朋友可以參考下2016-01-01
Android?性能優(yōu)化實(shí)現(xiàn)全量編譯提速的黑科技
這篇文章主要為大家介紹了Android?性能優(yōu)化實(shí)現(xiàn)全量編譯提速的黑科技,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
Android自定義View圖片按Path運(yùn)動(dòng)和旋轉(zhuǎn)
這篇文章主要為大家詳細(xì)介紹了Android自定義View圖片按Path運(yùn)動(dòng)和旋轉(zhuǎn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01

