TBS使用X5内核下载遇到的问题

471 阅读3分钟

tbs最新的jar包

Application内进行初始化

        //X5内核下载
//        if (!(SPUtil[App.CONTEXT, WordReadHelper.TBS_INIT_KEY, false] as Boolean)){
//            WordReadHelper.init(App.CONTEXT)
//        }else{
//            Logger.d("WordReadHelper x5内核加载成功")
//        }

WordReadHelper类

class WordReadHelper private constructor() {
    fun setOnlyWifiDownload(onlyWifi: Boolean) {
        mOnlyWifi = onlyWifi
    }

    class ConnectReceiver : NetworkCallback() {
        override fun onAvailable(network: Network) {
            super.onAvailable(network)
            initFinish()
            Log.d(TAG, "onAvailable: 网络已连接")
        }

        override fun onLost(network: Network) {
            super.onLost(network)
            Log.d(TAG, "onLost: 网络已断开")
        }
    }

    companion object {
        const val TAG = "WordReadHelper"
        private var mOnlyWifi = true
        private var mInit = false
        private var mContext: Context? = null
        private var mConnectionReceiver: ConnectReceiver? = null

        //因此我们在sp里面做记录,看是否需要等待加载
        //如果上次加载好了,那这次肯定也很快,可以等待
        //如果上次没加载好,那还是提示用户过一会再用吧
        const val TBS_INIT_KEY = "tbs_init_key"

        fun init(context: Context?) {
            if (context == null) {
                throw NullPointerException("init fail")
            }
            mContext = context
            QbSdk.reset(mContext)
            resetSdk(context)
            QbSdk.setTbsListener(object : TbsListener {
                override fun onDownloadFinish(i: Int) {
                    //成功时i为100
//                    if (i != 100) {
//                        //此处存在一种情况,第一次启动app,init不会自动回调,
//                        // 此处额外加一层,判断网络监听器是否为空并作出处理
//                        if (mConnectionReceiver == null) initNetWorkCallBack() else {
//                            initFinish()
//                        }
//                    }
                    Log.d(TAG, "load $i")
                }

                override fun onInstallFinish(i: Int) {
                    mInit = true
//                    if (mConnectionReceiver != null) {
//                        val connMgr =
//                            context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
//                        connMgr.unregisterNetworkCallback(mConnectionReceiver!!)
//                    }
                    Log.d(TAG, "finish $i")
                }

                override fun onDownloadProgress(i: Int) {
                    //下载进度监听
                    Log.d(TAG, "progress $i")
                }
            })
            QbSdk.initX5Environment(context, object : PreInitCallback {
                override fun onCoreInitFinished() {
                    Log.e(TAG, "加载内核完成")
                    // 内核初始化完成,可能为系统内核,也可能为系统内核
                }

                /**
                 * 预初始化结束
                 * 由于X5内核体积较大,需要依赖wifi网络下发,所以当内核不存在的时候,默认会回调false,此时将会使用系统内核代替
                 * 内核下发请求发起有24小时间隔,卸载重装、调整系统时间24小时后都可重置
                 * 调试阶段建议通过 WebView 访问 debugtbs.qq.com -> 安装线上内核 解决
                 * @param isX5 是否使用X5内核
                 */
                override fun onViewInitFinished(b: Boolean) {
                    mInit = b
                    Log.e(TAG, "加载内核是否成功:$b")
                    SPUtil.put(App.CONTEXT,TBS_INIT_KEY, b)
                }
            })
        }

        private fun resetSdk(context: Context?) {
            // 在调用TBS初始化、创建WebView之前进行如下配置
            val map: HashMap<String, Any> = HashMap()
            map[TbsCoreSettings.TBS_SETTINGS_USE_SPEEDY_CLASSLOADER] = true
            map[TbsCoreSettings.TBS_SETTINGS_USE_DEXLOADER_SERVICE] = true
            QbSdk.initTbsSettings(map)
            QbSdk.setDownloadWithoutWifi(!mOnlyWifi)
            QbSdk.setCoreMinVersion(QbSdk.CORE_VER_ENABLE_202112)
            QbSdk.disableAutoCreateX5Webview()
            //强制使用系统内核
            //QbSdk.forceSysWebView();
        }

        //该方法是用来判断tbs是否加载完成的,供外部调用
        fun initFinish(): Boolean {
            //上次没加载完,那就根据状态判断是否重置
            if (!mInit && !TbsDownloader.isDownloading()) {
                QbSdk.reset(mContext)
                resetSdk(mContext)
                if (!mOnlyWifi || isWifi(mContext)) TbsDownloader.startDownload(mContext)
            }
            return mInit
        }

        private fun isWifi(mContext: Context?): Boolean {
            val connectivityManager = mContext?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            val info = connectivityManager.activeNetworkInfo
            return (info != null
                    && info.type == ConnectivityManager.TYPE_WIFI)
        }

        fun initNetWorkCallBack() {
            if (mConnectionReceiver == null) {
                mConnectionReceiver = ConnectReceiver()
                val builder = NetworkRequest.Builder()
                val request = builder.build()
                val connMgr =
                    mContext!!.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
                connMgr.registerNetworkCallback(request, mConnectionReceiver!!)
            }
        }
    }
}

