Android内部没有控件来直接显示文档,跳转WPS或其他第三方文档App体验性不好,使用腾讯X5内核能很好的解决的这一问题。
一、下载腾讯X5内核
1.前往https://x5.tencent.com/下载Android的内核,新版本的腾讯X5可以直接在bulid.gradle集成 api 'com.tencent.tbs.tbssdk:sdk:43697',如果是在App里集成可以把api换成implementation
2.AndroidStudio导入腾讯X5
a.把下载好的jar包导入libs,然后run as,再把jnilibs导入main包下
b. module的build.gradle添加cpu适配
3.Application中腾讯X5初始化,在onCreate()方法调用init方法
1
2
3
4
5
6
7
8
9
10
11
12
13QbSdk.initX5Environment(this, new QbSdk.PreInitCallback() { @Override public void onCoreInitFinished() { } @Override public void onViewInitFinished(boolean b) { Log.e("xxx","hasLoad"+b); //此处将内核加载是否成功的状态保存到本地,SharePreference工具类可换为自己的 SharedPreferenceUtils.saveBoolean(getApplicationContext(),"hasLoad",b); } });
4.应用内调用,无论是否加载内核,都是把在线的文档下载到本地然后打开,不同的是,未加载内核会借助QQ浏览器或其他App的文件浏览功能类似微信(这个调用,腾讯X5已自动处理,我们无需关心),而加载内核后,使用X5的TbsReaderView来打开文件,接下来就是具体代码。
a.bulid.gradle中集成Retrofit,RxJava和进度管理器ProgressManager
1
2
3
4
5
6implementation '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'
写网络下载工具
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public 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.具体调用
首先注册文件进度下载监听
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35private ProgressDialog commonProgressDialog;//切换为自己的进度控件 private ProgressInfo mLastDownloadingInfo; ProgressManager.getInstance().addResponseListener(url, new ProgressListener() { @Override public void onProgress(ProgressInfo progressInfo) { if (mLastDownloadingInfo == null) { mLastDownloadingInfo = progressInfo; } //因为是以请求开始时的时间作为 Id ,所以值越大,说明该请求越新 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()) { //说明已经下载完成 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(); } }); } }); }
然后打开文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89private static final String DOWN_DIR = Environment.getExternalStorageDirectory() + File.separator+"Download"; //文件下载的路径,可以自定义 //打开文件 private void openFile(String filePath,String fileName) { boolean hasLoad = SharedPreferenceUtils.getBoolean(mContext, "hasLoad");//是否记载内核 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,"当前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(); //未加载内核调用方法 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代码,对于一些包名可以切换为自己的包名,还有一些第三方库像进度展示,也可以切换为自己的进度控件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179import 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()) {//网络地址要先下载 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; } /** * 回退上一级菜单 * @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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61<?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代码,这个自定义的类是从https://github.com/ZhongXiaoHong/superFileView导入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127import 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文件夹存在导致加载文件失败 String bsReaderTemp = Environment.getExternalStorageDirectory()+ File.separator+"TbsReaderTemp"; File bsReaderTempFile =new File(bsReaderTemp); if (!bsReaderTempFile.exists()) { Log.d("xxx","准备创建/storage/emulated/0/TbsReaderTemp!!"); boolean mkdir = bsReaderTempFile.mkdir(); if(!mkdir){ Log.d("xxx","创建/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(); } } }
加载内核后打开文件
未加载内核打开文件
总结
以上所述是小编给大家介绍的Android集成腾讯X5实现文档浏览功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对靠谱客网站的支持!如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
最后
以上就是积极发带最近收集整理的关于Android集成腾讯X5实现文档浏览功能的全部内容,更多相关Android集成腾讯X5实现文档浏览功能内容请搜索靠谱客的其他文章。
发表评论 取消回复