Android App 集成 MuPdf 实现 Pdf 阅读、编辑、标记等功能
By Long Luo
之前开发 Android电子书阅读器App 时,需要支持 Pdf 文件的阅读和标记功能,经过分析和测试不同实现方案,最终选择 MuPdf 方案。
Pdf解决方案
目前手机上实现 Pdf 文件的支持,有很多解决方案:
Andorid原生自带的Pdf解决方案,主要提供两个类 PdfRenderer 和 PdfDocument ,但是 Lollipop 才有的类,PdfRenderer 中核心代码是用的 native 方法,所以没办法将 PdfRenderer 从 SDK 中抽取出来用,局限性大,不采用。
开源 AndroidPdfViewer ,完全使用 Java 实现,但问题在于太大,性能不及原生,所以放弃。
MuPdf,一款轻量级的 pdf 框架,支持前面两者功能,同时如果是文本的 pdf 文档还支持搜索、标注等功能,使用 native C 代码实现,快,编译好的so库也只有10M大小。
调起手机中第三方支持 Pdf 阅读的应用;
通过 pdf.js 实现在线预览,需要调用网页,性能不及原生,放弃。
MuPdf
MuPdf 是一个轻量级 PDF、XPS 和 E-book 阅读器,支持全部平台。
源码下载地址:https://mupdf.com/downloads/archive/
官网提供了一个例子:MuPDF Android Viewer,下面我们来编译并实现。
MuPdf编译
下载源码:1
$ git clone --recursive git://git.ghostscript.com/mupdf-android-viewer.git
安装Cygwin或者直接在Linux下使用:1
2mupdf-android-viewer$cd jni
mupdf-android-viewer/jni$make generate
会调用 make -j4 -C libmupdf generate
命令编译字体文件,然后在 libmupdf
目录下生成 generated
文件夹,里面主要是一些字体文件。
编译libmupdf_java.so
Linux 下 NDK 编译环境配置可以参考之前的文章 Linux下Android开发环境搭建指南 。
或者在 Windows 下配置好NDK编译,然后进入 ~/mupdf-android-viewer/jni/libmupdf
目录下,ndk-build
编译:1
~\mupdf-android-viewer\jni\libmupdf>ndk-build -j8 APP_BUILD_SCRIPT=platform/java/Android.mk APP_PROJECT_PATH=build/android APP_PLATFORM=android-16 APP_OPTIM=debug APP_ABI=arm64-v8a
编译中出现下列错误:1
2
3process_begin: CreateProcess(... ...)
harfbuzz...
make (e=87): 参数错误。
原因是参数太长,解决方案是在 mupdf-android-viewer\jni\libmupdf\platform\java
的:
在 Android.mk 文件中添加:LOCAL_SHORT_COMMANDS := true1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29# Android makefile to be used with ndk-build.
#
# Run ndk-build with the following arguments:
# APP_BUILD_SCRIPT=platform/java/Android.mk (this file)
# APP_PROJECT_DIR=build/android (where you want the output)
# APP_PLATFORM=android-16
# APP_OPTIM=release (or debug)
# APP_ABI=all (or armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips, mips64)
#
# The top-level Makefile will invoke ndk-build with appropriate arguments
# if you run 'make android'.
#
# Use the MUPDF_EXTRA_CFLAGS, MUPDF_EXTRA_CPPFLAGS, MUPDF_EXTRA_LDFLAGS,
# and MUPDF_EXTRA_LDLIBS variables to add more compiler flags.
#
# LOCAL_C_INCLUDES paths are relative to the NDK root directory.
# LOCAL_SRC_FILES paths are relative to LOCAL_PATH.
#
# We make sure to use absolute paths everywhere, so this makefile works
# regardless of where it is called from.
LOCAL_PATH := $(call my-dir)
MUPDF_PATH := $(realpath $(LOCAL_PATH)/../..)
LOCAL_SHORT_COMMANDS := true
ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
HAVE_NEON := yes
endif
在 Application.mk 文件中添加:APP_SHORT_COMMANDS := true1
2
3
4
5
6
7APP_SHORT_COMMANDS := true
ifdef USE_TESSERACT
APP_STL := c++_static
endif
重新编译,OK的话会在 \jni\libmupdf\build\android\libs\arm64-v8a
目录下生成下列文件:1
~\mupdf-android-viewer\jni\libmupdf\build\android\libs\arm64-v8a\libmupdf_java.so
Pdf Viewer 集成MuPdf
Demo具体源码可参考:https://github.com/longluo/AndroidPdfViewer
已测试OK!