Android电子书阅读器App
By LongLuo
这几天写了个Android App,实现了一个电子书阅读器,下面写下具体开发思路及过程。
主流电子书格式
目前市面上常见的电子书格式有epub、txt、mobi、azw、azw3等,如果做一个电子书阅读器的话,必须支持上述格式。
Epub
epub最开始使用的是epublib ,集成非常简单,只需要将epublib.jar拷贝到libs目录下,并在代码中调用即可,参考代码如下所示:1
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 try {
EpubReader reader = new EpubReader();
InputStream in = getAssets().open("algorithms.epub");
book = reader.readEpub(in);
Metadata metadata = book.getMetadata();
StringBuffer buffer = new StringBuffer();
for (String s : metadata.getDescriptions()) {
buffer.append(s + " ");
}
String bookInfo = "作者:" + metadata.getAuthors().get(0) +
"\n出版社:" + metadata.getPublishers().get(0) +
"\n出版时间:" + TimeUtils.getStringData(metadata.getDates().get(0).getValue()) +
"\n书名:" + metadata.getTitles().get(0) +
"\n简介:" + metadata.getDescriptions().get(0) +
"\n语言:" + metadata.getLanguage() +
"\n\n封面图:";
mTvText.setText(bookInfo);
Log.i(TAG, "onCreate: bookInfo=" + bookInfo);
// 书籍的阅读顺序,是一个线性的顺序。通过Spine可以知道应该按照怎样的章节,顺序去阅读,
// 并且通过Spine可以找到对应章节的内容。
Spine spine = book.getSpine();
List<SpineReference> spineReferences = spine.getSpineReferences();
if (spineReferences != null && spineReferences.size() > 0) {
Resource resource = spineReferences.get(1).getResource();//获取带章节信息的那个html页面
Log.i(TAG, "initView: book=" + resource.getId() + " " + resource.getTitle() + " " + resource.getSize() + " ");
byte[] data = resource.getData();//和 resource.getInputStream() 返回的都是html格式的文章内容,只不过读取方式不一样
String strHtml = StringUtils.bytes2Hex(data);
Log.i(TAG, "initView: strHtml= " + strHtml);
parseHtmlData(strHtml);
} else {
Log.i(TAG, "initView: spineReferences is null");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 解析html
*/
private void parseHtmlData(String strHtml) throws IOException {
Document doc = Jsoup.parse(strHtml);
Log.i(TAG, "parseHtmlData: doc.title();=" + doc.title());
Elements eles = doc.getElementsByTag("a"); // a标签
// 遍历Elements的每个Element
EpubBean epubBean;
for (Element link : eles) {
String linkHref = link.attr("href"); // a标签的href属性
String text = link.text();
epubBean = new EpubBean();
epubBean.href = linkHref;
epubBean.tilte = text;
indexTitleList.add(epubBean);
Log.i(TAG, "parseHtmlData: linkHref=" + linkHref + " text=" + text);
}
}
不过这种方法仍然看起来比较复杂,由于之后为了支持Pdf,集成了MuPdf,而MuPdf本身也支持epub格式的读写,所以在后来版本中,就只需要保留MuPdf即可,就去除了EpubLib。
具体参考Android App集成MuPdf,实现Pdf阅读、编辑、标记等功能 这篇文章,实现Pdf的阅读、编辑、标记等功能。
mobi & azw, azw3
mobi/azw/azw3格式支持,使用了libmobi 开源库。
libmobi编译
下载源码之后,使用NDK编译生成libmobi.so。
在mobi文件夹下增加Android.mk文件:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CFLAGS := $(APP_CFLAGS)
LOCAL_CPPFLAGS := $(APP_CPPFLAGS)
LOCAL_ARM_MODE := $(APP_ARM_MODE)
LOCAL_MODULE := libmobi
LOCAL_SRC_FILES := buffer.c common.c compression.c debug.c encryption.c index.c memory.c meta.c miniz.c mobitool.c opf.c parse_rawml.c read.c sha1.c structure.c util.c write.c xmlwriter.c
LOCAL_CFLAGS += -std=c99
LOCAL_CFLAGS += -DUSE_XMLWRITER
LOCAL_LDLIBS := -lz
include $(BUILD_SHARED_LIBRARY)
Application.mk文件内容:1
2
3
4
5
6
7
8
9
10
11APP_PLATFORM=android-16
APP_ABI := arm64-v8a armeabi-v7a
APP_OPTIM := release
APP_ARM_MODE := arm
APP_CFLAGS := -O2
APP_CPPFLAGS := -O2
APP_STL := c++_static
在当前目录下:1
~\jni\mobi>ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk NDK_APPLICATION_MK=./Application.mk
在libs文件夹下会生成对应的libmobi.so文件。
开发历程
在开发电子书阅读App功能时,从无到有,逐渐添加功能,下面就是我开发的过程:
1. 最简单的Demo
只实现了简单的epub的阅读:https://github.com/longluo/EbookReader/tree/demobook
2. 丰富各种界面
https://github.com/longluo/EbookReader/tree/demobook
3. 移植FBReader App
参考开源的FBReader,https://github.com/longluo/EbookReader/tree/fbreader
4. 增加Pdf支持
集成MuPdf:https://github.com/longluo/EbookReader/tree/pdf
5. 增加azw/mobi格式支持
集成LibMobi,实现azw/mobi格式支持: https://github.com/longluo/EbookReader/tree/azw_mobi
ToDos
- 书架展示
- 书签功能
- 修改字体、背景等; …