日常的项目中,我们偶尔会遇到文件的预览,例如PPT、WORD、EXCEL、TXT、PDF等。

  1. 我们可以使用判断系统中的应用,找到可以打开相应文件的应用。
  2. 还有我最常用的检测系统中是否有WPS office,不存在就提醒用户去下载WPS office,存在就打开。
  3. 马上要说的腾讯提供的TBS浏览服务。

如果仅仅是PDF的预览,github上有作者提供了一个PDF的预览框架。不支持在线预览,需要先将文件从服务器下载保存。==》 android-pdfview,需要的可以去看看。

调用WPS office预览office

如果想使用WPS office进行office文档的预览,可以参考如下两个博客。
1、Android 实现 调用 WPS Office手机版接口
2、Android调用WPS

解决导入第三方包报错,包没找到的问题,在你项目所在的project的build.grale
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.2'

        //解决导入第三方包报错,包没找到的问题
        classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
    }
贴一个检测手机中是否存在某个应用的方法
/**
     * 判断是否安装了某个应用
     * @param context
     * @param appPackageName
     * @return true 安装 false 未安装
     */
    public static boolean isApplicationAvilible(Context context, String appPackageName) {
        // 获取packagemanager
        PackageManager packageManager = context.getPackageManager();
        // 获取所有已安装程序的包信息
        List<PackageInfo> pinfo = packageManager.getInstalledPackages(0);
        if(!pinfo.isEmpty()){
            for (int i = 0; i < pinfo.size(); i++) {
                String name = pinfo.get(i).packageName;
                if(appPackageName.equals(name)){
                    return true;
                }
            }
        }
        /*if (pinfo != null) {
            for (int i = 0; i < pinfo.size(); i++) {
                String pn = pinfo.get(i).packageName;
                if (appPackageName.equals(pn)) {
                    return true;
                }
            }
        }*/
        return false;
    }

不扯皮了,还是讲讲如何使用腾讯的TBS的使用,webview和文件预览
  1. 腾讯TBS官网接入步骤
  2. SDK下载
  3. TBS浏览服务SDK接入问题
1、接入TBS

下载TBS的SDK
这里写图片描述
这里写图片描述
然后在app module中src==》main包下创建jniLibs文件夹,然后将TBS的demo中jniLibs中的文件复制到这个文件夹中。准备工作就做好了。
这里写图片描述

2、然后在APPlication中初始化腾讯的X5内核
public class APPAplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        //x5内核初始化接口
        QbSdk.initX5Environment(getApplicationContext(),  cb);
    }

    /**
     * 搜集本地tbs内核信息并上报服务器,服务器返回结果决定使用哪个内核。
     */
    QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {

        @Override
        public void onViewInitFinished(boolean arg0) {
            //x5內核初始化完成的回调,为true表示x5内核加载成功,否则表示x5内核加载失败,会自动切换到系统内核。
            Log.e("APPAplication", " onViewInitFinished is " + arg0);
        }

        @Override
        public void onCoreInitFinished() {
            Log.e("APPAplication", " onCoreInitFinished");
        }
    };
}
3、然后直接参考demo的写法,使用TBS浏览服务加载网页,比如我们平常遇到的需要加载某些新闻页面或者富文本。

我们在使用腾讯TBS的WebView的情况下,在整个应用中不能出现系统的WebView,好像有冲突。

public class Main3Activity extends AppCompatActivity {

    @BindView(R.id.wb_content)
    X5WebView wbContent;
    @BindView(R.id.progress)
    ProgressBar progress;
    @BindView(R.id.bt_back)
    Button btBack;
    @BindView(R.id.tv_title)
    TextView tvTitle;
    private Unbinder unbinder;
    private String mHomeUrl = "https://www.baidu.com/?tn=39042058_30_oem_dg";
    //private String mHomeUrl = "https://www.panda.tv/";
    //private String mHomeUrl = "https://www.vip.com/";
    private URL mIntentUrl;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setFormat(PixelFormat.TRANSLUCENT);
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                getWindow().setFlags(
                        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Intent intent = getIntent();
        if (intent != null) {
            try {
                mIntentUrl = new URL(intent.getData().toString());
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (NullPointerException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        setContentView(R.layout.activity_main3);
        unbinder = ButterKnife.bind(this);

        initWeb();
        btBack.setOnClickListener(onClickListener);
    }

    private void initWeb() {
        WebSettings webSetting = wbContent.getSettings();
        webSetting.setAllowFileAccess(true);
        webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        webSetting.setSupportZoom(true);
        webSetting.setBuiltInZoomControls(true);
        webSetting.setUseWideViewPort(true);
        webSetting.setSupportMultipleWindows(false);
        // webSetting.setLoadWithOverviewMode(true);
        webSetting.setAppCacheEnabled(true);
        // webSetting.setDatabaseEnabled(true);
        webSetting.setDomStorageEnabled(true);
        webSetting.setJavaScriptEnabled(true);
        webSetting.setGeolocationEnabled(true);
        webSetting.setAppCacheMaxSize(Long.MAX_VALUE);
        webSetting.setAppCachePath(this.getDir("appcache", 0).getPath());
        webSetting.setDatabasePath(this.getDir("databases", 0).getPath());
        webSetting.setGeolocationDatabasePath(this.getDir("geolocation", 0)
                .getPath());
        // webSetting.setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);
        webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);
        // webSetting.setRenderPriority(WebSettings.RenderPriority.HIGH);
        // webSetting.setPreFectch(true);

        wbContent.setWebViewClient(webViewClient);
        wbContent.setWebChromeClient(webChromeClient);

        if (mIntentUrl == null) {
            wbContent.loadUrl(mHomeUrl);
        } else {
            wbContent.loadUrl(mIntentUrl.toString());
        }
        CookieSyncManager.createInstance(this);
        CookieSyncManager.getInstance().sync();
    }

    WebViewClient webViewClient = new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView webView, String url) {
            //此处不能像使用系统的WebView的写法一样,强行显示在WebView中,不调用系统浏览器
            //要参考demo中BrowserActivity中这里的写法,直接返回false,否则会出现网页中某得页面加载不出来的情况,别问我为什么知道,^_^,踩过坑。
            /*if (!TextUtils.isEmpty(url)) {
                webView.loadUrl(url);
            }
            return super.shouldOverrideUrlLoading(webView, url);*/
            return false;
        }

        @Override
        public void onPageFinished(WebView webView, String s) {
            super.onPageFinished(webView, s);
        }
    };

