文章目录
- 前言
- 一、效果图
- 二、实现步骤
- 1.在项目main目录下新建一个assets
- 2.新建一个js为index.js
- 3.新建一个HTML为index.html
- 4.xml布局
- 4.Activity类(kotlin)
- 5.Activity类(Java)
- 总结
前言
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文件了,都有注释自己慢慢去理解,有问题欢迎提出并指正!