android项目接入Tbs-实现项目内部打开office在线文档并解决.so文件加载不上的问题

1、去官网下载jar包,网址:https://x5.tencent.com/tbs/sdk.html

2、将jar包复制在项目libs下,并右键add libra…,新建JniLibs文件,将事例中的armeabi文件复制进去,如下图:

android项目接入Tbs-实现项目内部打开office在线文档并解决.so文件加载不上的问题_第1张图片

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 *;
}

你可能感兴趣的:(android项目接入Tbs-实现项目内部打开office在线文档并解决.so文件加载不上的问题)