SDK 介绍
腾讯浏览服务已支持以下基础文档格式的本地打开,接入 SDK 可支持打开文档格式:doc、docx、rtf、ppt、pptx、xls、xlsx、xlsm、csv、pdf、txt、epub、dwg、chm。
其他兼容了 office 格式、遵循 office 标准的文件,可以先把文件后缀名转成以上基础格式,再调用 SDK 打开。
SDK 接入说明
隐私政策
请开发者及终端用户认真阅读上述规则。如您是开发者,请您确认充分了解并同意本规则后再集成 SDK 产品,如果您不同意上述规则及按照本规则履行对应的用户个人信息保护义务,应立即停止接入及使用 SDK 产品。
为了保证腾讯浏览服务 SDK 的正常使用,SDK 需要在
AndroidManifest.xml
声明了如下权限:权限类型 | 权限使用说明 |
android.permission.INTERNET | 文档能力使用前的授权鉴权功能 (私有化版本忽略此项) |
| android.permission.ACCESS_NETWORK_STATE |
在 SDK 的功能使用期间,SDK 需要获取以下信息数据以支持 SDK 基础功能的正常运行。
信息类型 | 目的 | 时机 | 处理方式 |
获取设备信息(操作系统版本、CPU 类型、屏幕宽高、屏幕方向、屏幕像素) | 加载文档引擎必要参数 | SDK 初始化获取 | 内存内使用,退出程序即销毁 |
应用信息(宿主应用包名,版本号) | 加载文档引擎必要参数 | SDK 初始化获取 | 通过标识化、加密传输和处理的安全处理方式 |
为实现 SDK 的基础功能,SDK 打开文档可能涉及使用到以下权限,但 SDK 不会主动申请权限,也不会判断应用是否有权限,在需要使用功能的同时,宿主根据业务的判断自己决定是否授予,权限的控制由宿主自主决定。下表列举了各个权限使用涉及的功能及影响。
操作系统 | 权限名称 | 使用目的 | 需要权限的时机 | 不授权影响 |
Android | 存储权限 | 文档引擎运行必要异常日志需要读写文件 | SDK 初始化时使用 | 不影响打开文档功能,影响文档日志读写,用户体验问题定位。 |
| 剪切板权限 | 支持文档中文本复制到剪切板中 | 打开文档用户操作长按菜单选中文本复制功能时获取。 | 不影响打开文档功能,影响文档内文本复制粘贴功能的用户体验。 |
| 网络权限 | 文档能力使用前的授权鉴权功能 | SDK 初始化时使用 | 影响是否能够打开文档(私有化版本忽略此项) |
注意:
请务必确保用户同意隐私政策后,再调用 SDK iniEngine 接口进行初始化。
混淆配置
为了功能的正常使用,需要在 proguard-rules.pro 文件中添加如下配置:
-dontwarn com.tencent.tbs.reader.**-keep class com.tencent.tbs.reader.** {*;}
SDK 接入方式
implementation 'TbsFileSdk.aar'
接口介绍
腾讯浏览服务 SDK 不使用 TbsReaderView,统一使用 TbsFileInterfaceImpl 下的接口:
LicenseKey 初始化接口
功能介绍:设置客户端绑定的 LicenseKey。
场景描述:用户同意隐私政策后,首先调用该接口设置 LicenseKey,才能初始化 SDK。
public static void setLicenseKey(String licenseStr)
SDK 初始化接口
功能介绍:初始化文件 SDK。
场景描述:该方法仅需调用一次,只有成功初始化 SDK 才能调用打开文档的其他接口。
public static int initEngine(Context appContext)public static void initEngineAsync(Context appContext, final ITbsReaderCallback callBackListener)
initEngineAsync 相关回调值:
actionType | args | result | 描述 |
OPEN_FILEREADER_ASYNC_LOAD_READER_ENTRY_CALLBACK | 0:加载 SDK 成功 非0:加载 SDK 失败 | / | 异步加载 SDK |
格式判断接口
功能介绍:判断该文件的格式是否是腾讯浏览服务 SDK 支持打开的文件格式。
场景描述:在打开文件前调用。
/*** @param fileExt 文件后缀名,如文件名为test.pdf,则只需要传入"pdf"* @return boolean*/public static boolean canOpenFileExt(String fileExt)
打开文档接口
功能介绍:打开本地文档。
public int openFileReader(Context cx, Bundle param, ITbsReaderCallback callback, FrameLayout layout)
参数配置:
layout:
传入 null 则使用默认的 dialog 方式,使用默认标题栏和右上角菜单。
传入一个自定义的 layout,则没有标题栏,layout 内只显示文档内容,宿主可以自己实现标题栏及其功能(和 TbsReaderView 方式相同)。
param:
必要参数
参数名称 | 值 | 描述 |
filePath | String | 本地文件路径,SDK 只支持打开一个本地文档,服务器文档需要先下载到本地再调 SDK 打开 |
fileExt | String | 文件后缀名,例如文件名为 test.pdf,则只需要传入"pdf" |
tempPath | String | 文件临时目录路径(文件打开过程中缓存目录,包括记录上次文档打开位置等,打开文档结束后不会自动删除,如有需要可自行删除,建议指定在沙盒目录下) |
可选参数
参数名称 | 值 | 描述 |
file_reader_enable_long_press_menu | boolean | 开启长按菜单复制功能、支持 PDF、DOCX、XLSX 和 TXT |
file_reader_is_ppt_page_mode_default | boolean | 设置 PPT 打开为翻页模式 |
默认 dialog 模式特定参数
默认 dialog 模式提供一些自定义标题栏和右上角菜单的参数:
参数名称 | 值 | 描述 |
file_reader_top_bar_bg_color | String:#ffffff | 设置顶 bar 的颜色 |
file_reader_top_bar_hight | Int | 设置顶 bar 的高度 |
自定义 layout 方式特定参数(老 SDK 的 TbsReaderView 方式)
非默认 dialog 模式不提供自定义参数,如果宿主实现了固定高度的标题栏,需要传入额外的参数设置文档内容显示区域的高度(例如屏幕高度-标题栏高度):
参数名称 | 值 | 描述 |
set_content_view_height | int | 设置文档内容的高度(默认为整个屏幕高度) |
openFileReader 相关回调值:
actionType | args | result | 描述 |
OPEN_FILEREADER_STATUS_UI_CALLBACK | 打开文件: Bundle[{typeId=0, typeDes=fileReaderOpened}] 关闭文件: Bundle[{typeId=1, typeDes=fileReaderClosed}] | / | 文件打开关闭事件 |
READER_PLUGIN_SO_ERR | / | / | 文档引擎加载失败 |
READER_PLUGIN_SO_SUCCESS | / | / | 文档引擎加载成功 |
NOTIFY_CANDISPLAY | / | / | 文档引擎渲染成功,即将显示文档 |
NOTIFY_ERRORCODE | / | 0 :文档引擎渲染成功 | 文档引擎渲染错误码 |
READER_EVENT_CLICK | / | / | 单击事件 |
READER_EVENT_SCROLL_BEGIN | / | / | 滑动开始事件 |
READER_EVENT_SCROLL_END | / | / | 滑动结束事件 |
READER_EVENT_SCALE_BEGIN | / | / | 缩放开始事件 |
READER_EVENT_SCALE_END | / | / | 缩放结束事件 |
READER_PAGE_TOAST | Bundle[{cur_page=当前页码, page_count=总页码}] | / | 获取当前页码和总页码 |
关闭文档接口
功能介绍:关闭文档,释放相关资源。
public void closeFileReader()
页面跳转接口
功能介绍:支持 PDF、DOCX、PPTX 跳转到指定页面。
public void gotoPosition(Bundle b)
使用示例:
滑动模式(默认模式):
Bundle b = new Bundle();b.putInt("progress", 3); // 跳转到第4页TbsFileInterfaceImpl.getInstance().gotoPosition(b);
翻页模式(仅 PPT/PPTX 支持):
Bundle b = new Bundle();b.putInt("page", 3); // 跳转到第4页TbsFileInterfaceImpl.getInstance().gotoPosition(b);
其他功能
横屏
在
AndroidManifest.xml
设置打开文件的 activity 属性:android:configChanges="orientation|keyboardHidden|navigation|screenSize"
自定义 layout 方式需要主动调用接口适配横屏,默认 dialog 模式无需调用该接口:
/*** @param width layout宽度* @param height layout高度*/public void onSizeChanged(int width, int height)
长按菜单
腾讯浏览服务文档引擎(PDF、DOCX、XLSX、TXT)支持长按复制文本功能 ,见打开文档接口可选参数。
PPT 翻页模式
参考打开文档接口可选参数,设置 PPT 打开为翻页模式(默认是滑动模式);参考页面跳转接口设置 PPT 翻页模式页面跳转。
接入示例
腾讯浏览服务 SDK 不使用 TbsReaderView,统一使用 TbsFileInterfaceImpl 下的接口,提供以下两种接入方式:
默认 Dialog 方式
openFileReader 接口 layout 传入 null。
//设置回调ITbsReaderCallback callback = new ITbsReaderCallback() {@Overridepublic void onCallBackAction(Integer actionType, Object args, Object result) {Log.i(TAG, "actionType=" + actionType + ",args=" + args + ",result=" + result);if (ITbsReader.OPEN_FILEREADER_STATUS_UI_CALLBACK == actionType) {if (args instanceof Bundle) {int id = ((Bundle) args).getInt("typeId");if (ITbsReader.TBS_READER_TYPE_STATUS_UI_SHUTDOWN == id) {TbsFileInterfaceImpl.getInstance().closeFileReader(); //关闭fileReader}}}}};//设置licenseKeyTbsFileInterfaceImpl.setLicenseKey("your licenseKey");int ret = -1;//初始化Engineif (!TbsFileInterfaceImpl.isEngineLoaded()) {ret = TbsFileInterfaceImpl.initEngine(this);}if(ret != 0) {Log.i(TAG, "initEngine失败, 无法调用其他接口,ret = " + ret);return;}//点击打开文档findViewById(R.id.btn_dialog).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {ret = openFileReader(fileName);}});private int openFileReader(String fileName) {//设置参数Bundle param = new Bundle();param.putString("filePath", filePath); //文件路径param.putString("fileExt", extName); // 文件后缀名,如文件名为test.pdf,则只需要传入"pdf"param.putString("tempPath", getExternalFilesDir("temp").getAbsolutePath());//调用openFileReader打开文档if (TbsFileInterfaceImpl.canOpenFileExt(extName)) { //tbs支持的文档类型int ret = TbsFileInterfaceImpl.getInstance().openFileReader(this, param, callback, null);if (ret != 0) {Log.i(TAG, "openFileReader失败, ret = " + ret);}} else {//tbs不支持的文档类型//...}}
自定义 Layout 方式
openFileReader 接口传入一个 layout。
public class MainActivity extends AppCompatActivity {private final String TAG = "FileSdkDemo";private static boolean isInit = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initUI();//设置licenseKeyTbsFileInterfaceImpl.setLicenseKey("your licenseKey");//初始化Engineint ret = -1;if (!TbsFileInterfaceImpl.isEngineLoaded()) {ret = TbsFileInterfaceImpl.initEngine(MainActivity.this);}if(ret != 0) {Toast.makeText(getApplicationContext(), "初始化Engine失败 ret = " + ret, Toast.LENGTH_SHORT).show();} else {Toast.makeText(getApplicationContext(), "初始化Engine成功", Toast.LENGTH_SHORT).show();isInit = true;}}private void initUI() {findViewById(R.id.exit).setOnClickListener(v->finish());findViewById(R.id.btn_open_doc_reader).setOnClickListener(view -> openExternalFilesDirDocument(filePath,extName));}private void openExternalFilesDirDocument(String filePath, String extName) {if(isInit) {if(TbsFileInterfaceImpl.canOpenFileExt(fileExt)) {PreviewActivity.start(this, filePath, extName);} else {// tbs不支持打开的类型}} else {Toast.makeText(getApplicationContext(), "Engine未初始化成功,无法打开文件", Toast.LENGTH_SHORT).show();}}
public class PreviewActivity extends AppCompatActivity {private FrameLayout mFlRoot; //内容显示区域private RelativeLayout mRl; //自定义标题栏private boolean isDestroyed = false;public static void start(Context context, String filePath,String fileExt) {context = context.getApplicationContext();Intent starter = new Intent(context, PreviewActivity.class);starter.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);starter.putExtra("filePath", filePath);starter.putExtra("fileExt", fileExt);context.startActivity(starter);}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_preview);String filePath = getIntent().getStringExtra("filePath");String fileExt = getIntent().getStringExtra("fileExt");initView();openFile(filePath, fileExt);}private void initView() {mFlRoot = findViewById(R.id.content);mRl = findViewById(R.id.reader_top);}private void openFile(String filePath, String fileExt) {//设置回调ITbsReaderCallback callback = new ITbsReaderCallback() {@Overridepublic void onCallBackAction(Integer actionType, Object args, Object result) {Log.i(TAG, "actionType=" + actionType + ",args=" + args + ",result=" + result);if (args instanceof Bundle) {int id = ((Bundle) args).getInt("typeId");if (ITbsReader.TBS_READER_TYPE_STATUS_UI_SHUTDOWN == id) {finish(); // 加密文档弹框取消需关闭activity}}}};//设置参数Bundle param = new Bundle();param.putString("filePath", filePath);param.putString("fileExt", fileExt); // 文件后缀名,如文件名为test.pdf,则只需要传入"pdf"param.putString("tempPath", getExternalFilesDir("temp").getAbsolutePath());//调用openFileReader打开文件mFlRoot.post(new Runnable() {@Overridepublic void run() {int height = mFlRoot.getHeight();param.putInt("set_content_view_height", height); // 文档内容的显示区域高度,自定义layout模式必须传入这个值int ret = TbsFileInterfaceImpl.getInstance().openFileReader(PreviewActivity.this, param, callback, mFlRoot);}});}// 销毁资源使用onpause + ondestroy的方式。避免onDestroy延迟回调private void destroy() {if (isDestroyed) {return;}// 回收资源mFlRoot.removeAllViews(); //移除内容显示区域layoutTbsFileInterfaceImpl.getInstance().closeFileReader(); //关闭fileReaderisDestroyed = true;}@Overrideprotected void onPause() {super.onPause();if (isFinishing()) {destroy();}}@Overridepublic void onDestroy() {super.onDestroy();destroy();}//横屏切换@Overridepublic void onConfigurationChanged(@NonNull Configuration newConfig) {super.onConfigurationChanged(newConfig);DisplayMetrics dm = new DisplayMetrics();((Activity)this).getWindowManager().getDefaultDisplay().getMetrics(dm);int w = dm.widthPixels;int h = dm.heightPixels - mRl.getHeight();TbsFileInterfaceImpl.getInstance().onSizeChanged(w, h);}}
异步初始化
ITbsReaderCallback callback = new ITbsReaderCallback() {@Overridepublic void onCallBackAction(Integer actionType, Object args, Object result) {Log.i(TAG, "actionType=" + actionType + ",args=" + args + ",result=" + result);// ITbsReader.OPEN_FILEREADER_ASYNC_LOAD_READER_ENTRY_CALLBACK 的值为 7002,不是错误码if (ITbsReader.OPEN_FILEREADER_ASYNC_LOAD_READER_ENTRY_CALLBACK == actionType) {int ret = (int)args; // 错误码为actionType == 7002时 args的值if (ret == 0) {// 初始化成功} else {// 初始化失败}}}};if (!TbsFileInterfaceImpl.isEngineLoaded()) {TbsFileInterfaceImpl.initEngineAsync(this, callback);}