1、去官网下载jar包,网址:https://x5.tencent.com/tbs/sdk.html
2、将jar包复制在项目libs下,并右键add libra…,新建JniLibs文件,将事例中的armeabi文件复制进去,如下图:
3、在module的build.gradle添加:
defaultConfig {
......
ndk {
// 声明创建so库的文件名,会自动添加lib前缀, 添加了前缀,不会自动添加
moduleName "MathKit" //声明启用Android日志, 在c/c++的源文件中使用的#include 日志将得到输出
ldLibs "log"
//选择要添加的对应 cpu 类型的 .so 库。
abiFilters 'armeabi', 'armeabi-v7a', 'x86'
}
repositories {
maven {url 'http://repo1.maven.org/maven2' }
}
}
4、在manifest加权限:
5、在项目Application文件里加载x5内核,本地安装qq或微信的可加载成功。
//搜集本地tbs内核信息并上报服务器,服务器返回结果决定使用哪个内核。
QbSdk.initX5Environment(this, new QbSdk.PreInitCallback() {
@Override
public void onCoreInitFinished() {
//x5内核初始化完成回调接口,此接口回调并表示已经加载起来了x5,有可能特殊情况下x5内核加载失败,切换到系统内核。
}
@Override
public void onViewInitFinished(boolean b) {
//x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
Log.e("@@","加载内核是否成功:" + b);//打印出来可排错
initX5 = b;
}
});
6、配置完成后使用:
import com.tencent.smtt.sdk.TbsReaderView;
import java.io.File;
/**
* Created by rjj on 2018/12/14
*/
public class OfficePlayerActivity implements TbsReaderView.ReaderCallback,View.OnClickListener {
private TbsReaderView mTbsReaderView;
private DownloadManager mDownloadManager;
private long mRequestId;
private DownloadObserver mDownloadObserver;
private String mFileUrl = "http://你的文件路径...";
private String mFileName;
private String fimeNameStr="";
private String path="fileTemp";//存储在手机的文件夹名称
//读写权限
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
//请求状态码
private static int REQUEST_PERMISSION_CODE = 1;
private Button mDownloadBtn;
@Override
protected int getLayoutId() {
return R.layout.activity_office_player;
}
@Override
protected void initView() {
mTbsReaderView = new TbsReaderView(this, this);
mDownloadBtn = (Button) findViewById(R.id.btn_download);
RelativeLayout rootRl = (RelativeLayout) findViewById(R.id.rl_root);
rootRl.addView(mTbsReaderView, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
**//动态添加文件的读写权限,6.0以上需要动态添加读写权限**
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_PERMISSION_CODE);
}else{
setData();
}
}else{
setData();
}
}
private void setData() {
mFileName = parseName(mFileUrl);
if (isLocalExist()) {//如果文件存在则打开,不存在则下载
mDownloadBtn.setVisibility(View.GONE);
displayFile();
}else{
startDownload();
}
}
public void onClickDownload(View v) {
if (isLocalExist()) {
mDownloadBtn.setVisibility(View.GONE);
displayFile();
} else {
startDownload();
}
}
@Override
public void onBackPressed() {
finish();//不关掉此界面,之后加载文件会无法加载
}
private void displayFile() {
//增加下面一句解决没有TbsReaderTemp文件夹存在导致加载文件失败
// String bsReaderTemp = "/storage/emulated/0/"+path;
// File bsReaderTempFile = new File(bsReaderTemp);
//
// if (!bsReaderTempFile.exists()) {
// Log.d("TAG", "准备创建/storage/emulated/0/TbsReaderTemp!!");
// boolean mkdir = bsReaderTempFile.mkdir();
// if(!mkdir){
// Log.e("TAG", "创建/storage/emulated/0/TbsReaderTemp失败!!!!!");
// }
// }
String path1 = getLocalFile().getPath() + mFileName;
//显示文件
Bundle bundle = new Bundle();
bundle.putString("filePath", new File(getLocalFile().getPath()).toString());
bundle.putString("tempPath", Environment.getExternalStorageDirectory() + "/" + path);
// bundle.putString("filePath", "/storage/emulated/0/Download/"+path+mFileName);
// bundle.putString("tempPath", Environment.getExternalStorageDirectory()+"/"+bsReaderTemp);
boolean result = mTbsReaderView.preOpen(getFileType(new File(path1).toString()), false);
if (result) {
mTbsReaderView.openFile(bundle);
}
}
private String parseFormat(String fileName) {
return fileName.substring(fileName.lastIndexOf(".") + 1);
}
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;
}
private String getFileType(String paramString) {
String str = "";
if (TextUtils.isEmpty(paramString)) {
return str;
}
int i = paramString.lastIndexOf('.');
if (i <= -1) {
return str;
}
str = paramString.substring(i + 1);
return str;
}
private boolean isLocalExist() {
return getLocalFile().exists();
}
private File getLocalFile() {
return new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS+ "/"+path+"/"), mFileName);
}
private void startDownload() {
mDownloadObserver = new DownloadObserver(new Handler());
getContentResolver().registerContentObserver(Uri.parse("content://downloads/my_downloads"), true, mDownloadObserver);
mDownloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(mFileUrl));
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS+ "/"+path+"/", mFileName);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
mRequestId = mDownloadManager.enqueue(request);
}
private void queryDownloadStatus() {
DownloadManager.Query query = new DownloadManager.Query().setFilterById(mRequestId);
Cursor cursor = null;
try {
cursor = mDownloadManager.query(query);
if (cursor != null && cursor.moveToFirst()) {
//已经下载的字节数
int currentBytes = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
//总需下载的字节数
int totalBytes = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
//状态所在的列索引
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
Log.i("downloadUpdate: ", currentBytes + " " + totalBytes + " " + status);
mDownloadBtn.setText("正在下载:" + currentBytes + "/" + totalBytes);
if (DownloadManager.STATUS_SUCCESSFUL == status && mDownloadBtn.getVisibility() == View.VISIBLE) {
mDownloadBtn.setVisibility(View.GONE);
mDownloadBtn.performClick();
}
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
@Override
public void onCallBackAction(Integer integer, Object o, Object o1) {
}
@Override
protected void onDestroy() {
super.onDestroy();
mTbsReaderView.onStop();
if (mDownloadObserver != null) {
getContentResolver().unregisterContentObserver(mDownloadObserver);
}
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.left_bar_ll:
finish();
break;
}
}
private class DownloadObserver extends ContentObserver {
private DownloadObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
Log.i("downloadUpdate: ", "onChange(boolean selfChange, Uri uri)");
queryDownloadStatus();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION_CODE) {
setData();//执行文件下载或打开方法
for (int i = 0; i < permissions.length; i++) {
Log.i("MainActivity", "申请的权限为:" + permissions[i] + ",申请结果:" + grantResults[i]);
}
}
}
}
7、如果armeabi文件下的.so加载不上(在你的项目里用到多个第三方库时会出现这类问题),可以在project的.gradle里面添加:
// 保证dex_files文件中指定的文件都加载到Main Dex中
afterEvaluate {
tasks.matching {
it.name.startsWith('dex')
}.each { dx ->
if (dx.additionalParameters == null) {
dx.additionalParameters = []
}
dx.additionalParameters += '--multi-dex'
dx.additionalParameters += "--main-dex-list=$projectDir/dex_files".toString()
}
}
8、混淆打包在proguard-rules.pro文件里添加:
# Addidional for x5.sdk classes for apps
-keep class com.tencent.smtt.export.external.**{
*;
}
-keep class com.tencent.tbs.video.interfaces.IUserStateChangedListener {
*;
}
-keep class com.tencent.smtt.sdk.CacheManager {
public *;
}
-keep class com.tencent.smtt.sdk.CookieManager {
public *;
}
-keep class com.tencent.smtt.sdk.WebHistoryItem {
public *;
}
-keep class com.tencent.smtt.sdk.WebViewDatabase {
public *;
}
-keep class com.tencent.smtt.sdk.WebBackForwardList {
public *;
}
-keep public class com.tencent.smtt.sdk.WebView {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.WebView$HitTestResult {
public static final ;
public java.lang.String getExtra();
public int getType();
}
-keep public class com.tencent.smtt.sdk.WebView$WebViewTransport {
public ;
}
-keep public class com.tencent.smtt.sdk.WebView$PictureListener {
public ;
public ;
}
-keepattributes InnerClasses
-keep public enum com.tencent.smtt.sdk.WebSettings$** {
*;
}
-keep public enum com.tencent.smtt.sdk.QbSdk$** {
*;
}
-keep public class com.tencent.smtt.sdk.WebSettings {
public *;
}
-keepattributes Signature
-keep public class com.tencent.smtt.sdk.ValueCallback {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.WebViewClient {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.DownloadListener {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.WebChromeClient {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.WebChromeClient$FileChooserParams {
public ;
public ;
}
-keep class com.tencent.smtt.sdk.SystemWebChromeClient{
public *;
}
# 1. extension interfaces should be apparent
-keep public class com.tencent.smtt.export.external.extension.interfaces.* {
public protected *;
}
# 2. interfaces should be apparent
-keep public class com.tencent.smtt.export.external.interfaces.* {
public protected *;
}
-keep public class com.tencent.smtt.sdk.WebViewCallbackClient {
public protected *;
}
-keep public class com.tencent.smtt.sdk.WebStorage$QuotaUpdater {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.WebIconDatabase {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.WebStorage {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.DownloadListener {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.QbSdk {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.QbSdk$PreInitCallback {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.CookieSyncManager {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.Tbs* {
public ;
public ;
}
-keep public class com.tencent.smtt.utils.LogFileUtils {
public ;
public ;
}
-keep public class com.tencent.smtt.utils.TbsLog {
public ;
public ;
}
-keep public class com.tencent.smtt.utils.TbsLogClient {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.CookieSyncManager {
public ;
public ;
}
# Added for game demos
-keep public class com.tencent.smtt.sdk.TBSGamePlayer {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.TBSGamePlayerClient* {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.TBSGamePlayerClientExtension {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.TBSGamePlayerService* {
public ;
public ;
}
-keep public class com.tencent.smtt.utils.Apn {
public ;
public ;
}
-keep class com.tencent.smtt.** {
*;
}
# end
-keep public class com.tencent.smtt.export.external.extension.proxy.ProxyWebViewClientExtension {
public ;
public ;
}
-keep class MTT.ThirdAppInfoNew {
*;
}
-keep class com.tencent.mtt.MttTraceEvent {
*;
}
# Game related
-keep public class com.tencent.smtt.gamesdk.* {
public protected *;
}
-keep public class com.tencent.smtt.sdk.TBSGameBooter {
public ;
public ;
}
-keep public class com.tencent.smtt.sdk.TBSGameBaseActivity {
public protected *;
}
-keep public class com.tencent.smtt.sdk.TBSGameBaseActivityProxy {
public protected *;
}
-keep public class com.tencent.smtt.gamesdk.internal.TBSGameServiceClient {
public *;
}