一.在AndroidManifest.xml中找到
<application android:name=”org.geometerplus.android.fbreader.FBReaderApplication” android:icon=”@drawable/fbreader” android:logo=”@drawable/fbreader_bw” android:label=”FBReader”>
可以看到应用程序的入口为FBReaderApplication
找到FBReaderApplication的类,里面定义如下
public class FBReaderApplication extends ZLAndroidApplication {
}
那么,我们只能看基类ZLAndroidApplication的实现
复制代码
public abstract class ZLAndroidApplication extends Application {
public ZLAndroidApplicationWindow myMainWindow;
@Override
public void onCreate() {
super.onCreate();
new ZLSQLiteConfig(this);
new ZLAndroidImageManager();
new ZLAndroidLibrary(this);
}
}
复制代码
它的工作就是
1.初始化sqlite
2.初始化一个图片管理类
3.初始化一个应用程序信息获取的类,如亮度,分辨率,dpi等等
二 找到启动Activity,在AndroidManifest.xml中找到:
复制代码
<activity android:name=”org.geometerplus.android.fbreader.FBReader” android:launchMode=”singleTask” android:icon=”@drawable/fbreader” android:label=”FBReader” android:theme=”@style/FBReader.Activity” android:configChanges=”orientation|keyboardHidden|screenSize”>
<intent-filter>
<action android:name=”android.intent.action.MAIN”/>
<category android:name=”android.intent.category.LAUNCHER”/>
</intent-filter>
复制代码
即启动Activity为FBReader。
三 下面找出启动之后,书本怎么解析
在FBReader.java类中,找到onStart()函数
复制代码
protected void onStart() {
super.onStart();
getCollection().bindToService(this, new Runnable() {
public void run() {
new Thread() {
public void run() {
openBook(getIntent(), getPostponedInitAction(), false);
myFBReaderApp.getViewWidget().repaint();
}
}.start();
myFBReaderApp.getViewWidget().repaint();
}
});
initPluginActions();
// 其他
}
复制代码
函数中加粗部分,跟踪。。
复制代码
private synchronized void openBook(Intent intent, Runnable action, boolean force) {
Log.i(“FBReader” , “FBReader::openBook”);
if (!force && myBook != null) {
return;
}
// 其他
myFBReaderApp.openBook(myBook, bookmark, action);
}
复制代码
继续跟踪上面加粗的函数
复制代码
public void openBook(final Book book, final Bookmark bookmark, final Runnable postAction) {
Log.i(“FBReader” , “FBReaderApp::openBook”);
if (book != null || Model == null) {
runWithMessage(“loadingBook”, new Runnable() {
public void run() {
openBookInternal(book, bookmark, false);
if (book != null) {
book.addLabel(Book.READ_LABEL);
Collection.saveBook(book, false);
}
}
}, postAction);
}
}
复制代码
继续
复制代码
synchronized void openBookInternal(Book book, Bookmark bookmark, boolean force) {
Log.i(“FBReader”, “FBReaderApp::openBookInternal”);
if (book == null) { // book为空,获取最近阅读中的第一本书
book = Collection.getRecentBook(0);
if (book == null || !book.File.exists()) { // 如果没有阅读历史或者第一个最近阅读的书籍不存在,则打开帮助文件
book = Collection.getBookByFile(BookUtil.getHelpFile());
}
if (book == null) {
return;
}
book.addLabel(Book.READ_LABEL);
Collection.saveBook(book, false);
}
if (!force && Model != null && book.equals(Model.Book)) {
if (bookmark != null) {
gotoBookmark(bookmark);
}
return;
}
onViewChanged();
storePosition();
BookTextView.setModel(null);
FootnoteView.setModel(null);
clearTextCaches();
Model = null;
System.gc();
System.gc();
try {
Model = BookModel.createModel(book);
Collection.saveBook(book, false);
ZLTextHyphenator.Instance().load(book.getLanguage());
BookTextView.setModel(Model.getTextModel());
setBookmarkHighlightings(BookTextView, null);
BookTextView.gotoPosition(Collection.getStoredPosition(book.getId()));
if (bookmark == null) {
setView(BookTextView);
} else {
gotoBookmark(bookmark);
}
Collection.addBookToRecentList(book);
final StringBuilder title = new StringBuilder(book.getTitle());
if (!book.authors().isEmpty()) {
boolean first = true;
for (Author a : book.authors()) {
title.append(first ? ” (” : “, “);
title.append(a.DisplayName);
first = false;
}
title.append(“)”);
}
setTitle(title.toString());
} catch (BookReadingException e) {
processException(e);
}
getViewWidget().reset();
getViewWidget().repaint();
}
复制代码
createModel函数如下:
复制代码
public static BookModel createModel(Book book) throws BookReadingException {
final FormatPlugin plugin = book.getPlugin(); // 根据book获取Plugin,需要知道怎么获取Plugin的可以跟踪进去看看
System.err.println(“using plugin: ” + plugin.supportedFileType() + “/” + plugin.type());
final BookModel model;
switch (plugin.type()) { // 根据Plugin类型,选择用底层的Model还是选择Java层的Model
case NATIVE:
model = new NativeBookModel(book);
break;
case JAVA:
model = new JavaBookModel(book);
break;
default:
throw new BookReadingException(“unknownPluginType”, plugin.type().toString(), null);
}
plugin.readModel(model); // 这里调用ReadModel
return model;
}
复制代码
这里强调下,java层木有txt的Plugin,所以我选择一个epub文件来继续在java层跟踪具体实现。
@Override
public void readModel(BookModel model) throws BookReadingException {
Log.i(“FBReader” , “OEBPlugin::readModel”);
model.Book.File.setCached(true);
new OEBBookReader(model).readBook(getOpfFile(model.Book.File));
}
这里重头戏来了。
OEBBookReader.java中的readBook函数如下
复制代码
void readBook(ZLFile file) throws BookReadingException {
Log.i(“FBReader”, ” OEBBookReader::readBook:ZLFile fileName = ” + file.getShortName());
myFilePrefix = MiscUtil.htmlDirectoryPrefix(file);
// 清理缓存之类
myIdToHref.clear();
myHtmlFileNames.clear();
myNCXTOCFileName = null;
myTourTOC.clear();
myGuideTOC.clear();
myState = READ_NONE;
try {
read(file); // 这里标记为第一步,以epub随遇而安为例子,这里打开的是/mnt/sdcard/Download/随遇而安.epub:tencent/content.opf
} catch (IOException e) {
throw new BookReadingException(e, file);
}
myModelReader.setMainTextModel();
myModelReader.pushKind(FBTextKind.REGULAR);
int count = 0;
for (String name : myHtmlFileNames) { // 所有章节对应的文件名
final ZLFile xhtmlFile = ZLFile.createFileByPath(myFilePrefix + name);
if (xhtmlFile == null || !xhtmlFile.exists()) {
continue;
}
Log.i(“FBReader”, ” xhtmlFile = ” + xhtmlFile.getLongName());
if (count++ == 0 && xhtmlFile.getPath().equals(myCoverFileName)) {
continue;
}
final XHTMLReader reader = new XHTMLReader(myModelReader, myFileNumbers);
final String referenceName = reader.getFileAlias(MiscUtil.archiveEntryName(xhtmlFile.getPath()));
myModelReader.addHyperlinkLabel(referenceName);
myTOCLabels.put(referenceName, myModelReader.Model.BookTextModel.getParagraphsNumber());
try {
reader.readFile(xhtmlFile, referenceName + ‘#’); // 这里定义为第二步,解析每个章节的内容,第二部最终还是会去调用parser.doIt();
} catch (IOException e) {
throw new BookReadingException(e, xhtmlFile);
}
myModelReader.insertEndOfSectionParagraph();
}
generateTOC();
}
复制代码
先跟踪第一步的代码
public void read(ZLFile file) throws IOException {
ZLXMLProcessor.read(this, file);
}
public static void read(ZLXMLReader xmlReader, ZLFile file) throws IOException {
read(xmlReader, file, 65536);// 一次性读取64K
}
复制代码
public static void read(ZLXMLReader xmlReader, ZLFile file, int bufferSize) throws IOException {
InputStream stream = file.getInputStream(); // 这里打开文件读取数据流啊
try {
read(xmlReader, stream, bufferSize);
} finally {
try {
stream.close();
} catch (IOException e) {
}
}
}
复制代码
复制代码
public static void read(ZLXMLReader xmlReader, InputStream stream, int bufferSize) throws IOException {
ZLXMLParser parser = null;
try {
parser = new ZLXMLParser(xmlReader, stream, bufferSize);
xmlReader.startDocumentHandler();
parser.doIt();// 解析啊,这里就是读取xml文件的内容啊
xmlReader.endDocumentHandler();
} finally {
if (parser != null) {
parser.finish();
}
}
}
复制代码
到这里,第一步算是解析完成了
我们再看看第一步解析出来的数据到哪里去了
在ZLXMLParser中
复制代码
void doIt() throws IOException {
case TEXT:
while (true) {
switch (buffer[++i]) {
case ‘<‘:
if (i > startPosition) {
xmlReader.characterDataHandlerFinal(buffer, startPosition, i – startPosition);
}
state = LANGLE;
break mainSwitchLabel;
case ‘&’:
if (i > startPosition) {
xmlReader.characterDataHandler(buffer, startPosition, i – startPosition);
}
savedState = TEXT;
state = ENTITY_REF;
startPosition = i + 1;
break mainSwitchLabel;
}
}
}
}
}
}
复制代码
看到加粗函数了没?
跟踪进去啦!
public void characterDataHandlerFinal(char[] ch, int start, int length) {
characterDataHandler(ch, start, length);
}
在XHTMLReader中的characterDataHandler函数
复制代码
public void characterDataHandler(char[] data, int start, int len) {
if (len > 0) {
if (myInsideBody && !myModelReader.paragraphIsOpen()) {
myModelReader.beginParagraph();
}
myModelReader.addData(data, start, len, false);
}
}
复制代码
在BookReader中
复制代码
public final void addData(char[] data, int offset, int length, boolean direct) {
if (!myTextParagraphExists || length == 0) {
return;
}
if (!myInsideTitle && !mySectionContainsRegularContents) {
while (length > 0 && Character.isWhitespace(data[offset])) {
–length;
++offset;
}
if (length == 0) {
return;
}
}
myTextParagraphIsNonEmpty = true;
if (direct && myTextBufferLength == 0 && !myInsideTitle) {
myCurrentTextModel.addText(data, offset, length);
} else {
final int oldLength = myTextBufferLength;
final int newLength = oldLength + length;
if (myTextBuffer.length < newLength) {
myTextBuffer = ZLArrayUtils.createCopy(myTextBuffer, oldLength, newLength);
}
System.arraycopy(data, offset, myTextBuffer, oldLength, length);
myTextBufferLength = newLength;
if (myInsideTitle) {
addContentsData(myTextBuffer, oldLength, length);
}
}
if (!myInsideTitle) {
mySectionContainsRegularContents = true;
}
}
复制代码
到此为止,解析出来的数据添加到BookReader的myCurrentTextModel中,或者是添加到缓存myContentsBuffer中
<application android:name=”org.geometerplus.android.fbreader.FBReaderApplication” android:icon=”@drawable/fbreader” android:logo=”@drawable/fbreader_bw” android:label=”FBReader”>
可以看到应用程序的入口为FBReaderApplication
找到FBReaderApplication的类,里面定义如下
public class FBReaderApplication extends ZLAndroidApplication {
}
那么,我们只能看基类ZLAndroidApplication的实现
复制代码
public abstract class ZLAndroidApplication extends Application {
public ZLAndroidApplicationWindow myMainWindow;
@Override
public void onCreate() {
super.onCreate();
new ZLSQLiteConfig(this);
new ZLAndroidImageManager();
new ZLAndroidLibrary(this);
}
}
复制代码
它的工作就是
1.初始化sqlite
2.初始化一个图片管理类
3.初始化一个应用程序信息获取的类,如亮度,分辨率,dpi等等
二 找到启动Activity,在AndroidManifest.xml中找到:
复制代码
<activity android:name=”org.geometerplus.android.fbreader.FBReader” android:launchMode=”singleTask” android:icon=”@drawable/fbreader” android:label=”FBReader” android:theme=”@style/FBReader.Activity” android:configChanges=”orientation|keyboardHidden|screenSize”>
<intent-filter>
<action android:name=”android.intent.action.MAIN”/>
<category android:name=”android.intent.category.LAUNCHER”/>
</intent-filter>
复制代码
即启动Activity为FBReader。
三 下面找出启动之后,书本怎么解析
在FBReader.java类中,找到onStart()函数
复制代码
protected void onStart() {
super.onStart();
getCollection().bindToService(this, new Runnable() {
public void run() {
new Thread() {
public void run() {
openBook(getIntent(), getPostponedInitAction(), false);
myFBReaderApp.getViewWidget().repaint();
}
}.start();
myFBReaderApp.getViewWidget().repaint();
}
});
initPluginActions();
// 其他
}
复制代码
函数中加粗部分,跟踪。。
复制代码
private synchronized void openBook(Intent intent, Runnable action, boolean force) {
Log.i(“FBReader” , “FBReader::openBook”);
if (!force && myBook != null) {
return;
}
// 其他
myFBReaderApp.openBook(myBook, bookmark, action);
}
复制代码
继续跟踪上面加粗的函数
复制代码
public void openBook(final Book book, final Bookmark bookmark, final Runnable postAction) {
Log.i(“FBReader” , “FBReaderApp::openBook”);
if (book != null || Model == null) {
runWithMessage(“loadingBook”, new Runnable() {
public void run() {
openBookInternal(book, bookmark, false);
if (book != null) {
book.addLabel(Book.READ_LABEL);
Collection.saveBook(book, false);
}
}
}, postAction);
}
}
复制代码
继续
复制代码
synchronized void openBookInternal(Book book, Bookmark bookmark, boolean force) {
Log.i(“FBReader”, “FBReaderApp::openBookInternal”);
if (book == null) { // book为空,获取最近阅读中的第一本书
book = Collection.getRecentBook(0);
if (book == null || !book.File.exists()) { // 如果没有阅读历史或者第一个最近阅读的书籍不存在,则打开帮助文件
book = Collection.getBookByFile(BookUtil.getHelpFile());
}
if (book == null) {
return;
}
book.addLabel(Book.READ_LABEL);
Collection.saveBook(book, false);
}
if (!force && Model != null && book.equals(Model.Book)) {
if (bookmark != null) {
gotoBookmark(bookmark);
}
return;
}
onViewChanged();
storePosition();
BookTextView.setModel(null);
FootnoteView.setModel(null);
clearTextCaches();
Model = null;
System.gc();
System.gc();
try {
Model = BookModel.createModel(book);
Collection.saveBook(book, false);
ZLTextHyphenator.Instance().load(book.getLanguage());
BookTextView.setModel(Model.getTextModel());
setBookmarkHighlightings(BookTextView, null);
BookTextView.gotoPosition(Collection.getStoredPosition(book.getId()));
if (bookmark == null) {
setView(BookTextView);
} else {
gotoBookmark(bookmark);
}
Collection.addBookToRecentList(book);
final StringBuilder title = new StringBuilder(book.getTitle());
if (!book.authors().isEmpty()) {
boolean first = true;
for (Author a : book.authors()) {
title.append(first ? ” (” : “, “);
title.append(a.DisplayName);
first = false;
}
title.append(“)”);
}
setTitle(title.toString());
} catch (BookReadingException e) {
processException(e);
}
getViewWidget().reset();
getViewWidget().repaint();
}
复制代码
createModel函数如下:
复制代码
public static BookModel createModel(Book book) throws BookReadingException {
final FormatPlugin plugin = book.getPlugin(); // 根据book获取Plugin,需要知道怎么获取Plugin的可以跟踪进去看看
System.err.println(“using plugin: ” + plugin.supportedFileType() + “/” + plugin.type());
final BookModel model;
switch (plugin.type()) { // 根据Plugin类型,选择用底层的Model还是选择Java层的Model
case NATIVE:
model = new NativeBookModel(book);
break;
case JAVA:
model = new JavaBookModel(book);
break;
default:
throw new BookReadingException(“unknownPluginType”, plugin.type().toString(), null);
}
plugin.readModel(model); // 这里调用ReadModel
return model;
}
复制代码
这里强调下,java层木有txt的Plugin,所以我选择一个epub文件来继续在java层跟踪具体实现。
@Override
public void readModel(BookModel model) throws BookReadingException {
Log.i(“FBReader” , “OEBPlugin::readModel”);
model.Book.File.setCached(true);
new OEBBookReader(model).readBook(getOpfFile(model.Book.File));
}
这里重头戏来了。
OEBBookReader.java中的readBook函数如下
复制代码
void readBook(ZLFile file) throws BookReadingException {
Log.i(“FBReader”, ” OEBBookReader::readBook:ZLFile fileName = ” + file.getShortName());
myFilePrefix = MiscUtil.htmlDirectoryPrefix(file);
// 清理缓存之类
myIdToHref.clear();
myHtmlFileNames.clear();
myNCXTOCFileName = null;
myTourTOC.clear();
myGuideTOC.clear();
myState = READ_NONE;
try {
read(file); // 这里标记为第一步,以epub随遇而安为例子,这里打开的是/mnt/sdcard/Download/随遇而安.epub:tencent/content.opf
} catch (IOException e) {
throw new BookReadingException(e, file);
}
myModelReader.setMainTextModel();
myModelReader.pushKind(FBTextKind.REGULAR);
int count = 0;
for (String name : myHtmlFileNames) { // 所有章节对应的文件名
final ZLFile xhtmlFile = ZLFile.createFileByPath(myFilePrefix + name);
if (xhtmlFile == null || !xhtmlFile.exists()) {
continue;
}
Log.i(“FBReader”, ” xhtmlFile = ” + xhtmlFile.getLongName());
if (count++ == 0 && xhtmlFile.getPath().equals(myCoverFileName)) {
continue;
}
final XHTMLReader reader = new XHTMLReader(myModelReader, myFileNumbers);
final String referenceName = reader.getFileAlias(MiscUtil.archiveEntryName(xhtmlFile.getPath()));
myModelReader.addHyperlinkLabel(referenceName);
myTOCLabels.put(referenceName, myModelReader.Model.BookTextModel.getParagraphsNumber());
try {
reader.readFile(xhtmlFile, referenceName + ‘#’); // 这里定义为第二步,解析每个章节的内容,第二部最终还是会去调用parser.doIt();
} catch (IOException e) {
throw new BookReadingException(e, xhtmlFile);
}
myModelReader.insertEndOfSectionParagraph();
}
generateTOC();
}
复制代码
先跟踪第一步的代码
public void read(ZLFile file) throws IOException {
ZLXMLProcessor.read(this, file);
}
public static void read(ZLXMLReader xmlReader, ZLFile file) throws IOException {
read(xmlReader, file, 65536);// 一次性读取64K
}
复制代码
public static void read(ZLXMLReader xmlReader, ZLFile file, int bufferSize) throws IOException {
InputStream stream = file.getInputStream(); // 这里打开文件读取数据流啊
try {
read(xmlReader, stream, bufferSize);
} finally {
try {
stream.close();
} catch (IOException e) {
}
}
}
复制代码
复制代码
public static void read(ZLXMLReader xmlReader, InputStream stream, int bufferSize) throws IOException {
ZLXMLParser parser = null;
try {
parser = new ZLXMLParser(xmlReader, stream, bufferSize);
xmlReader.startDocumentHandler();
parser.doIt();// 解析啊,这里就是读取xml文件的内容啊
xmlReader.endDocumentHandler();
} finally {
if (parser != null) {
parser.finish();
}
}
}
复制代码
到这里,第一步算是解析完成了
我们再看看第一步解析出来的数据到哪里去了
在ZLXMLParser中
复制代码
void doIt() throws IOException {
case TEXT:
while (true) {
switch (buffer[++i]) {
case ‘<‘:
if (i > startPosition) {
xmlReader.characterDataHandlerFinal(buffer, startPosition, i – startPosition);
}
state = LANGLE;
break mainSwitchLabel;
case ‘&’:
if (i > startPosition) {
xmlReader.characterDataHandler(buffer, startPosition, i – startPosition);
}
savedState = TEXT;
state = ENTITY_REF;
startPosition = i + 1;
break mainSwitchLabel;
}
}
}
}
}
}
复制代码
看到加粗函数了没?
跟踪进去啦!
public void characterDataHandlerFinal(char[] ch, int start, int length) {
characterDataHandler(ch, start, length);
}
在XHTMLReader中的characterDataHandler函数
复制代码
public void characterDataHandler(char[] data, int start, int len) {
if (len > 0) {
if (myInsideBody && !myModelReader.paragraphIsOpen()) {
myModelReader.beginParagraph();
}
myModelReader.addData(data, start, len, false);
}
}
复制代码
在BookReader中
复制代码
public final void addData(char[] data, int offset, int length, boolean direct) {
if (!myTextParagraphExists || length == 0) {
return;
}
if (!myInsideTitle && !mySectionContainsRegularContents) {
while (length > 0 && Character.isWhitespace(data[offset])) {
–length;
++offset;
}
if (length == 0) {
return;
}
}
myTextParagraphIsNonEmpty = true;
if (direct && myTextBufferLength == 0 && !myInsideTitle) {
myCurrentTextModel.addText(data, offset, length);
} else {
final int oldLength = myTextBufferLength;
final int newLength = oldLength + length;
if (myTextBuffer.length < newLength) {
myTextBuffer = ZLArrayUtils.createCopy(myTextBuffer, oldLength, newLength);
}
System.arraycopy(data, offset, myTextBuffer, oldLength, length);
myTextBufferLength = newLength;
if (myInsideTitle) {
addContentsData(myTextBuffer, oldLength, length);
}
}
if (!myInsideTitle) {
mySectionContainsRegularContents = true;
}
}
复制代码
到此为止,解析出来的数据添加到BookReader的myCurrentTextModel中,或者是添加到缓存myContentsBuffer中
原文地址:
http://www.cnblogs.com/deagle/articles/3262289.html
http://www.cnblogs.com/deagle/articles/3262289.html
今天的文章fbreader pdf plugin_ezpdf阅读器安卓版分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/85715.html