Android之WebView加载PDF链接预览PDF文件


前言

Android的webview压根就不支持加载pdf,Android与iOS不同,iOS加载pdf,不管本地还是在线,直接使用webview渲染就可以了,而Android却做不到,所以我们必须得扣脑壳了。方法也有很多种,比如第三方PDFview,MuPDF等,但是不推荐,引入进去apk体积会大很多,所以大多场景都是通过js解析,然后在webview中加载PDF文件,所以内库很小也就2兆多,那我们就开始吧。


一、效果图

在这里插入图片描述

二、实现步骤

1.在项目main目录下新建一个assets

2.新建一个js为index.js

var url = location.search.substring(1);

PDFJS.cMapUrl = 'https://unpkg.com/pdfjs-dist@1.9.426/cmaps/';
PDFJS.cMapPacked = true;

var pdfDoc = null;

function createPage() {
    var div = document.createElement("canvas");
    document.body.appendChild(div);
    return div;
}

function renderPage(num) {
    pdfDoc.getPage(num).then(function (page) {
        var viewport = page.getViewport(2.0);
        var canvas = createPage();
        var ctx = canvas.getContext('2d');

        canvas.height = viewport.height;
        canvas.width = viewport.width;

        page.render({
            canvasContext: ctx,
            viewport: viewport
        });
    });
}

PDFJS.getDocument(url).then(function (pdf) {
    pdfDoc = pdf;
    for (var i = 1; i <= pdfDoc.numPages; i++) {
        renderPage(i)
    }
});


3.新建一个HTML为index.html

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=4.0,user-scalable=no"/>
    <title>Document</title>
    <style type="text/css">
        canvas {
            width: 100%;
            height: 100%;
            border: 1px solid black;
        }
    </style>
    <script src="https://unpkg.com/pdfjs-dist@1.9.426/build/pdf.min.js"></script>
    <script type="text/javascript" src="index.js"></script>
</head>
<body>
</body>
</html>


4.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"
    android:background="#ffffff">

    <include
        android:id="@+id/include"
        layout="@layout/title_layout" />

    <WebView
        android:id="@+id/pdfwebview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/gosign"
        android:layout_below="@+id/include" />

    <TextView
        android:id="@+id/gosign"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_alignParentBottom="true"
        android:layout_centerInParent="true"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="30dp"
        android:layout_marginBottom="30dp"
        android:background="@drawable/blackground_home_blue"
        android:gravity="center"
        android:text="Go Sign"
        android:textColor="#ffffff"
        android:textSize="16dp" />

</RelativeLayout>

4.Activity类(kotlin)

注意:activity代码要点在于WebSettings设置的参数和loadUrl()加载URL时加"file:///android_asset/index.html?"

class PDFWebViewActivity : Activity(), OnClickListener {