    WebChromeClient webChromeClient = new WebChromeClient() {
        @Override
        public void onProgressChanged(WebView webView, int i) {
            try {
                progress.setProgress(i);
            } catch (Exception e) {
                e.printStackTrace();
            }
            super.onProgressChanged(webView, i);
        }

        @Override
        public void onReceivedTitle(WebView webView, String s) {
            super.onReceivedTitle(webView, s);
            tvTitle.setText(s);
        }

        @Override
        public boolean onJsConfirm(WebView webView, String s, String s1, JsResult jsResult) {
            return super.onJsConfirm(webView, s, s1, jsResult);
        }
    };

    View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.bt_back:
                    if(wbContent != null && wbContent.canGoBack()){
                        wbContent.goBack();
                        return;
                    }
                    finish();
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (intent == null || wbContent == null || intent.getData() == null){
            return;
        }
        finish();
        wbContent.loadUrl(intent.getData().toString());
    }

    @Override
    protected void onDestroy() {
        if (unbinder != null) {
            unbinder.unbind();
        }
        //一定要调用WebView的销毁
        if (null != wbContent) {
            wbContent.destroy();
        }
        super.onDestroy();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        //监听返回键
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
            //判断webView是否还有需要返回的页面
            if(wbContent != null && wbContent.canGoBack()){
                wbContent.goBack();
                return true;
            }else{
                return super.onKeyDown(keyCode, event);
            }
        }
        return super.onKeyDown(keyCode, event);
    }
}
4、进入正题,TBS进行文件的预览,不支持在线预览。如果需要预览服务器上的文件,我们需要先下载保存,然后再调用TBS的浏览服务进行打开。打开文件有两种方式。

我在使用的过程中,还遇到了一个问题,就是在一个Activity中选择一个本地文件进行预览,可以看到文件显示出来,然后不退出当前Activity继续选择一个文件进行浏览,就会一直都在加载中,如果后面遇到了解决方法,告诉楼主一生,不胜感激。

