一、TBS简介:(TBS官网:https://x5.tencent.com/tbs/index.html)
腾讯浏览服务(TBS,Tencent Browsing Service)整合腾讯底层浏览技术和腾讯平台资源及能力,提供整体浏览服务解决方案。TBS在文件打开方面,目前支持42种文件格式,包括20种文档、12种音乐、6种图片和4种压缩包。帮助应用实现应用内文档浏览,无需跳转调用其他应用。
二、TBS的读取本地pdf、doc等文件的使用
1、下载并导入TBS相关的sdk
2、新建jniLibs\armeabi文件夹,并将 liblbs.so文件导入
3、新建assets文件夹,将需要加载html相关文件放入本地文件夹内
4、在AndroidManifest.xml中添加对应的权限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 硬件加速对X5视频播放非常重要,建议开启 -->
<uses-permission android:name="android.permission.GET_TASKS" />
5、在 build.gradle中的defaultConfig添加支持的ndk
ndk {
abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
}
6、xml中添加页面布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/frame_web_video"></FrameLayout>
<com.tencent.smtt.sdk.WebView
android:layout_width="match_parent"
android:layout_height="200px"
android:id="@+id/web_filechooser">
</com.tencent.smtt.sdk.WebView>
<FrameLayout
android:layout_below="@id/web_filechooser"
android:layout_width="match_parent"
android:layout_height="500px"
android:id="@+id/redFile" >
</FrameLayout>
</RelativeLayout>
注意: webview是用来加载html页面的,并且webview需要使用TBS提供的webview组件
FrameLayout使用来显示读取的文档的位置
7、Activity中具体实现代码
public class DocBrower extends AppCompatActivity {
// @InjectView(R.id.test_webView)
WebView mTestView;
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE" };
private ValueCallback<Uri> uploadFile;
private ValueCallback<Uri[]> uploadFiles;
private FrameLayout mReadFile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_doc_brower);
ButterKnife.inject(this);
verifyStoragePermissions(DocBrower.this);
mTestView=(WebView)findViewById(R.id.web_filechooser);
mReadFile = (FrameLayout) findViewById(R.id.show_doc);
//设置webview相关属性
WebSettings webSetting = mTestView.getSettings();
webSetting.setJavaScriptEnabled(true);
webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
webSetting.setAllowFileAccess(true);
webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
webSetting.setSupportZoom(true);
webSetting.setBuiltInZoomControls(true);
webSetting.setUseWideViewPort(true);
webSetting.setSupportMultipleWindows(true);
webSetting.setAppCacheEnabled(true);
webSetting.setDomStorageEnabled(true);
webSetting.setGeolocationEnabled(true);
webSetting.setAppCacheMaxSize(Long.MAX_VALUE);
webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);
webSetting.setCacheMode(WebSettings.LOAD_NO_CACHE);
//设置html页面监听
mTestView.setWebChromeClient(new WebChromeClient(){
// For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
Log.i("test", "openFileChooser 1");
DocBrower.this.uploadFile = uploadFile;
openFileChooseProcess();
}
// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsgs) {
Log.i("test", "openFileChooser 2");
DocBrower.this.uploadFile = uploadFile;
openFileChooseProcess();
}
// For Android > 4.1.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
Log.i("test", "openFileChooser 3");
DocBrower.this.uploadFile = uploadFile;
openFileChooseProcess();
}
// For Android >= 5.0
public boolean onShowFileChooser(com.tencent.smtt.sdk.WebView webView,
ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams) {
Log.i("test", "openFileChooser 4:" + filePathCallback.toString());
DocBrower.this.uploadFiles = filePathCallback;
openFileChooseProcess();
return true;
}
});
//将html加载到webview上
mTestView.loadUrl("file:///android_asset/webpage/fileChooser.html");
CookieManager.getInstance();
CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().sync();
}
//动态申请文件读写权限
public static void verifyStoragePermissions(Activity activity) {
try {
//检测是否有写的权限
int permission = ActivityCompat.checkSelfPermission(activity,
"android.permission.WRITE_EXTERNAL_STORAGE");
if (permission != PackageManager.PERMISSION_GRANTED) {
// 没有写的权限,去申请写的权限,会弹出对话框
ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//打开本地文件,进行选择
private void openFileChooseProcess() {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
startActivityForResult(Intent.createChooser(i, "test"), 0);
}
//选择完成后的回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case 0:
if (null != uploadFile) {
Uri result = data == null || resultCode != RESULT_OK ? null
: data.getData();
uploadFile.onReceiveValue(result);
uploadFile = null;
Log.e("文件路径:",result+"");
getFileType(getRealPathFromURI(result));
openFile(getRealPathFromURI(result));
}
if (null != uploadFiles) {
Uri result = data == null || resultCode != RESULT_OK ? null
: data.getData();
uploadFiles.onReceiveValue(new Uri[]{result});
uploadFiles = null;
Log.e("文件路径:",result+"");
getFileType(getRealPathFromURI(result));
openFile(getRealPathFromURI(result));
}
break;
default:
break;
}
} else if (resultCode == RESULT_CANCELED) {
if (null != uploadFile) {
uploadFile.onReceiveValue(null);
uploadFile = null;
}
}
}
//uri转成真实路径
private String getRealPathFromURI(Uri contentURI) {
String result;
Cursor cursor = null;
try {
cursor = getContentResolver().query(contentURI, null, null, null, null);
} catch (Throwable e) {
e.printStackTrace();
}
if (cursor == null) {
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
}
//打开doc相关文件的方法
private void openFile(String path) {
//通过bundle把文件传给x5,打开的事情交由x5处理
Bundle bundle = new Bundle();
//传递文件路径
bundle.putString("filePath", path);
//临时的路径
bundle.putString("tempPath", Environment.getExternalStorageDirectory() + File.separator + "temp");
TbsReaderView readerView = new TbsReaderView(this, new TbsReaderView.ReaderCallback() {
@Override
public void onCallBackAction(Integer integer, Object o, Object o1) {
}
});
//加载文件前的初始化工作,加载支持不同格式的插件
boolean b = readerView.preOpen(getFileType(path), false);
if (b) {
readerView.openFile(bundle);
}
// 往容器里添加TbsReaderView控件
mReadFile.addView(readerView);
}
/***
* 获取文件类型
*
* @param path 文件路径
* @return 文件的格式
*/
private String getFileType(String path) {
String str = "";
if (TextUtils.isEmpty(path)) {
return str;
}
int i = path.lastIndexOf('.');
if (i <= -1) {
return str;
}
str = path.substring(i + 1);
return str;
}
/**
* 确保注销配置能够被释放
*/
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
if (this.mTestView != null) {
mTestView.destroy();
}
super.onDestroy();
}
}
注意:WebView 、ValueCallback、TbsReaderView 等组件或方法都需要选择TBS包下
8、在APPAplication中初始化TBS服务
//搜集本地tbs内核信息并上报服务器,服务器返回结果决定使用哪个内核。
QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {
@Override
public void onViewInitFinished(boolean arg0) {
// TODO Auto-generated method stub
//x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
Log.d("app", " onViewInitFinished is " + arg0);
}
@Override
public void onCoreInitFinished() {
// TODO Auto-generated method stub
}
};
//x5内核初始化接口
QbSdk.initX5Environment(getApplicationContext(), cb);
使用TBS实现doc、pdf等多格式文档在线阅读 源码