    private lateinit var relative_back: RelativeLayout
    private lateinit var text_title: TextView
    private lateinit var url: String//接收URL
    private lateinit var title: String//接收title
    private lateinit var pdfwebview: WebView
    private lateinit var gosign: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //去掉状态栏
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            val decorView = window.decorView
            val option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            decorView.systemUiVisibility = option
            window.statusBarColor = Color.parseColor("#00000000")
        }
        //修改状态栏文字为黑色
        window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
                View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
        setContentView(R.layout.pdfwebviewlayout)
        url = intent.getStringExtra("url")!!.trim { it <= ' ' }
        title = intent.getStringExtra("title")!!.trim { it <= ' ' }
        instantiation()
    }

    fun instantiation() {
        EventBus.getDefault().register(this)
        relative_back = findViewById(R.id.relative_back)
        text_title = findViewById(R.id.text_title)
        text_title.text = title
        pdfwebview = findViewById(R.id.pdfwebview)
        gosign = findViewById(R.id.gosign)
        gosign.setOnClickListener(this)
        relative_back.setOnClickListener(this)
        webviewDe(url)
    }

    override fun onClick(v: View?) {
        when (v?.id) {
            R.id.relative_back ->
                finish()
        }
    }

    /**
     * webview显示
     */
    @SuppressLint("SetJavaScriptEnabled", "JavascriptInterface")
    private fun webviewDe(url: String) {
        println("网页url打印:$url")
        val webSettings: WebSettings = pdfwebview.getSettings()
        webSettings.cacheMode = WebSettings.LOAD_DEFAULT
        //设置加载进来的页面自适应手机屏幕
        webSettings.useWideViewPort = true
        webSettings.loadWithOverviewMode = true
        //问题2:基本都需要支持JS
        webSettings.javaScriptEnabled = true
        webSettings.allowFileAccess = true
        //支持通过JS打开新窗口
        webSettings.allowFileAccessFromFileURLs = true
        webSettings.allowUniversalAccessFromFileURLs = true
        webSettings.javaScriptCanOpenWindowsAutomatically = true
        webSettings.setGeolocationEnabled(true)
        webSettings.domStorageEnabled = true
        webSettings.setAppCacheEnabled(false)
        pdfwebview.scrollBarStyle = WebView.SCROLLBARS_OUTSIDE_OVERLAY
        //触摸焦点起作用
        pdfwebview.requestFocus()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            //http与https的方法
            webSettings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
        }
        // 添加js交互接口类,并起别名 Android
        pdfwebview.addJavascriptInterface(JavascriptImgInterface(), "Android")

        //设置WebChromeClient类
        pdfwebview.webChromeClient = object : WebChromeClient() {
            //获取网站标题
            override fun onReceivedTitle(view: WebView, title: String) {
                println("标题在这里$title")
            }

            //图片选取
            override fun onShowFileChooser(
                webView: WebView,
                filePathCallback: ValueCallback<Array<Uri>>,
                fileChooserParams: FileChooserParams,
            ): Boolean {
                return true
            }
        }
        //设置WebViewClient类
        pdfwebview.webViewClient = object : WebViewClient() {
            override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
                // 返回值是true的时候控制去WebView打开,为false调用系统浏览器或第三方浏览器
                view.loadUrl(url)
                return true
            }

            //设置加载前的函数 kotlin这里favicon: Bitmap?的Bitmap?必须加?
            override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
                if (!this@PDFWebViewActivity.isFinishing) 
                {
                    println("开始加载了")
                    DialogUtils.showLoadingDialog(this@PDFWebViewActivity)
                }
            }

            //设置结束加载函数
            override fun onPageFinished(view: WebView, url: String) {
                println("结束加载了")
                try {
                    DialogUtils.hideLoadingDialog()
                } catch (e: Exception) {
                }
            }
        }
        pdfwebview.loadUrl("file:///android_asset/index.html?$url")
    }

    class JavascriptImgInterface {
        /**
         * 注意: 在Android4.2极其以上系统需要给提供js调用的方法前加入一个注释:@JavaScriptInterface;
         * 在虚拟机当中 Javascript调用Java方法会检测这个anotation,
         * 如果方法被标识@JavaScriptInterface则Javascript可以成功调用这个Java方法,否则调用不成功。
         */
        //js调用Android方法给web返回Token值
        @JavascriptInterface
        open fun Android_Token(): String? {
            println("打印的token:" + SpUtil.get(ConstantUtil.TOKEN, ""))
            return SpUtil.get(ConstantUtil.TOKEN, "")
        }

    }
}

5.Activity类(Java)

注意:activity代码要点在于WebSettings设置的参数和loadUrl()加载URL时加"file:///android_asset/index.html?"


public class PDFWebViewActivity extends Activity implements View.OnClickListener {