ShowOnlinePdfActivity

package com.ahsl.health.ui.shop.invoice

import android.os.Bundle
import android.os.Environment
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import com.ahsl.health.R
import com.ahsl.health.app.BaseVMActivity
import com.ahsl.health.app.BaseViewModel
import com.ahsl.sdkkit.umeng.Platform
import com.ahsl.sdkkit.umeng.UmengClient
import com.ahsl.sdkkit.umeng.UmengShare
import com.hjq.bar.OnTitleBarListener
import com.orhanobut.logger.Logger
import com.tencent.smtt.sdk.TbsReaderView
import com.umeng.socialize.ShareAction
import com.umeng.socialize.media.UMWeb
import kotlinx.android.synthetic.main.activity_show_online_pdf.*
import java.io.File

/**
 * 展示在线pdf的界面
 */
class ShowOnlinePdfActivity : BaseVMActivity<BaseViewModel>(), TbsReaderView.ReaderCallback,
    UmengShare.OnShareListener {

    private var tbsReaderView: TbsReaderView? = null
    private var pdfUrl: String = ""
    private var pdfName: String = ""

    companion object {
        const val ShowOnlinePdf_Url: String = "ShowOnlinePdf_Url"
        const val ShowOnlinePdf_Name: String = "ShowOnlinePdf_Name"
    }

    override fun getLayoutResId(): Int = R.layout.activity_show_online_pdf

    override fun initView() {
        tb_invoice_review.setOnTitleBarListener(object : OnTitleBarListener {
            override fun onLeftClick(view: View?) {
                finish()
            }

            override fun onTitleClick(view: View?) {

            }

            override fun onRightClick(view: View?) {
                val web = UMWeb(pdfUrl)
                web.title = "发票预览"
                web.description = "点击查看发票"
                UmengClient.share(this@ShowOnlinePdfActivity, Platform.WECHAT,
                    ShareAction(this@ShowOnlinePdfActivity)
                        .withMedia(web),
                    this@ShowOnlinePdfActivity)
            }

        })
    }

    override fun initData() {

        show_online_pdf_ll?.visibility = View.VISIBLE
        pdfView?.visibility = View.GONE

        pdfUrl = intent.getStringExtra(ShowOnlinePdf_Url).orEmpty()
        pdfName = intent.getStringExtra(ShowOnlinePdf_Name).orEmpty()
        Logger.d("luxiang pdfUrl = $pdfUrl")
        Logger.d("luxiang pdfName = $pdfName")

        try {

            tbsReaderView = TbsReaderView(this, this)

            tbsReaderView?.apply {
                show_online_pdf_ll?.addView(
                    this, LinearLayout.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT
                    )
                )
            }

            showDialog(null)


            LoadPDFAsyncTask(pdfName, object : LoadPDFAsyncTask.OnLoadPDFListener {
                override fun onProgressListener(curPro: Int?, maxPro: Int?) {

                }

                override fun onFailureListener() {

                    hideDialog()
                    toast("文件加载失败")
                }

                override fun onCompleteListener(file: File?) {
                    Logger.d("luxiang file ${file?.path} ")

                    hideDialog()

                    try {
                        val bundle = Bundle()

                        bundle.putString("filePath", file?.path)
                        //存放临时文件的目录。运行后,会在 Environment.getExternalStorageDirectory().getPath() 的目录下生成.tbs...的文件
                        bundle.putString(
                            "tempPath",
                            Environment.getExternalStorageDirectory().path
                        )

                        val result = tbsReaderView!!.preOpen("pdf", false)

                        Logger.d("luxiang result $result ")

                        if (result) {
                            //X5内核正常,可以直接展示PDF文件

                            tbsReaderView!!.openFile(bundle)
                        } else {
                            //这是备选方案,兼容X5内核加载失败,无法展示PDF文件的情况

                            show_online_pdf_ll?.visibility = View.GONE
                            pdfView?.visibility = View.VISIBLE

                            pdfView.fromFile(file)
                                .defaultPage(0)
                                .enableAnnotationRendering(true)
                                .spacing(0) // in dp
                                .load()

                        }


                    } catch (e: Exception) {
                        e.printStackTrace()
                        hideDialog()
                        toast("文件加载失败")
                        Logger.d("加载在线PDF e = $e")
                    }

                }

            }).execute(pdfUrl)

        } catch (e: Exception) {
            e.printStackTrace()
            hideDialog()
        }
    }

    override fun initVM(): BaseViewModel = BaseViewModel()

    override fun startObserve() {

    }

    override fun onCallBackAction(p0: Int?, p1: Any?, p2: Any?) {

    }

    override fun onDestroy() {
        super.onDestroy()
        //很重要
        if (tbsReaderView != null) {
            tbsReaderView?.onStop()
            tbsReaderView = null
        }

    }

    override fun onSucceed(platform: Platform?) {

    }
}

