使用TBS實現doc、pdf等多格式文檔在線閱讀

一、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等多格式文檔在線閱讀 源碼 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章