diff --git a/zhuike/src/main/java/com/novelbook/android/BookActivity.java b/zhuike/src/main/java/com/novelbook/android/BookActivity.java index 003d916..2aed68f 100644 --- a/zhuike/src/main/java/com/novelbook/android/BookActivity.java +++ b/zhuike/src/main/java/com/novelbook/android/BookActivity.java @@ -11,11 +11,13 @@ import android.view.View; import android.widget.Toast; import com.novelbook.android.adapter.BookListAdapter; +import com.novelbook.android.db.Chapter; import com.novelbook.android.db.Novel; import com.novelbook.android.netsubscribe.MovieSubscribe; import com.novelbook.android.netutils.HttpMethods; import com.novelbook.android.netutils.OnSuccessAndFaultListener; import com.novelbook.android.netutils.OnSuccessAndFaultSub; +import com.novelbook.android.utils.BookUtil; import com.novelbook.android.utils.NovelParseUtil; import org.json.JSONException; @@ -24,6 +26,7 @@ import org.litepal.LitePal; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import butterknife.BindView; @@ -41,6 +44,7 @@ public class BookActivity extends Activity_base { // private BookListAdapter mAdapter; private List mData;; + private List chapters = new ArrayList<>(); @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.rvBooklist) @@ -143,7 +147,7 @@ public class BookActivity extends Activity_base { }).setCancelable(true).show(); return; } - ReadActivity.openBook(book ,this); + ReadActivity.openBook(book ,chapters,this); } @@ -201,12 +205,25 @@ void onResponseProcess( String content ,String url){ } } */ + + + siteJson.put("chapterUrlRegexOnMulu", "
]*href=\"(/book/[\\d]+/[\\d]+\\.html)\">([^<]+)
"); String[] chapters2 = NovelParseUtil.getChapters(url, content, siteJson); if (chapters2 != null) { for (int i = 0; i < chapters2.length; i += 2) { Log.d(TAG, String.format("%s-->%s", chapters2[i], chapters2[i + 1])); + Chapter chapter = new Chapter(); + chapter.setChapterName(chapters2[i + 1]); + chapter.setChapterPath(chapters2[i ]); + chapters.add(chapter); + } + + + + + siteJson.put("chapterContentRegex", "
([\\s\\S]+?)
"); siteJson.put("chapterContentDumpRegex", ""); @@ -217,7 +234,7 @@ void onResponseProcess( String content ,String url){ // .header("User-Agent", "OkHttp Example") .build(); Response response = HttpMethods.getOkClient().newCall(request).execute(); - // Log.d(TAG,String.format("%s-->%s\n%s" , chapters2[i], chapters2[i+1] , NovelParseUtil.getChapterContent(response.body().string(), siteJson))); + // Log.d(TAG,String.format("%s-->%s\n%s" , chapters2[i], chapters2[i+1] , NovelParseUtil.getChapterContent(response.body().string(), siteJson))); } } diff --git a/zhuike/src/main/java/com/novelbook/android/ReadActivity.java b/zhuike/src/main/java/com/novelbook/android/ReadActivity.java index 2778a07..0f50995 100644 --- a/zhuike/src/main/java/com/novelbook/android/ReadActivity.java +++ b/zhuike/src/main/java/com/novelbook/android/ReadActivity.java @@ -35,6 +35,7 @@ import com.baidu.tts.client.SpeechError; import com.baidu.tts.client.SpeechSynthesizer; import com.baidu.tts.client.SpeechSynthesizerListener; import com.baidu.tts.client.TtsMode; +import com.novelbook.android.db.Chapter; import com.novelbook.android.db.Novel; import com.novelbook.android.db.BookMarks; import com.novelbook.android.dialog.PageModeDialog; @@ -48,6 +49,7 @@ import org.litepal.LitePal; import java.io.IOException; import java.text.DecimalFormat; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -58,6 +60,7 @@ import butterknife.OnClick; public class ReadActivity extends Activity_base implements SpeechSynthesizerListener { private static final String TAG = "ReadActivity"; private final static String EXTRA_BOOK = "book"; + private final static String EXTRA_CHAPTERS = "chapters"; private final static int MESSAGE_CHANGEPROGRESS = 1; @BindView(R.id.bookpage) @@ -103,6 +106,7 @@ public class ReadActivity extends Activity_base implements SpeechSynthesizerLis private Config config; private WindowManager.LayoutParams lp; private Novel book; + private List mChapters; private PageFactory pageFactory; private int screenWidth, screenHeight; // popwindow是否显示 @@ -194,12 +198,12 @@ public class ReadActivity extends Activity_base implements SpeechSynthesizerLis //获取intent中的携带的信息 Intent intent = getIntent(); book = (Novel) intent.getSerializableExtra(EXTRA_BOOK); - + mChapters = (ArrayList) intent.getSerializableExtra(EXTRA_CHAPTERS); bookpage.setPageMode(config.getPageMode()); pageFactory.setPageWidget(bookpage); try { - pageFactory.openBook(book); + pageFactory.openBook(book,mChapters); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "打开电子书失败", Toast.LENGTH_SHORT).show(); @@ -523,13 +527,15 @@ public class ReadActivity extends Activity_base implements SpeechSynthesizerLis } - public static boolean openBook(final Novel book, Activity context) { + public static boolean openBook(final Novel book,List chapters ,Activity context) { if (book == null){ throw new NullPointerException("Novel can not be null"); } Intent intent = new Intent(context, ReadActivity.class); intent.putExtra(EXTRA_BOOK, book); + // intent.putExtra(EXTRA_CHAPTERS, chapters); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); context.overridePendingTransition(R.anim.in_from_right, R.anim.out_to_left); context.startActivity(intent); diff --git a/zhuike/src/main/java/com/novelbook/android/db/Chapter.java b/zhuike/src/main/java/com/novelbook/android/db/Chapter.java index ba2fa41..51baf02 100644 --- a/zhuike/src/main/java/com/novelbook/android/db/Chapter.java +++ b/zhuike/src/main/java/com/novelbook/android/db/Chapter.java @@ -14,6 +14,7 @@ public class Chapter extends LitePalSupport { private int length; private String chapterPath; + public int getId() { return id; } @@ -79,7 +80,5 @@ public class Chapter extends LitePalSupport { } - - } diff --git a/zhuike/src/main/java/com/novelbook/android/db/Novel.java b/zhuike/src/main/java/com/novelbook/android/db/Novel.java index a89f9ec..2bc01e1 100644 --- a/zhuike/src/main/java/com/novelbook/android/db/Novel.java +++ b/zhuike/src/main/java/com/novelbook/android/db/Novel.java @@ -23,6 +23,10 @@ public class Novel extends LitePalSupport implements Serializable{ private String lastestChapterName; private String description; private long lastUpateTime; + private boolean isOnShelf; //是否入书架 + private boolean isFinished; //是否完本 + + public int getId() { return id; @@ -152,8 +156,19 @@ public class Novel extends LitePalSupport implements Serializable{ this.lastUpateTime = lastUpateTime; } + public boolean isOnShelf() { + return isOnShelf; + } + public void setOnShelf(boolean onShelf) { + isOnShelf = onShelf; + } + public boolean isFinished() { + return isFinished; + } - + public void setFinished(boolean finished) { + isFinished = finished; + } } diff --git a/zhuike/src/main/java/com/novelbook/android/utils/BookUtil.java b/zhuike/src/main/java/com/novelbook/android/utils/BookUtil.java index d331282..14be86b 100644 --- a/zhuike/src/main/java/com/novelbook/android/utils/BookUtil.java +++ b/zhuike/src/main/java/com/novelbook/android/utils/BookUtil.java @@ -10,8 +10,11 @@ import android.util.Log; import com.novelbook.android.bean.Cache; import com.novelbook.android.db.Chapter; import com.novelbook.android.db.Novel; +import com.novelbook.android.netutils.HttpMethods; +import org.json.JSONException; +import org.json.JSONObject; import org.litepal.LitePal; import java.io.File; @@ -26,6 +29,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import okhttp3.Request; +import okhttp3.Response; + public class BookUtil { public static final String TAG ="BookUtil"; @@ -40,7 +46,16 @@ public class BookUtil { public static final String lineBreakChar ="\n"; protected final ArrayList myArray = new ArrayList<>(); //目录 - private List directoryList = new ArrayList<>(); + private List mChapters = new ArrayList<>(); + public List getChapters() { + return mChapters; + } + + public void setChapters(List chapters) { + this.mChapters = chapters; + } + + private String m_strCharsetName; private String bookName; @@ -52,7 +67,17 @@ public class BookUtil { private long bookLen; private long position; - private Novel book; + private Novel mNovel; + + private Chapter mChapter; + + public Chapter getChapter() { + return mChapter; + } + + public void setChapter(Chapter chapter) { + this.mChapter = chapter; + } public void setChapterNo(int chapterNo) { this.chapterNo = chapterNo; @@ -83,28 +108,39 @@ public class BookUtil { } } - public synchronized void openBook(Novel book) throws IOException { - this.book = book; + public synchronized void openBook(Novel novel) throws IOException { + this.mNovel = novel; //如果当前缓存不是要打开的书本就缓存书本同时删除缓存 //TODO 构建新的缓存策略,几个选项,1:每本书一个缓存 2:控制缓存总大小,超过限制删除旧缓存 3:网络小说的缓存 - directoryList = LitePal.where("bookId=?",book.getId()+"").find(Chapter.class); + boolean isLocalImport = TextUtils.isEmpty( novel.getNovelId()); + boolean isOnShelf = isLocalImport || novel.isOnShelf(); + boolean isLoadChaptsFromRemote = !isLocalImport ;// && !novel.isFinished() ; //是否从目标网站下载目录 + - for(Chapter c :directoryList){ - Log.d(TAG, String.format("bookchapter :%s,fileName :%s, chapter Size %s",c.getChapterName(),c.getChapterPath(),c.getLength())); - } - chaptCache = new HashMap(); - if(directoryList.isEmpty()) { //1. 首次打开 本地导入的书 2. 首次打开 未缓存的在线小说 + if(isLocalImport) { - if (bookPath == null || !bookPath.equals(book.getNovelPath())) { - cleanCacheFile(); - this.bookPath = book.getNovelPath(); - bookName = FileUtils.getFileName(bookPath); - cacheBook(); + mChapters = LitePal.where("novelId=?", mNovel.getId() + "").find(Chapter.class); + + for (Chapter c : mChapters) { + Log.d(TAG, String.format("bookchapter :%s,fileName :%s, chapter Size %s", c.getChapterName(), c.getChapterPath(), c.getLength())); + } + + chaptCache = new HashMap(); + if (mChapters.isEmpty()) { //1. 首次打开 本地导入的书 2. 首次打开 未缓存的在线小说 + + if (bookPath == null || !bookPath.equals(mNovel.getNovelPath())) { + cleanCacheFile(); + this.bookPath = mNovel.getNovelPath(); + bookName = FileUtils.getFileName(bookPath); + cacheBook(); + } } } + + } private void cleanCacheFile(){ @@ -236,23 +272,23 @@ public class BookUtil { //缓存书本 private void cacheBook() throws IOException { - if (TextUtils.isEmpty(book.getCharset())) { + if (TextUtils.isEmpty(mNovel.getCharset())) { m_strCharsetName = FileUtils.getCharset(bookPath); if (m_strCharsetName == null) { m_strCharsetName = "utf-8"; } ContentValues values = new ContentValues(); values.put("charset",m_strCharsetName); - LitePal.update(Novel.class,values,book.getId()); + LitePal.update(Novel.class,values,mNovel.getId()); }else{ - m_strCharsetName = book.getCharset(); + m_strCharsetName = mNovel.getCharset(); } File file = new File(bookPath); InputStreamReader reader = new InputStreamReader(new FileInputStream(file),m_strCharsetName); int index = 0; bookLen = 0; - directoryList.clear(); + mChapters.clear(); myArray.clear(); while (true){ char[] buf = new char[cachedSize]; @@ -348,11 +384,11 @@ public class BookUtil { bookChapter.setLength((int)(size - start)); bookChapter.setChapterPath(fileChapterName(chaptId) ); bookChapter.update(bookChapter.getId()); - directoryList.add(bookChapter); + mChapters.add(bookChapter); } bookChapter = new Chapter(); - bookChapter.setNovelId(book.getId()); + bookChapter.setNovelId(mNovel.getId()); bookChapter.setNovelChapterStartPos(start); bookChapter.setChapterName(str.replaceAll("###","")); bookChapter.setNovelPath(bookPath); @@ -376,7 +412,7 @@ public class BookUtil { if(writer==null) { bookChapter = new Chapter(); - bookChapter.setNovelId(book.getId()); + bookChapter.setNovelId(mNovel.getId()); bookChapter.setNovelChapterStartPos(start); bookChapter.setChapterName(str.replaceAll("###","")); bookChapter.setNovelPath(bookPath); @@ -397,7 +433,7 @@ public class BookUtil { /* Chapter bookChapter = new Chapter(); - bookChapter.setBookId(book.getId()); + bookChapter.setBookId(mNovel.getId()); bookChapter.setBookChapterStartPos(start); bookChapter.setChapterName(title.replaceAll("###","")); @@ -406,7 +442,7 @@ public class BookUtil { bookChapter.save(); int id= bookChapter.getId(); Log.d(TAG,str + " chaptId is " + id); - directoryList.add(bookChapter); + mChapters.add(bookChapter); */ } } @@ -417,7 +453,7 @@ public class BookUtil { bookChapter.setLength((int)(size - start)); bookChapter.setChapterPath(fileChapterName(chaptId) ); bookChapter.update(bookChapter.getId()); - directoryList.add(bookChapter); + mChapters.add(bookChapter); } }catch (Exception e){ e.printStackTrace(); @@ -429,7 +465,7 @@ public class BookUtil { } public List getDirectoryList(){ - return directoryList; + return mChapters; } public long getBookLen(){ @@ -445,7 +481,7 @@ public class BookUtil { } String getChapterPath(){ - return chapterPath +book.getId()+"/"; + return chapterPath +mNovel.getId()+"/"; } //获取书本缓存 @@ -493,11 +529,37 @@ public class BookUtil { try { File file = new File(fileChapterName(index)); - if(!file.exists()){ + if(!file.exists()) { /* 章节内容没有缓存在本地 1. 根据本地的章节网络地址信息,读取章节内容到本地,若读取失败则 2. 查询主服务器,若有地址更新则更新本地信息,并重复1,若没有更新地址,则地址无效,返回章节内容正待手打 */ + + Chapter chapter = mChapters.get(index); + String url = chapter.getChapterUrl(); + + JSONObject siteJson = new JSONObject(); + siteJson.put("chapterContentRegex", "
([\\s\\S]+?)
"); + siteJson.put("chapterContentDumpRegex", ""); + Request request = new Request.Builder() + .url(url) + // .header("User-Agent", "OkHttp Example") + .build(); + Response response = HttpMethods.getOkClient().newCall(request).execute(); + String content = NovelParseUtil.getChapterContent(response.body().string(), siteJson); + + char[] buf = content.toCharArray(); + try { + file.createNewFile(); + + final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(index)), "UTF-16LE"); // UTF-16LE 比 utf-8 文件小 + writer.write(buf); + writer.close(); + } catch (IOException e) { + throw new RuntimeException("Error during writing " + fileName(index)); + } + + } @@ -519,6 +581,8 @@ public class BookUtil { } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("Error during reading " + fileChapterName(index)); + } catch (JSONException e) { + e.printStackTrace(); } Cache cache = new Cache(); cache.setSize(block.length); diff --git a/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java b/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java index 660193b..28a0c46 100644 --- a/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java +++ b/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java @@ -137,6 +137,8 @@ public class PageFactory { //书本名字 private String bookName = ""; private Novel mBook; + //书的目录列表 + private List mChapters; //书本章节 private int currentChapter = 0; //当前电量 @@ -498,7 +500,7 @@ public class PageFactory { * 打开书本 * @throws IOException */ - public void openBook(Novel book ) throws IOException { + public void openBook(Novel book , List chapters ) throws IOException { //清空数据 currentChapter = 0; // m_mbBufLen = 0; @@ -506,8 +508,8 @@ public class PageFactory { this.mBook = book ; bookPath = mBook.getNovelPath(); - bookName = FileUtils.getFileName(bookPath); - + bookName =mBook.getNovelName();// FileUtils.getFileName(bookPath); + this.mChapters = chapters; mStatus = Status.OPENING; drawStatus(mBookPageWidget.getCurPage()); drawStatus(mBookPageWidget.getNextPage()); @@ -533,6 +535,7 @@ public class PageFactory { PageFactory.mStatus = PageFactory.Status.FINISH; // m_mbBufLen = mBookUtil.getBookLen(); mBookUtil.setChapterNo((int)chapter); + mBookUtil.setChapters(mChapters); currentChaptPages = loadCurrentChapt((int)chapter); currentPage = getPageForBegin(begin) ;// currentChaptPages.get(0); // currentPage = getPageForBegin(begin);