1、 使用TbsReaderView进行文件的预览,我们不能再XML中直接引入这个控件,会报错,查看源码可以看到这个控件没有实现需要的那个构造方法,就是我们只能通过new实例化对象。
//实例化TbsReaderView,然后将它装入我们准备的容器
tbsReaderView = new TbsReaderView(activity,readerCallback);
rlContent.addView(tbsReaderView,new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
//下面的回调必须要实现,暂时没找到此回调的用处
TbsReaderView.ReaderCallback readerCallback = new TbsReaderView.ReaderCallback() {
        @Override
        public void onCallBackAction(Integer integer, Object o, Object o1) {

        }
    };
预览文件的方法
private void openFile(String path) {
        Bundle bundle = new Bundle();
        //文件路径
        bundle.putString("filePath", path);
        //临时文件的路径,必须设置,否则会报错
        bundle.putString("tempPath", Environment.getExternalStorageDirectory().getAbsolutePath()+"腾讯文件TBS");
        //准备
        boolean result = tbsReaderView.preOpen(getFileType(path), false);
        if (result) {
            //预览文件
            tbsReaderView.openFile(bundle);
        }
    }
@Override
    protected void onDestroy() {
        super.onDestroy();
        //需要将预览服务停止,一定不要忘了
        if(tbsReaderView != null){
            tbsReaderView.onStop();
        }
    }
2、使用QbSdk的openFileReader进行文件的预览

使用这个方式预览,我们需要下载的TBS后面标注为(完整+文件)的SDK

下面是腾讯TBS提供的预览文件的文档,可以参考这个写
1public static int openFileReader(Context context, String filePath, HashMap<String, String>
extraParams,ValueCallback<String> callback)
【接口说明】
1、此方法在Qbsdk 类下
2、调用之后,优先调起QQ 浏览器打开文件。如果没有安装QQ 浏览器,在X5 内核下调起简版QB 打开文
件。如果使用的系统内核,则调起文件阅读器弹框。
3、此方法暂时只支持本地文件打开,在线文件后期完善
【参数定义】
context:调起miniqb 的Activity 的context。此参数只能是activity 类型的context,不能设置为Application
的context。
filePath:文件路径。格式为android 本地存储路径格式,例如:/sdcard/Download/xxx.doc. 不支持file:///
格式。暂不支持在线文件。
extraParams:miniqb 的扩展功能。为非必填项,可传入null 使用默认设置。
其格式是一个key 对应一个value。在文件查看器的产品形态中,当前支持的key 包括:
local: “true”表示是进入文件查看器,如果不设置或设置为“false”,则进入miniqb 浏览器模式。不是必
须设置项。
style: “0”表示文件查看器使用默认的UI 样式。“1”表示文件查看器使用微信的UI 样式。不设置此key
或设置错误值,则为默认UI 样式。
topBarBgColor: 定制文件查看器的顶部栏背景色。格式为“#xxxxxx”,例“#2CFC47”;不设置此key 或设置
错误值,则为默认UI 样式。
menuData: 该参数用来定制文件右上角弹出菜单,可传入菜单项的icon 的文本,用户点击菜单项后,sdk
会通过startActivity+intent 的方式回调。menuData 是jsonObject 类型,结构格式如下:
public static final String jsondata =
"{
pkgName:\"com.example.thirdfile\", "
+ "className:\"com.example.thirdfile.IntentActivity\","
+ "thirdCtx: {pp:123},"
+ "menuItems:"
+ "["
+ "{id:0,iconResId:"+ R.drawable.ic_launcher +",text:\"menu0\"},
{id:1,iconResId:" + R.drawable.bookmark_edit_icon + ",text:\"menu1\"},
{id:2,iconResId:"+ R.drawable.bookmark_folder_icon +",text:\"菜单2\"}"
+ "]"
+ "
}";
pkgName 和className 是回调时的包名和类名。
thirdCtx 是三方参数,需要是jsonObject 类型,sdk 不会处理该参数,只是在菜单点击事件发生的时候原样
回传给调用方。
menuItems 是json 数组,表示菜单中的每一项。
ValueCallback:提供miniqb 打开/关闭时给调用方回调通知,以便应用层做相应处理。
在单独进程打开文件的场景中,回调参数出现如下字符时,表示可以关闭当前进程,避免内存占用。
openFileReader open in QB
filepath error
TbsReaderDialogClosed
default browser:
filepath error
fileReaderClosed
【返回说明】
1:用QQ 浏览器打开
2:用MiniQB 打开
3:调起阅读器弹框
-1:filePath 为空打开失败
【使用实例】
//params 为定制参数非必须选项可以传null 为默认设置
public static final Stringjsondata = "{
pkgName:\"com.example.thirdfile\", "
+ "className:\"com.example.thirdfile.IntentActivity\","
+ "thirdCtx: {pp:123},"
+ "menuItems:"
+ "["
+ "{id:0,iconResId:"+ R.drawable.ic_launcher +",text:\"menu0\"},
{id:1,iconResId:" + R.drawable.bookmark_edit_icon + ",text:\"menu1\"},
{id:2,iconResId:"+ R.drawable.bookmark_folder_icon +",text:\"菜单2\"}"
+ "]"
+ " }";
HashMap<String, String> params = new HashMap<String, String>();
params.put("style", "1");
params.put("local", "true");
params.put("memuData", jsondata);
QbSdk.openFileReader(ctx,”/sdcard/xxx.doc”, params,callback);
参考上面腾讯提供的预览文档书写预览方法
private void openOtherFile(String path) {
        /*QbSdk.canOpenFile(activity, path, new ValueCallback<Boolean>() {
            @Override
            public void onReceiveValue(Boolean aBoolean) {
                Log.e(TAG,"文件是否能够打开:"+aBoolean);
            }
        });*/
        HashMap<String,String> params = new HashMap<>();
        //“0”表示文件查看器使用默认的UI 样式。“1”表示文件查看器使用微信的UI 样式。不设置此key或设置错误值,则为默认UI 样式。
        params.put("style","1");
        //“true”表示是进入文件查看器,如果不设置或设置为“false”,则进入miniqb 浏览器模式。不是必须设置项
        params.put("local","true");
        //定制文件查看器的顶部栏背景色。格式为“#xxxxxx”,例“#2CFC47”;不设置此key 或设置错误值,则为默认UI 样式。
        params.put("topBarBgColor","#ff8b3d");
        QbSdk.openFileReader(activity, path, params, new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String s) {

            }
        });
    }
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