LoadPDFAsyncTask

package com.ahsl.health.ui.shop.invoice;


import android.os.AsyncTask;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import com.ahsl.health.app.App;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.logging.Logger;

public class LoadPDFAsyncTask extends AsyncTask<String, Integer, File> {
    private OnLoadPDFListener onLoadPDFListener;
    private String filePath = "pdf";
    private String fileName;

    public LoadPDFAsyncTask(String fileName) {
        this.fileName = fileName;
    }

    public LoadPDFAsyncTask(String fileName, OnLoadPDFListener onLoadPDFListener) {
        this.fileName = fileName;
        this.onLoadPDFListener = onLoadPDFListener;
    }

    public void setOnLoadPDFListener(OnLoadPDFListener onLoadPDFListener) {
        this.onLoadPDFListener = onLoadPDFListener;
    }

    //这里是开始线程之前执行的,是在UI线程
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    //当任务被取消时回调
    @Override
    protected void onCancelled() {
        super.onCancelled();
        if (onLoadPDFListener != null) onLoadPDFListener.onFailureListener();
    }

    //当任务被取消时回调
    @Override
    protected void onCancelled(File file) {
        super.onCancelled(file);
    }

    //子线程中执行
    @Override
    protected File doInBackground(String... strings) {
        String httpUrl = strings[0];
        if (TextUtils.isEmpty(httpUrl)) {
            if (onLoadPDFListener != null) onLoadPDFListener.onFailureListener();
        }
        filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "pdf";
        File pathFile = new File(filePath);
        if (!pathFile.exists()) {
            if (pathFile.mkdirs()){
                System.out.println("create success");
            }else {
                System.out.println("create fail");
            }
        }

        File pdfFile = new File(filePath + File.separator + fileName);
        if (pdfFile.exists()) {
            return pdfFile;
        }
        try {
            URL url = new URL(httpUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.connect();
            int count = conn.getContentLength(); //文件总大小 字节
            int curCount = 0; // 累计下载大小 字节
            int curRead = -1;// 每次读取大小 字节
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                InputStream is = conn.getInputStream();
                FileOutputStream fos = new FileOutputStream(pdfFile);
                byte[] buf = new byte[1024];
                while ((curRead = is.read(buf)) != -1) {
                    curCount += curRead;
                    fos.write(buf, 0, curRead);
                    publishProgress(curCount, count);
                }

                fos.close();
                is.close();
                conn.disconnect();
            }

        } catch (Exception e) {
            e.printStackTrace();
            if (onLoadPDFListener != null) onLoadPDFListener.onFailureListener();
            return null;
        }

        return pdfFile;
    }

    //更新进度
    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        if (onLoadPDFListener != null) {
            onLoadPDFListener.onProgressListener(values[0], values[1]);
        }
    }

    //当任务执行完成是调用,在UI线程
    @Override
    protected void onPostExecute(File file) {
        super.onPostExecute(file);
        if (onLoadPDFListener != null) {
            if (file != null && file.exists()) {
                onLoadPDFListener.onCompleteListener(file);
            } else {
                onLoadPDFListener.onFailureListener();
            }
        }

    }


    //下载PDF文件时的回调接口
    public interface OnLoadPDFListener {
        //下载完成
        void onCompleteListener(File file);

        //下载失败
        void onFailureListener();

        //下载进度 字节
        void onProgressListener(Integer curPro, Integer maxPro);
    }

}