    private String url;//接收URL
    private String title;//接收title
    private ImageView left_black_risk;//返回键
    private TextView text_title;//title
    private RelativeLayout gosign;//去签名
    private static String message;//返回消息
    private WebView webviewx5;//webview

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //去掉状态栏
        if (Build.VERSION.SDK_INT >= 21) {
            View decorView = getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            decorView.setSystemUiVisibility(option);
            getWindow().setStatusBarColor(Color.parseColor("#00000000"));
        }
        //修改状态栏文字为黑色
        getWindow().getDecorView().setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
                        View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        setContentView(R.layout.pdfwebviewlayout);
        url = getIntent().getStringExtra("url").trim();
        title = getIntent().getStringExtra("title").trim();
        instantiation();
    }

    private void instantiation() {
        webviewx5 = findViewById(R.id.webview);
        left_black_risk = findViewById(R.id.left_black_risk);
        text_title = findViewById(R.id.text_title);
        gosign = findViewById(R.id.gosign);
        text_title.setText(title);
        left_black_risk.setOnClickListener(this);
        gosign.setOnClickListener(this);
        webviewDe(url);
    }

    /**
     * webview显示
     */
    @SuppressLint({"SetJavaScriptEnabled", "JavascriptInterface"})
    private void webviewDe(String url) {
        System.out.println("网页url打印:" + url);
        WebSettings webSettings = webviewx5.getSettings();
        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
        //设置加载进来的页面自适应手机屏幕
        webSettings.setUseWideViewPort(true);
        webSettings.setLoadWithOverviewMode(true);
        //问题2:基本都需要支持JS
        webSettings.setJavaScriptEnabled(true);
        webSettings.setAllowFileAccess(true);
        //支持通过JS打开新窗口
        webSettings.setAllowFileAccessFromFileURLs(true);
        webSettings.setAllowUniversalAccessFromFileURLs(true);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        webSettings.setGeolocationEnabled(true);
        webSettings.setDomStorageEnabled(true);
        webSettings.setAppCacheEnabled(false);

        webviewx5.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
        //触摸焦点起作用
        webviewx5.requestFocus();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            //http与https的方法
            webSettings.setMixedContentMode(MIXED_CONTENT_ALWAYS_ALLOW);
        }
        // 添加js交互接口类,并起别名 Android
        webviewx5.addJavascriptInterface(new JavascriptImgInterface(), "Android");

        //设置WebChromeClient类
        webviewx5.setWebChromeClient(new WebChromeClient() {


            //获取网站标题
            @Override
            public void onReceivedTitle(WebView view, String title) {
                System.out.println("标题在这里" + title);
            }

            //图片选取
            @Override
            public boolean onShowFileChooser(WebView webView,
                                             ValueCallback<Uri[]> filePathCallback,
                                             FileChooserParams fileChooserParams) {
                return true;
            }
        });
        //设置WebViewClient类
        webviewx5.setWebViewClient(new WebViewClient() {

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                // 返回值是true的时候控制去WebView打开,为false调用系统浏览器或第三方浏览器
                view.loadUrl(url);
                return true;
            }

            //设置加载前的函数
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                if (!PDFWebViewActivity.this.isFinishing())//xActivity即为本界面的Activity
                {
                    System.out.println("开始加载了");
                    DialogUtils.showLoadingDialog(PDFWebViewActivity.this);
                }
            }

            //设置结束加载函数
            @Override
            public void onPageFinished(WebView view, String url) {
                System.out.println("结束加载了");
                try {
                    DialogUtils.hideLoadingDialog();
                } catch (Exception e) {

                }
            }
        });
        webviewx5.loadUrl("file:///android_asset/index.html?" + url);
    }

    public class JavascriptImgInterface {
        /**
         * 注意: 在Android4.2极其以上系统需要给提供js调用的方法前加入一个注释:@JavaScriptInterface;
         * 在虚拟机当中 Javascript调用Java方法会检测这个anotation,
         * 如果方法被标识@JavaScriptInterface则Javascript可以成功调用这个Java方法,否则调用不成功。
         */
        //js调用Android方法给web返回Token值
        @JavascriptInterface
        public String Android_Token() {
            System.out.println("打印的token:" + SpUtil.get(ConstantUtil.TOKEN, ""));
            return SpUtil.get(ConstantUtil.TOKEN, "");
        }

        //js调用Android方法下载apk
        @JavascriptInterface
        public String Android_DownloadApk(String url) {
            //方式一:代码实现跳转
            Intent intent = new Intent();
            //通过intent发送数据
            intent.setAction("android.intent.action.VIEW");
            //创建一个链接  链接.语法解析
            Uri content_url = Uri.parse(url);
            //通过intent接受
            intent.setData(content_url);
            //开始于当前intent
            startActivity(intent);
            return url;
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            //返回键
            case R.id.left_black_risk:
                finish();
                break;
            //去签名
            case R.id.gosign:
                break;
        }
    }
}


总结

以上便是通过加载js的方式预览PDF文件了,都有注释自己慢慢去理解,有问题欢迎提出并指正!

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叶已初秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值