在线下载章节内容
This commit is contained in:
		
							parent
							
								
									9ad85f7c2e
								
							
						
					
					
						commit
						355b7adf63
					
				|  | @ -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<Novel> mData;; | ||||
| 
 | ||||
|     private List<Chapter> 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", "<dd> <a[^>]*href=\"(/book/[\\d]+/[\\d]+\\.html)\">([^<]+)</a></dd>"); | ||||
|         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", "<div id=\"content\">([\\s\\S]+?)</div>"); | ||||
|             siteJson.put("chapterContentDumpRegex", "<script>chaptererror();</script>"); | ||||
| 
 | ||||
|  | @ -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))); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<Chapter> 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<Chapter>) 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<Chapter> 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); | ||||
|  |  | |||
|  | @ -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 { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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<Cache> myArray = new ArrayList<>(); | ||||
|     //目录 | ||||
|     private List<Chapter> directoryList = new ArrayList<>(); | ||||
|     private List<Chapter> mChapters = new ArrayList<>(); | ||||
|     public List<Chapter> getChapters() { | ||||
|         return mChapters; | ||||
|     } | ||||
| 
 | ||||
|     public void setChapters(List<Chapter> 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<Integer,Cache>(); | ||||
|         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<Integer, Cache>(); | ||||
|             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<Chapter> 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", "<div id=\"content\">([\\s\\S]+?)</div>"); | ||||
|                     siteJson.put("chapterContentDumpRegex", "<script>chaptererror();</script>"); | ||||
|                     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); | ||||
|  |  | |||
|  | @ -137,6 +137,8 @@ public class PageFactory { | |||
|     //书本名字 | ||||
|     private String bookName = ""; | ||||
|     private Novel mBook; | ||||
|     //书的目录列表 | ||||
|     private List<Chapter> 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<Chapter> 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); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue