pda/zhuike/src/main/java/com/novelbook/android/utils/BookUtil.java

1562 lines
59 KiB
Java
Raw Normal View History

2019-04-02 17:41:53 +08:00
package com.novelbook.android.utils;
2019-04-05 23:59:31 +08:00
import android.app.ProgressDialog;
2019-04-02 17:41:53 +08:00
import android.content.ContentValues;
2019-04-05 23:59:31 +08:00
import android.content.Context;
2019-04-02 17:41:53 +08:00
2019-04-18 17:19:42 +08:00
import android.os.AsyncTask;
2019-04-05 23:59:31 +08:00
import android.os.Handler;
import android.os.Message;
2019-04-02 17:41:53 +08:00
import android.text.TextUtils;
import android.util.Log;
2019-04-05 23:59:31 +08:00
import android.widget.Toast;
2019-04-02 17:41:53 +08:00
2019-04-05 23:59:31 +08:00
import com.google.gson.Gson;
import com.novelbook.android.MyApp;
2019-04-02 17:41:53 +08:00
import com.novelbook.android.bean.Cache;
2019-04-05 23:59:31 +08:00
import com.novelbook.android.bean.NovelSites;
import com.novelbook.android.bean.Site;
import com.novelbook.android.db.SiteRule;
2019-04-03 16:21:00 +08:00
import com.novelbook.android.db.Chapter;
import com.novelbook.android.db.Novel;
2019-04-05 23:59:31 +08:00
import com.novelbook.android.netsubscribe.BookSubscribe;
2019-04-03 18:09:00 +08:00
import com.novelbook.android.netutils.HttpMethods;
2019-04-20 00:26:49 +08:00
import com.novelbook.android.netutils.NetUtil;
2019-04-05 23:59:31 +08:00
import com.novelbook.android.netutils.OnSuccessAndFaultListener;
import com.novelbook.android.netutils.OnSuccessAndFaultSub;
2019-04-02 17:41:53 +08:00
2019-04-03 18:09:00 +08:00
import org.json.JSONException;
import org.json.JSONObject;
2019-04-02 17:41:53 +08:00
import org.litepal.LitePal;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
2019-04-05 23:59:31 +08:00
import java.util.Date;
2019-04-02 17:41:53 +08:00
import java.util.HashMap;
import java.util.List;
import java.util.Map;
2019-04-05 23:59:31 +08:00
import okhttp3.Call;
import okhttp3.Callback;
2019-04-03 18:09:00 +08:00
import okhttp3.Request;
import okhttp3.Response;
2019-04-05 23:59:31 +08:00
import okhttp3.ResponseBody;
2019-04-03 18:09:00 +08:00
2019-04-02 17:41:53 +08:00
public class BookUtil {
public static final String TAG ="BookUtil";
2019-04-08 23:16:20 +08:00
public static final String storagePath = FileUtils.getDiskCacheDir(MyApp.applicationContext);//Environment.getExternalStorageDirectory() + "/zhuike";
public static final String cachedPath = storagePath + "/cache/";
public static final String chapterPath = storagePath + "/chapter/";
2019-04-02 17:41:53 +08:00
private static final String charachterType = "utf-8";//"UTF-16LE";
2019-04-05 23:59:31 +08:00
private Context mContext;
private ProgressDialog progressDialog;
private MuluStatus mMuluStatus; //目录是否下载完成
private Gson gson = new Gson();
public void setContext(Context context) {
this.mContext = context;
}
2019-04-14 23:17:31 +08:00
public boolean isReadingCatalogs() {
return mMuluStatus == MuluStatus.isDownloading;
}
2019-04-02 17:41:53 +08:00
//存储的字符数
public static final int cachedSize = 30000;
// protected final ArrayList<WeakReference<char[]>> myArray = new ArrayList<>();
public static final String lineBreakChar ="\n";
protected final ArrayList<Cache> myArray = new ArrayList<>();
//目录
2019-04-03 18:09:00 +08:00
private List<Chapter> mChapters = new ArrayList<>();
2019-04-05 23:59:31 +08:00
//当前章节
// private Chapter mCurrentChapter;
2019-04-03 18:09:00 +08:00
public List<Chapter> getChapters() {
return mChapters;
}
public void setChapters(List<Chapter> chapters) {
this.mChapters = chapters;
}
2019-04-02 17:41:53 +08:00
private String m_strCharsetName;
private String bookName;
private String bookPath;
public void setBookLen(long bookLen) {
this.bookLen = bookLen;
}
private long bookLen;
private long position;
2019-04-03 18:09:00 +08:00
private Novel mNovel;
2019-04-05 23:59:31 +08:00
public void setNovel(Novel novel) {
this.mNovel = novel;
}
2019-04-14 23:17:31 +08:00
public Novel getNovel( ) {
return mNovel ;
}
2019-04-05 23:59:31 +08:00
//当前目录网站列表
private NovelSites mNovelSites;
//当前目录网站
private Site mSite;
private SiteRule mSiteRule;
2019-04-16 23:11:00 +08:00
2019-04-26 23:33:17 +08:00
private Map<Integer,Cache> chaptCache = new HashMap<Integer,Cache>();
private Map<Integer,DownloadStatus> chaptDownStatus = new HashMap<Integer, DownloadStatus>();
DownloadStatus downloadStatus = DownloadStatus.notStart;
2019-04-18 17:19:42 +08:00
public NovelSites getmNovelSites() {
return mNovelSites;
}
2019-04-23 22:45:08 +08:00
public synchronized void openBook(Novel novel, long chapter) throws IOException, InterruptedException {
2019-04-16 23:11:00 +08:00
this.mNovel = novel;
//如果当前缓存不是要打开的书本就缓存书本同时删除缓存
//TODO 构建新的缓存策略几个选项1每本书一个缓存 2控制缓存总大小超过限制删除旧缓存 3网络小说的缓存
boolean isLocalImport = novel.isLocalBook();
boolean isOnShelf = isLocalImport || novel.isOnShelf();
boolean isLoadChaptsFromRemote = !isLocalImport ;// && !novel.isFinished() ; //是否从目标网站下载目录
// showProgressDialog();
if(isLocalImport) {
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. 首次打开 本地导入的书
if (bookPath == null || !bookPath.equals(mNovel.getNovelPath())) {
2019-04-26 23:33:17 +08:00
cleanCacheFile();
2019-04-16 23:11:00 +08:00
this.bookPath = mNovel.getNovelPath();
bookName = FileUtils.getFileName(bookPath);
cacheBook();
}
}
}else{ //读取目录列表
2019-04-23 22:45:08 +08:00
Log.d(TAG, String.format("prepare book %s open chapter %s in background.... mMuluStatus %smSiteRule %s,thread %s",mNovel.getName(),chapter,mMuluStatus,mSiteRule,Thread.currentThread().getName()) );
File file =new File(fileChapterName((int)chapter));
if( file.exists()){
Log.d(TAG, String.format("prepare book open chapter file %s, exist,not waiting more...to open file...",fileChapterName((int)chapter) ));
return;
}
2019-04-16 23:11:00 +08:00
MuluStatus m = mMuluStatus;
// Log.d(TAG,String.format("mulu on Site %s download status %s",mSite.getDomain(),mMuluStatus));
Log.d(TAG, String.format("prepare book %s open book in background.... mMuluStatus %smSiteRule %s,thread %s",mNovel.getName(),mMuluStatus,mSiteRule,Thread.currentThread().getName()) );
2019-04-20 00:26:49 +08:00
int sleptTime =0;
2019-04-16 23:11:00 +08:00
while( mSiteRule ==null || mMuluStatus==null || mMuluStatus == MuluStatus.isDownloading){
2019-04-20 00:26:49 +08:00
sleptTime++;
2019-04-23 22:45:08 +08:00
if(sleptTime >400 || sleptTime >30 && !NetUtil.isNetworkConnected()){
2019-04-20 00:26:49 +08:00
break;
}
2019-04-23 22:45:08 +08:00
2019-04-16 23:11:00 +08:00
Thread.sleep(50);
if(mMuluStatus == MuluStatus.failed){
2019-04-23 22:45:08 +08:00
Log.d(TAG,String.format("prepare book %s failed ,mMuluStatus %s,msiteRule %s,slept %s" ,mNovel.getName(),mMuluStatus,mSiteRule,sleptTime*50));
// throw new RuntimeException("读取资源失败,请检查网络");
2019-04-16 23:11:00 +08:00
}
}
2019-04-23 22:45:08 +08:00
Log.d(TAG,String.format("prepare book %s waiting for mulu downloading ,mMuluStatus %s,msiteRule %s,slept %s" ,mNovel.getName(),mMuluStatus,mSiteRule,sleptTime*50));
2019-04-16 23:11:00 +08:00
}
// dismissProgressDialog();
}
2019-04-05 23:59:31 +08:00
public void setNovelSites(NovelSites nvs) {
this.mNovelSites = nvs;
2019-04-15 23:26:24 +08:00
2019-04-16 23:11:00 +08:00
Log.d(TAG, String.format("prepare book %s get novel sites count %s .",mNovel.getName(), nvs.getSites().length) );
2019-04-05 23:59:31 +08:00
if(nvs.getSites().length ==0){
2019-04-15 23:26:24 +08:00
throw new RuntimeException("书本错误 code 001"); //无目标网站
// return;
2019-04-05 23:59:31 +08:00
}
mSite =nvs.getSites()[0];
if(nvs.getSites().length > 0)
for (Site site:nvs.getSites() ) {
if(site.getSelectedByDefault()){
mSite = site;
break;
}
}
2019-04-06 23:04:42 +08:00
getSiteRule();
}
private void setSiteInfo() {
2019-04-05 23:59:31 +08:00
File file = new File(getChapterPath() +mSite.getDomain());
if(!file.exists()){
file.mkdir();
}
2019-04-06 23:04:42 +08:00
mNovel.setDomain(mSite.getDomain());
mNovel.setMuluUrl(mSite.getMuluUrl());
2019-04-07 23:49:08 +08:00
mNovel.update(mNovel.getId());
2019-04-03 18:09:00 +08:00
}
2019-04-06 23:04:42 +08:00
public void getTargetSites(){
2019-04-25 02:01:18 +08:00
Log.d(TAG, "prepare book: getTargetSites" );
2019-04-06 23:04:42 +08:00
BookSubscribe.getNovelSites(mNovel.getNovelId(),new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() {
@Override
public void onSuccess(String result) {
//成功
try {
2019-04-16 23:11:00 +08:00
Log.d(TAG, String.format("prepare book %s get target sites done.thread %s",mNovel.getName(),Thread.currentThread().getName()) );
2019-04-06 23:04:42 +08:00
NovelSites nvs = (NovelSites) gson.fromJson(result,NovelSites.class);
//pageFactory.prepareBook(mNovel,nvs, BookActivity.this);
setNovelSites(nvs);
2019-04-15 23:26:24 +08:00
2019-04-06 23:04:42 +08:00
} catch ( Exception e) {
2019-04-16 23:11:00 +08:00
Log.d(TAG, String.format("prepare book %s get target sites fail.thread %s ,msg %s",mNovel.getName(),Thread.currentThread().getName(),e.getMessage()) );
Log.e(TAG, "prepare book fail", e);
2019-04-06 23:04:42 +08:00
e.printStackTrace();
}
2019-04-07 23:49:08 +08:00
// Toast.makeText(mContext,"getMuluInfo 请求成功 " ,Toast.LENGTH_SHORT).show();
2019-04-06 23:04:42 +08:00
}
@Override
public void onFault(String errorMsg) {
2019-04-25 02:01:18 +08:00
Log.d(TAG, String.format("prepare book %s get target sites fail.thread %s ,msg %s",mNovel.getName(),Thread.currentThread().getName(),errorMsg) );
2019-04-06 23:04:42 +08:00
//失败
2019-04-07 23:49:08 +08:00
// Toast.makeText(mContext,"getMuluInfo 请求失败"+errorMsg,Toast.LENGTH_SHORT).show();
2019-04-06 23:04:42 +08:00
}
2019-04-07 23:49:08 +08:00
},null));
2019-04-06 23:04:42 +08:00
}
2019-04-05 23:59:31 +08:00
private void getSiteRule() {
mSiteRule = null;
BookSubscribe.getSiteRule(mSite.getDomain(),new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() {
@Override
public void onSuccess(String result) {
Log.d(TAG, "prepare book siteRule:" +result);
2019-04-05 23:59:31 +08:00
//成功
SiteRule sr= new SiteRule();
try {
sr = (SiteRule) gson.fromJson(result, SiteRule.class);
}catch (Exception e){
Log.e(TAG, "prepare book error on gson: ", e);
}
2019-04-05 23:59:31 +08:00
List<SiteRule> srs = LitePal.where("domain=?",sr.getDomain()).limit(1).find(SiteRule.class);
long id = srs.size()==1 ?srs.get(0).getId() :0;
if(id>0 ){
sr.update(id);
// mSiteRule =LitePal.find(SiteRule.class,id);
}else
{
sr.save();
}
mSiteRule =sr;
2019-04-06 23:04:42 +08:00
setSiteInfo();
Log.d(TAG, String.format("prepare book %s 目录正则表达式下载完成,开始读章节信息. muluRegex size %s, thread %s ",mNovel.getName(),mSiteRule.getChapterUrlRegexOnMulu().length, Thread.currentThread().getName()) );
2019-04-15 23:26:24 +08:00
2019-04-10 22:19:06 +08:00
Log.d(TAG, String.format("目录正则表达式下载完成,开始读取章节信息") );
if(mSiteRule.getChapterUrlRegexOnMulu().length>0) {
mMuluStatus = MuluStatus.isDownloading;
long startTime= new Date().getTime();
Log.d(TAG,String.format("prepare book loadChapts----start download %s,maxAge %s, 目录 from %s", mNovel.getName() ,mNovel.getMaxAge() ,mSite.getMuluUrl() ));
new Thread(){
@Override
public void run() {
Log.d(TAG, "changing Source: to get site rule");
String[] chaps = new String[0];
try {
JSONObject siteJson = new JSONObject(result);
chaps = NovelParseUtil.getChapters(mSite.getMuluUrl(), siteJson);
if (chaps != null)
for (String s : chaps) {
Log.d(TAG, "prepare book readChaptersAsync: chapt: " + s);
}
2019-04-05 23:59:31 +08:00
} catch (JSONException e) {
Log.e(TAG, "prepare book error on parese :", e);
}
2019-04-05 23:59:31 +08:00
if (chaps == null || chaps.length == 0) {
readChaptersAsync();
}else
{
Log.d(TAG,String.format("prepare book loadChapts----end download %s 目录, 目录数量 %s, cost %s", mNovel.getName() , mChapters.size(), new Date().getTime() -startTime ));
mMuluStatus = MuluStatus.isDone;
Log.d(TAG, String.format("prepare book %s 章节信息完成.",mNovel.getName()) );
}
}
}.start();
}else{
readChaptersAsync();
}
2019-04-05 23:59:31 +08:00
}
@Override
public void onFault(String errorMsg) {
//失败
2019-04-06 23:04:42 +08:00
Log.d(TAG,"error on get sitRule: "+errorMsg);
2019-04-05 23:59:31 +08:00
}
},mContext));
2019-04-06 23:04:42 +08:00
/*
if(mSiteRule==null && mSite!=null) {
List<SiteRule> srs = LitePal.where("domain=?", mSite.getDomain()).find(SiteRule.class);
if (srs.size() > 0) {
mSiteRule = srs.get(0);
}
}*/
2019-04-05 23:59:31 +08:00
2019-04-03 18:09:00 +08:00
}
2019-04-02 17:41:53 +08:00
public void setChapterNo(int chapterNo) {
this.chapterNo = chapterNo;
2019-04-15 23:26:24 +08:00
/*
if(chapterNo <= mChapters.size()) {
this.chapterNo = chapterNo;
}else{
Log.d(TAG, String.format("setChapterNo: wrong chapno for book %s,site %s,total chapts %s,chaptNo %s" ,mNovel.getName(),mNovel.getDomain(),getChapters().size(),chapterNo));
}
*/
2019-04-02 17:41:53 +08:00
}
public int getChapterNo() {
2019-04-15 23:26:24 +08:00
if(chapterNo > mChapters.size()){
2019-04-25 02:01:18 +08:00
Log.d(TAG, String.format(" prepare book getChapterNo ,chapterNo %s, getChapters().size() %s " ,chapterNo , mChapters.size()) );
2019-04-15 23:26:24 +08:00
chapterNo =1;
}
2019-04-25 02:01:18 +08:00
Log.d(TAG, String.format(" prepare book getChapterNo ,chapterNo %s, getChapters().size() %s " ,chapterNo , mChapters.size()) );
2019-04-02 17:41:53 +08:00
return chapterNo;
}
private int chapterNo;//当前章节
public String getLineBreakChar(){
return "\n";
}
public BookUtil(){
checkAndCreateDir(storagePath);
checkAndCreateDir(chapterPath);
checkAndCreateDir(cachedPath);
2019-04-05 23:59:31 +08:00
}
2019-04-15 23:26:24 +08:00
public boolean isBusy() {
return false;
}
2019-04-26 23:33:17 +08:00
private long tmpChaptLen=0;
public void setTmpChaptLen(long tmpChaptLen) {
this.tmpChaptLen = tmpChaptLen;
}
2019-04-15 23:26:24 +08:00
2019-04-18 17:19:42 +08:00
private boolean isChangeSource =false;
private int mChangeChapId;
private String mChangeTitle;
public void changeSource(String domain,int chapId,String chapTitle) {
Log.d(TAG, String.format("changing Source: target domain %s chaptId %s, chapt title %s ",domain,chapId,chapTitle) );
if(mSite.getDomain().equals(domain)){ //当前源
Log.d(TAG, "changing Source: same site with original " + domain);
return;
}
2019-04-26 23:33:17 +08:00
this.muluRetryCount=0;
this.downloadStatus = DownloadStatus.notStart;
chaptDownStatus.clear();
chaptCache.clear();
2019-04-18 17:19:42 +08:00
mChangeChapId = chapId;
mChangeTitle =chapTitle;
for (Site site:mNovelSites.getSites() ) {
if(site.getDomain().equals(domain)){
mSite = site;
break;
}
}
setSiteInfo();
2019-04-21 10:57:20 +08:00
2019-04-18 17:19:42 +08:00
isChangeSource = true;
mChapters.clear();
getSiteRule();
BookTask btsk = new BookTask();
btsk.execute( domain, chapId+"", chapTitle);
}
public String getSite() {
return mSite !=null? mSite.getDomain():"";
}
2019-04-25 02:01:18 +08:00
public boolean chaptCached(int num) {
File f = new File(fileChapterName(num));
return f.exists();
}
2019-04-26 23:33:17 +08:00
2019-04-18 17:19:42 +08:00
private class BookTask extends AsyncTask<String,Void,Boolean> {
private String domain;
private int chapId;
private String chapTitle;
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
Log.d("onPostExecute",isCancelled() + "");
if (isCancelled()){
return;
}
if (result) {
Log.d(TAG, "changing Source:successed get chapters for " + mSite.getDomain() );
int chId=chapterNo;
String title ="";
if( mChapters.size() >= mChangeChapId && mChapters.get(mChangeChapId-1)!=null ){
title= mChapters.get(mChangeChapId-1).getChapterName();
Log.d(TAG, "changing Source:chapter name in new site " + title );
}
if(title.equals(mChangeTitle)) {
Log.d(TAG, "changing Source:successed find chapter by original chaptId " + mChangeChapId + ":" + mChangeTitle);
chId = mChangeChapId;
}
else {
int i = 1;
for (Chapter chapter : mChapters) {
Log.d(TAG, "changing Source: finding chapter " + i + ":" + chapter.getChapterName());
if (chapter.getChapterName().equals(mChangeTitle)) {
Log.d(TAG, "changing Source:successed find chapter by original title " + i + ":" + mChangeTitle);
chId = i;
break;
}
i++;
}
}
chId = chId <= mChapters.size() ? chId: mChapters.size();
Log.d(TAG, "changing Source: to open chapter with new site source " + chId + " : "+ mChangeTitle );
pagefactory.changeChapter(chId);
Toast.makeText(mContext,"换源成功",Toast.LENGTH_LONG).show();
}else{
Log.d(TAG, "changing Source: failed " );
}
}
@Override
protected Boolean doInBackground(String... params) {
domain = params[0];
chapId = Integer.parseInt( params[1]);
chapTitle = params[2];
int splet =0;
while(isChangeSource){
try {
Thread.sleep(50);
splet++;
Log.d(TAG, String.format("changing Source slept %s,isChangeSource %s ", splet, isChangeSource ));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return true;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
/**
* 新线程换源 handler 有问题
* @param domain
* @param chapId
* @param chapTitle
*/
public void changeSourceNewThread(String domain,int chapId,String chapTitle) {
Log.d(TAG, String.format("changing Source: target domain %s chaptId %s, chapt title %s ",domain,chapId,chapTitle) );
if(mSite.getDomain().equals(domain)){ //当前源
Log.d(TAG, "changing Source: same site with original " + domain);
// return;
}
mChangeChapId = chapId;
mChangeTitle =chapTitle;
for (Site site:mNovelSites.getSites() ) {
if(site.getDomain().equals(domain)){
mSite = site;
break;
}
}
setSiteInfo();
// showProgressDialog();
isChangeSource = true;
new Thread(){
@Override
public void run() {
Log.d(TAG, "changing Source: to get site rule" );
getSiteRule();
}
}.start();
/*
while(isChangeSource){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
new Thread(){
@Override
public void run() {
Log.d(TAG, "changing Source: to get site rule" );
getSiteRule();
}
}.start();*/
}
2019-04-05 23:59:31 +08:00
enum MuluStatus{
isDownloading,
isDone,
failed
}
2019-04-21 10:57:20 +08:00
/*private void showProgressDialog(String title,boolean canBreak) {
2019-04-05 23:59:31 +08:00
if ( null == progressDialog) {
progressDialog =new ProgressDialog(mContext);
2019-04-18 17:19:42 +08:00
2019-04-05 23:59:31 +08:00
}
2019-04-18 17:19:42 +08:00
progressDialog.setMessage(title);
progressDialog.setCancelable(canBreak);
2019-04-05 23:59:31 +08:00
progressDialog.show();
2019-04-07 23:49:08 +08:00
// progressDialog.show(mContext,"网络不给力","正努力加载",false,true);
2019-04-05 23:59:31 +08:00
}
private void dismissProgressDialog() {
if ( null != progressDialog) {
progressDialog.dismiss();
}
2019-04-02 17:41:53 +08:00
}
2019-04-21 10:57:20 +08:00
*/
2019-04-02 17:41:53 +08:00
private void checkAndCreateDir(String path){
File file = new File(path);
if (!file.exists()){
file.mkdir();
}
}
2019-04-05 23:59:31 +08:00
2019-04-23 22:45:08 +08:00
int muluRetryCount =0;
2019-04-05 23:59:31 +08:00
void readChaptersAsync( ) {
2019-04-26 00:31:07 +08:00
if(mSite==null ||mSiteRule ==null){
Log.d(TAG,String.format("prepare book loadChapts failed---- %s ,mSite is null? %s ,mSiteRule ==null ? %s", mNovel.getName() ,mSite==null,mSiteRule ==null ));
return;
}
2019-04-05 23:59:31 +08:00
String url = mSite.getMuluUrl();
Request request = getTagRequest(url,mNovel.getMaxAge());
2019-04-05 23:59:31 +08:00
mMuluStatus = MuluStatus.isDownloading;
long startTime= new Date().getTime();
Log.d(TAG,String.format("prepare book loadChapts----start download %s,maxAge %s, 目录 from %s", mNovel.getName() ,mNovel.getMaxAge() ,url ));
2019-04-05 23:59:31 +08:00
2019-04-23 22:45:08 +08:00
/* if(muluRetryCount<3){
muluRetryCount++;
return;
}
if(muluRetryCount>=3) {
return;
}*/
2019-04-05 23:59:31 +08:00
HttpMethods.getOkClient().newCall(request).enqueue(new Callback() {
2019-04-05 23:59:31 +08:00
@Override
public void onFailure(Call call, IOException e) {
2019-04-23 22:45:08 +08:00
// Log.d(TAG, "onFailure: " + e.getMessage());
Log.e(TAG, "prepare book loadChapts---- failed: ", e);
Log.d(TAG, String.format("prepare book loadChapts---- failed %s 目录 from %s", mNovel.getName(), url));
2019-04-10 22:19:06 +08:00
2019-04-18 17:19:42 +08:00
handler.sendEmptyMessage(3);
2019-04-16 23:11:00 +08:00
//TODO 如果是取消了访问,则返回
2019-04-23 22:45:08 +08:00
if (e.toString().contains("closed") || e.getMessage().contains("Canceled")) {
Log.d(TAG, String.format("prepare book loadChapts---- canceled %s 目录 from %s", mNovel.getName(), url));
2019-04-18 23:34:19 +08:00
return;
}
2019-04-23 22:45:08 +08:00
mMuluStatus = MuluStatus.failed;
2019-04-25 02:01:18 +08:00
if (muluRetryCount < Constants.retryCnt) {
2019-04-23 22:45:08 +08:00
try {
Thread.sleep(50);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
muluRetryCount++;
Log.d(TAG,String.format("prepare book loadChapts----failed, retrying count %s",muluRetryCount ));
readChaptersAsync();
}
if (mNovelSites.getSites().length == 1) { //仅有一个rule,且失败了
// mMuluStatus = MuluStatus.failed;
2019-04-18 23:34:19 +08:00
2019-04-05 23:59:31 +08:00
return;
}
//try next site
2019-04-23 22:45:08 +08:00
for (Site st : mNovelSites.getSites()) {
if (!st.getDomain().equals(mSite.getDomain())) {
mSite = st;
break;
}
}
muluRetryCount=0;
// readChaptersAsync();
getSiteRule();
}
2019-04-05 23:59:31 +08:00
@Override
public void onResponse(Call call, Response response){
ResponseBody body = response.body();
2019-04-23 22:45:08 +08:00
2019-04-06 23:04:42 +08:00
if(response.code()!=200){
2019-04-23 22:45:08 +08:00
Log.d(TAG,String.format("prepare book loadChapts----failed, %s 目录 from %s,return code %s", mNovel.getName() ,url,response.code() ));
2019-04-18 17:19:42 +08:00
handler.sendEmptyMessage(3);
2019-04-06 23:04:42 +08:00
mMuluStatus = MuluStatus.failed;
2019-04-25 02:01:18 +08:00
if(muluRetryCount <Constants.retryCnt){
2019-04-23 22:45:08 +08:00
Log.d(TAG,String.format("prepare book loadChapts----failed, response code %s retrying count %s",response.code(), muluRetryCount ));
muluRetryCount++;
readChaptersAsync();
}
2019-04-06 23:04:42 +08:00
return;
}
2019-04-23 22:45:08 +08:00
muluRetryCount =0;
2019-04-05 23:59:31 +08:00
if (body != null) {
2019-04-16 23:11:00 +08:00
Log.d(TAG, String.format("prepare book %s 章节信息读取成功.thread %s",mNovel.getName(),Thread.currentThread().getName()) );
2019-04-05 23:59:31 +08:00
try {
String bodyStr = body.string();
2019-04-10 22:19:06 +08:00
// Log.d(TAG, "onResponse: " +bodyStr);
// Log.d(TAG,String.format("loadChaptContent----end download %s 目录, 目录数量 %s, cost %s", mNovel.getName() , mChapters.size(), new Date().getTime() -startTime ));
// long startTime2= new Date().getTime();
2019-04-15 23:26:24 +08:00
buildChapters(bodyStr,url);
2019-04-23 22:45:08 +08:00
Log.d(TAG,String.format("prepare book loadChapts----end download %s 目录, 目录数量 %s, cost %s", mNovel.getName() , mChapters.size(), new Date().getTime() -startTime ));
2019-04-05 23:59:31 +08:00
mMuluStatus = MuluStatus.isDone;
2019-04-15 23:26:24 +08:00
Log.d(TAG, String.format("prepare book %s 章节信息完成.",mNovel.getName()) );
2019-04-03 18:09:00 +08:00
2019-04-05 23:59:31 +08:00
} catch (IOException e) {
e.printStackTrace();
}finally {
body.close();
2019-04-18 17:19:42 +08:00
handler.sendEmptyMessage(3);
2019-04-05 23:59:31 +08:00
}
}
}
});
}
2019-04-15 23:26:24 +08:00
void buildChapters( String content ,String url){
Log.d(TAG, "buildChapters: " +content);
2019-04-26 00:31:07 +08:00
if(mSite==null ||mSiteRule ==null){
Log.d(TAG,String.format("prepare book buildChapters failed---- %s ,mSite is null? %s ,mSiteRule ==null ? %s", mNovel.getName() ,mSite==null,mSiteRule ==null ));
return;
}
2019-04-05 23:59:31 +08:00
try {
JSONObject siteJson = new JSONObject();
siteJson.put("chapterUrlPattern", mSiteRule.getChapterUrlPattern());
2019-04-20 00:26:49 +08:00
/* if(mSiteRule.getDomain().equals("qu.la")){
siteJson.put("chapterUrlRegexOnMulu", "<dd> <a[^>]*href=\"(/book/[\\d]+/[\\d]+\\.html)\">([^<]+)</a></dd>");
}else{
siteJson.put("chapterUrlRegexOnMulu", mSiteRule.getChapterUrlRegexOnMulu());
}*/
siteJson.put("chapterUrlRegexOnMulu", "");
2019-04-20 00:26:49 +08:00
//
2019-04-05 23:59:31 +08:00
mChapters = NovelParseUtil.getChapters(mSite.getDomain(),url, content, siteJson);
Log.d(TAG,String.format("mulu on Site %s download status %s",mSite.getDomain(),mMuluStatus));
if( mChapters.size()> mNovel.getChaptCnt()){
mNovel.setChaptCnt(mChapters.size());
mNovel.update(mNovel.getId());
}
2019-04-05 23:59:31 +08:00
} catch (JSONException e) {
// } catch (JSONException | IOException e) {
Log.e(TAG,String.format("prepare book, mulu on Site %s download status %s",mSite.getDomain(),mMuluStatus),e);
2019-04-05 23:59:31 +08:00
e.printStackTrace();
} finally {
// result.close();
// if (result2 != null) result2.close();
}
2019-04-02 17:41:53 +08:00
}
2019-04-05 23:59:31 +08:00
2019-04-02 17:41:53 +08:00
private void cleanCacheFile(){
File file = new File(cachedPath );
if (!file.exists()){
file.mkdir();
}else{
File[] files = file.listFiles();
for (int i = 0; i < files.length;i++){
files[i].delete();
}
}
file = new File(getChapterPath());
if (!file.exists()){
file.mkdir();
}else{
File[] files = file.listFiles();
for (int i = 0; i < files.length;i++){
files[i].delete();
}
}
}
public int next(boolean back){
position += 1;
2019-04-26 23:33:17 +08:00
if (position > tmpChaptLen){
position = tmpChaptLen;
2019-04-02 17:41:53 +08:00
return -1;
}
char result = chaptCurrent(); //current();
if (back) {
position -= 1;
}
return result;
}
public char[] nextLine(){
2019-04-26 23:33:17 +08:00
if (position >= tmpChaptLen){
2019-04-02 17:41:53 +08:00
return null;
}
String line = "";
2019-04-26 23:33:17 +08:00
while (position < tmpChaptLen){
2019-04-02 17:41:53 +08:00
int word = next(false);
if (word == -1){
break;
}
char wordChar = (char) word;
if ((wordChar + "").equals("\n") ){// if ((wordChar + "").equals("\r") && (((char)next(true)) + "").equals("\n")){
// next(false);
break;
}
line += wordChar;
}
return line.toCharArray();
}
public char[] preLine(){
if (position <= 0){
return null;
}
String line = "";
while (position >= 0){
int word = pre(false);
if (word == -1){
break;
}
char wordChar = (char) word;
if ((wordChar + "").equals("\n") ){ // if ((wordChar + "").equals("\n") && (((char)pre(true)) + "").equals("\r")){
// pre(false); // /r/n ->/n 不需要再往前读一个字符了
// line = "\r\n" + line;
break;
}
line = wordChar + line;
}
return line.toCharArray();
}
public char chaptCurrent(){
2019-04-25 02:01:18 +08:00
// chapterNo = mChapters.size() < chapterNo ? 1 : chapterNo;
// Log.d(TAG, String.format(" prepare book chaptCurrent() ,chapterNo %s, getChapters().size() %s " ,chapterNo , mChapters.size()) );
2019-04-02 17:41:53 +08:00
char[] charArray = chaptChars(chapterNo);
2019-04-07 23:49:08 +08:00
2019-04-15 23:26:24 +08:00
int i = (int)position-1;
2019-04-20 00:26:49 +08:00
i = i< charArray.length? i:charArray.length-1;
2019-04-15 23:26:24 +08:00
return charArray[i];
2019-04-02 17:41:53 +08:00
}
public char current(){
// int pos = (int) (position % cachedSize);
// int cachePos = (int) (position / cachedSize);
int cachePos = 0;
int pos = 0;
int len = 0;
for (int i = 0;i < myArray.size();i++){
long size = myArray.get(i).getSize();
if (size + len - 1 >= position){
cachePos = i;
pos = (int) (position - len);
break;
}
len += size;
}
char[] charArray = block(cachePos);
return charArray[pos];
}
public int pre(boolean back){
position -= 1;
if (position < 0){
position = 0;
return -1;
}
char result = current();
if (back) {
position += 1;
}
return result;
}
public long getPosition(){
return position;
}
public void setPostition(long position){
this.position = position;
}
//缓存书本
private void cacheBook() throws IOException {
2019-04-03 18:09:00 +08:00
if (TextUtils.isEmpty(mNovel.getCharset())) {
2019-04-02 17:41:53 +08:00
m_strCharsetName = FileUtils.getCharset(bookPath);
if (m_strCharsetName == null) {
m_strCharsetName = "utf-8";
}
ContentValues values = new ContentValues();
values.put("charset",m_strCharsetName);
2019-04-03 18:09:00 +08:00
LitePal.update(Novel.class,values,mNovel.getId());
2019-04-02 17:41:53 +08:00
}else{
2019-04-03 18:09:00 +08:00
m_strCharsetName = mNovel.getCharset();
2019-04-02 17:41:53 +08:00
}
File file = new File(bookPath);
InputStreamReader reader = new InputStreamReader(new FileInputStream(file),m_strCharsetName);
int index = 0;
bookLen = 0;
2019-04-03 18:09:00 +08:00
mChapters.clear();
2019-04-02 17:41:53 +08:00
myArray.clear();
while (true){
char[] buf = new char[cachedSize];
int result = reader.read(buf);
if (result == -1){
reader.close();
break;
}
String bufStr = new String(buf);
// Log.e(TAG,String.format("缓存的内容是\n %s",bufStr));
bufStr = bufStr.replaceAll("\r\n","\n");
// bufStr = bufStr.replaceAll("\u3000\u3000+[ ]*","\u3000\u3000");
bufStr = bufStr.replaceAll("\n+\\s*","\n\u3000\u3000");// bufStr = bufStr.replaceAll("\r\n+\\s*","\r\n\u3000\u3000");
// bufStr = bufStr.replaceAll("\r\n[ {0,}]","\r\n\u3000\u3000");
// bufStr = bufStr.replaceAll(" ","");
bufStr = bufStr.replaceAll("\u0000","");
buf = bufStr.toCharArray();
bookLen += buf.length;
// Log.e(TAG,String.format("缓存的内容脱空格处理后\n %s",bufStr));
Cache cache = new Cache();
cache.setSize(buf.length);
cache.setData(new WeakReference<char[]>(buf));
// bookLen += result;
myArray.add(cache);
// myArray.add(new WeakReference<char[]>(buf));
// myArray.set(index,);
Log.e(TAG,String.format("缓存的内容写入文件\n %s",fileName(index)));
Log.e(TAG,"---------------------------------------------------------------------------------------------------------");
try {
File cacheBook = new File(fileName(index));
if (!cacheBook.exists()){
cacheBook.createNewFile();
}
final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileName(index)), "UTF-16LE"); // UTF-16LE 比 utf-8 文件小
writer.write(buf);
writer.close();
} catch (IOException e) {
throw new RuntimeException("Error during writing " + fileName(index));
}
index ++;
}
chaptId =0; //初始化导入的chapid
int endchp = myArray.size()>3 ?3:myArray.size();
getChapter(1,3); //先导入2个部分 立即进行阅读
new Thread(){
@Override
public void run() {
getChapter(4,myArray.size()); //剩余部分后台导入
}
}.start();
}
int chaptId =0;
//获取章节
public synchronized void getChapter(int startblk,int endblk){
if(endblk <startblk) return;
try {
long size = 0;
String title ="";
long start =0;
int chaptFileId=0;
2019-04-03 16:21:00 +08:00
Chapter bookChapter = null;
2019-04-02 17:41:53 +08:00
OutputStreamWriter writer = null;
for (int i = startblk-1; i < endblk; i++) {
char[] buf = block(i);
String bufStr = new String(buf);
String[] paragraphs = bufStr.split(lineBreakChar); // String[] paragraphs = bufStr.split("\r\n");
for (String str : paragraphs) {
// if (str.length() <= 30 && (str.matches(".*第.{1,8}章.*") || str.matches(".*第.{1,8}节.*"))) {
if(isChapterTitle(str)) {
if(title.length()==0) {
title = str;
start =0;
}else {
start = size;
title = str;
}
if(bookChapter!=null) {
bookChapter.setLength((int)(size - start));
bookChapter.setChapterPath(fileChapterName(chaptId) );
bookChapter.update(bookChapter.getId());
2019-04-03 18:09:00 +08:00
mChapters.add(bookChapter);
2019-04-02 17:41:53 +08:00
}
2019-04-03 16:21:00 +08:00
bookChapter = new Chapter();
2019-04-03 18:09:00 +08:00
bookChapter.setNovelId(mNovel.getId());
2019-04-03 16:21:00 +08:00
bookChapter.setNovelChapterStartPos(start);
2019-04-02 17:41:53 +08:00
bookChapter.setChapterName(str.replaceAll("###",""));
2019-04-03 16:21:00 +08:00
bookChapter.setNovelPath(bookPath);
2019-04-02 17:41:53 +08:00
bookChapter.save();
int id= bookChapter.getId();
Log.d(TAG,str + " chaptId is " + id);
File chapter = new File(fileChapterName(++chaptId));
if (!chapter.exists()){
chapter.createNewFile();
}
if(writer!=null) {
writer.close();
}
writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(chaptId)), charachterType);
}
if(writer==null) {
2019-04-03 16:21:00 +08:00
bookChapter = new Chapter();
2019-04-03 18:09:00 +08:00
bookChapter.setNovelId(mNovel.getId());
2019-04-03 16:21:00 +08:00
bookChapter.setNovelChapterStartPos(start);
2019-04-02 17:41:53 +08:00
bookChapter.setChapterName(str.replaceAll("###",""));
2019-04-03 16:21:00 +08:00
bookChapter.setNovelPath(bookPath);
2019-04-02 17:41:53 +08:00
bookChapter.save();
writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(++chaptId)), charachterType); //序
}
str+=lineBreakChar;
writer.write(str);
// Log.e(TAG,String.format("当前行\n %s",str));
if (str.contains("\u3000\u3000")) {
size += str.length() + 2;
}else if (str.contains("\u3000")){
size += str.length() + 1;
}else {
size += str.length();
}
/*
2019-04-03 16:21:00 +08:00
Chapter bookChapter = new Chapter();
2019-04-03 18:09:00 +08:00
bookChapter.setBookId(mNovel.getId());
2019-04-02 17:41:53 +08:00
bookChapter.setBookChapterStartPos(start);
bookChapter.setChapterName(title.replaceAll("###",""));
bookChapter.setBookpath(bookPath);
bookChapter.setLength((int)(size - start));
bookChapter.save();
int id= bookChapter.getId();
Log.d(TAG,str + " chaptId is " + id);
2019-04-03 18:09:00 +08:00
mChapters.add(bookChapter);
2019-04-02 17:41:53 +08:00
*/
}
}
if(writer!=null) {
writer.close();
}
if(bookChapter!=null) {
bookChapter.setLength((int)(size - start));
bookChapter.setChapterPath(fileChapterName(chaptId) );
bookChapter.update(bookChapter.getId());
2019-04-03 18:09:00 +08:00
mChapters.add(bookChapter);
2019-04-02 17:41:53 +08:00
}
}catch (Exception e){
e.printStackTrace();
}
}
void createChapContent(){
}
2019-04-05 23:59:31 +08:00
public List<Chapter> getmChapters(){
2019-04-03 18:09:00 +08:00
return mChapters;
2019-04-02 17:41:53 +08:00
}
public long getBookLen(){
return bookLen;
}
protected String fileName(int index) {
2019-04-05 23:59:31 +08:00
return cachedPath + mNovel.getName() + index ;
2019-04-02 17:41:53 +08:00
}
2019-04-18 23:34:19 +08:00
public String fileChapterName(int chaptId ) {
2019-04-07 23:49:08 +08:00
if(!TextUtils.isEmpty(mNovel.getDomain())){
2019-04-02 17:41:53 +08:00
2019-04-06 23:04:42 +08:00
return getChapterPath() +mNovel.getDomain()+"/"+ chaptId ;
2019-04-05 23:59:31 +08:00
}
2019-04-02 17:41:53 +08:00
return getChapterPath() + chaptId ;
}
String getChapterPath(){
2019-04-05 23:59:31 +08:00
File file = new File(chapterPath +mNovel.getId());
if(!file.exists()){
file.mkdir();
}
2019-04-03 18:09:00 +08:00
return chapterPath +mNovel.getId()+"/";
2019-04-02 17:41:53 +08:00
}
//获取书本缓存
public char[] block(int index) {
if (myArray.size() == 0){
return new char[1];
}
char[] block = myArray.get(index).getData().get();
if (block == null) {
try {
File file = new File(fileName(index));
int size = (int)file.length();
if (size < 0) {
throw new RuntimeException("Error during reading " + fileName(index));
}
block = new char[size / 2];
InputStreamReader reader =
new InputStreamReader(
new FileInputStream(file),
"UTF-16LE"
);
if (reader.read(block) != block.length) {
throw new RuntimeException("Error during reading " + fileName(index));
}
reader.close();
} catch (IOException e) {
throw new RuntimeException("Error during reading " + fileName(index));
}
Cache cache = myArray.get(index);
cache.setData(new WeakReference<char[]>(block));
// myArray.set(index, new WeakReference<char[]>(block));
}
return block;
}
2019-04-05 23:59:31 +08:00
boolean isDownloadChapt =false;
2019-04-07 23:49:08 +08:00
synchronized boolean getDownloadStatus(){
return isDownloadChapt;
}
synchronized void setDownloadFlag(boolean flag){
2019-04-05 23:59:31 +08:00
isDownloadChapt = flag;
2019-04-25 02:01:18 +08:00
Log.d(TAG,String.format("set download flat",isDownloadChapt) );
2019-04-05 23:59:31 +08:00
}
2019-04-18 17:19:42 +08:00
public ChangeSource pagefactory;
Handler handler = new Handler() {
2019-04-05 23:59:31 +08:00
@Override
public void handleMessage(Message msg) {
int wt = msg.what;
2019-04-18 17:19:42 +08:00
handlerMsg(msg);
2019-04-07 23:49:08 +08:00
2019-04-05 23:59:31 +08:00
}
};
2019-04-18 17:19:42 +08:00
void handlerMsg(Message msg){
if (msg.what == 123) {
isDownloadChapt =true;
2019-04-25 02:01:18 +08:00
Log.d(TAG,String.format("handler msg, download %s",isDownloadChapt) );
2019-04-18 17:19:42 +08:00
}else if(msg.what==1){
isDownloadChapt =true;
// Toast.makeText(mContext,"网络错误",Toast.LENGTH_LONG).show();
}else if(msg.what==3){ //change source
isChangeSource =false;
Log.d(TAG, "changing Source:successed get chapters for " + mSite.getDomain() );
/*if(isChangeSource){
Log.d(TAG, "changing Source:successed get chapters for " + mSite.getDomain() );
isChangeSource =false;
int chapId=chapterNo;
if( mChapters.size() >= mChangeChapId && mChapters.get(mChangeChapId-1)!=null ){
String title = mChapters.get(mChangeChapId-1).getChapterName();
Log.d(TAG, "changing Source:chapter name in new site " + title );
if(title.equals(mChangeTitle)) {
Log.d(TAG, "changing Source:successed find chapter by original chaptId " + mChangeChapId + ":" + mChangeTitle);
chapId = mChangeChapId;
}
}else{
int i =1;
for (Chapter chapter : mChapters) {
if (chapter.getChapterName().equals(mChangeTitle)) {
Log.d(TAG, "changing Source:successed find chapter by original title " +i + ":"+ mChangeTitle );
chapId = i;
break;
}
i++;
}
}
chapId = chapId <= mChapters.size() ? chapId: mChapters.size();
Log.d(TAG, "changing Source: to open chapter with new site source " + chapId + " : "+ mChangeTitle );
pagefactory.changeChapter(chapId);
}
*/
}
}
2019-04-26 23:33:17 +08:00
2019-04-08 23:16:20 +08:00
private enum DownloadStatus{
notStart,
downloading,
failure,
success
}
2019-04-18 17:19:42 +08:00
public boolean isChapterContentExist(int index) {
char[] block = null;
if (chaptCache.containsKey(Integer.valueOf(index))) {
block = chaptCache.get(index).getData().get();
}
if (block == null) {
// cleanCacheFile(); //to remove
File file = new File(fileChapterName(index));
if (!file.exists()) {
2019-04-21 10:57:20 +08:00
2019-04-18 17:19:42 +08:00
new Thread(){
@Override
public void run() {
try {
loadChaptContent(index);
} catch (JSONException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
return false;
}
}
return true;
}
2019-04-02 17:41:53 +08:00
//获取chapter 缓存
2019-04-15 23:26:24 +08:00
public char[] chaptChars(final int index) {
2019-04-26 23:33:17 +08:00
// Log.d(TAG, String.format("prepare book begin to load content for chapter %s ------------------------------------------------------------------------->", index));
2019-04-02 17:41:53 +08:00
char[] block=null;
if(chaptCache.containsKey(Integer.valueOf(index))) {
block = chaptCache .get(index).getData().get();
}
2019-04-25 02:01:18 +08:00
// Log.d(TAG, String.format("prepare book begin to load content for chapter %s", index));
2019-04-02 17:41:53 +08:00
if (block == null) {
2019-04-05 23:59:31 +08:00
// cleanCacheFile(); //to remove
2019-04-02 17:41:53 +08:00
try {
File file = new File(fileChapterName(index));
2019-04-25 02:01:18 +08:00
Log.d(TAG, String.format("prepare book begin to load content for chapter %s,file exists?%s", index,file.exists()));
2019-04-23 22:45:08 +08:00
if (!file.exists()) {
2019-04-25 02:01:18 +08:00
Log.d(TAG, String.format("prepare book loadChapts---- %s, 目录数量 %s, MuluStatus %s , mChapters.size() %s, thread %s", mNovel.getName(), mChapters.size(), mMuluStatus
, mChapters.size()
, Thread.currentThread().getName()));
2019-04-03 18:09:00 +08:00
2019-04-23 22:45:08 +08:00
if (mMuluStatus == null) {
Log.d(TAG, String.format("prepare book loadChapts---- 还未有目录信息,出错了 %s 目录, 目录数量 %s, MuluStatus %s ,thread %s", mNovel.getName(), mChapters.size(), mMuluStatus, Thread.currentThread().getName()));
// getTargetSites();
2019-04-15 23:26:24 +08:00
}
2019-04-10 22:19:06 +08:00
int slept = 0;
2019-04-23 22:45:08 +08:00
while (NetUtil.isNetworkConnected() && slept < 100 && mMuluStatus == MuluStatus.isDownloading) {
2019-04-10 22:19:06 +08:00
try {
Thread.sleep(50);
slept++;
2019-04-23 22:45:08 +08:00
Log.d(TAG, String.format("prepare book loadChapts----等待中 %s 目录, 目录数量 %s, slept %s, MuluStatus %s", mNovel.getName(), mChapters.size(), slept, mMuluStatus));
2019-04-15 23:26:24 +08:00
2019-04-10 22:19:06 +08:00
} catch (InterruptedException e) {
e.printStackTrace();
}
}
2019-04-25 02:01:18 +08:00
if (!NetUtil.isNetworkConnected() || muluRetryCount >= Constants.retryCnt && (mChapters == null || mChapters.size() == 0)) {
Log.d(TAG, String.format("prepare book loadChapts----超时。。。或出错了 %s 目录, 目录数量 %s, slept %s, MuluStatus %s,thread %s", mNovel.getName(), mChapters.size(), slept, mMuluStatus, Thread.currentThread().getName()));
2019-04-20 00:26:49 +08:00
String error = "网络不给力";
2019-04-23 22:45:08 +08:00
return error.toCharArray();
2019-04-06 23:04:42 +08:00
}
2019-04-25 02:01:18 +08:00
Log.d(TAG, String.format("prepare book loadChaptContent----start %s", new Date().toString()));
2019-04-18 17:19:42 +08:00
2019-04-03 18:09:00 +08:00
2019-04-25 02:01:18 +08:00
Log.d(TAG, String.format("prepare book isDownloadChapt: %s", isDownloadChapt));
2019-04-06 23:04:42 +08:00
2019-04-23 22:45:08 +08:00
if (!chaptDownStatus.containsKey(Integer.valueOf(index))) {
chaptDownStatus.put(index, DownloadStatus.downloading);
2019-04-25 02:01:18 +08:00
Log.d(TAG, String.format("prepare book put chaptDownStatus index %s,start to load chapcontent", index));
2019-04-07 23:49:08 +08:00
loadChaptContent(index);
}
2019-04-25 02:01:18 +08:00
Log.d(TAG, String.format(" prepare book loadChaptContent %s for downloading,isDownload %s chaptDownStatus %s, thread %s ",
index,getDownloadStatus(), chaptDownStatus.get(Integer.valueOf(index)), Thread.currentThread().getName()));
2019-04-07 23:49:08 +08:00
2019-04-23 22:45:08 +08:00
int maxSleep = 4500;
int slepttime = 0;
// while(!file.exists() && !getDownloadStatus()){//&& slepttime <maxSleep){
// while( !getDownloadStatus() && slepttime <maxSleep){
2019-04-25 02:01:18 +08:00
/* while (NetUtil.isNetworkConnected() && !getDownloadStatus() && chaptDownStatus.get(Integer.valueOf(index)) == DownloadStatus.downloading && slepttime < maxSleep) {
2019-04-05 23:59:31 +08:00
Thread.sleep(50);
2019-04-23 22:45:08 +08:00
slepttime += 50;
Log.d(TAG, String.format(" prepare book loadChaptContent slept %s for downloading,isDownload %s thread %s ", slepttime, getDownloadStatus(), Thread.currentThread().getName()));
2019-04-25 02:01:18 +08:00
}*/
while (!file.exists() && NetUtil.isNetworkConnected() && chaptDownStatus.get(Integer.valueOf(index)) == DownloadStatus.downloading && slepttime < maxSleep) {
Thread.sleep(50);
slepttime += 50;
Log.d(TAG, String.format(" prepare book loadChaptContent %s , slept %s for downloading,isDownload %s thread %s ",index, slepttime, getDownloadStatus(), Thread.currentThread().getName()));
2019-04-03 18:09:00 +08:00
}
2019-04-25 02:01:18 +08:00
Log.d(TAG, String.format("prepare book loadChaptContent slept %s for downloading ", slepttime));
2019-04-23 22:45:08 +08:00
2019-04-25 02:01:18 +08:00
if (chaptDownStatus.get(Integer.valueOf(index)) == DownloadStatus.failure) {
if (fileRetryCnt.containsKey(index)) {
fileRetryCnt.put(index, fileRetryCnt.get(index) + 1);
} else {
fileRetryCnt.put(index, 1);
}
Log.d(TAG, String.format("prepare book loadChaptContent %s, rertying count %s ",index, fileRetryCnt.get(index)));
if (fileRetryCnt.get(index) < Constants.retryCnt) {
Log.d(TAG, String.format("prepare book loadChaptContent ,rertying to download chapt %s ", index));
loadChaptContent(index);
2019-04-21 10:57:20 +08:00
2019-04-25 02:01:18 +08:00
}
}
2019-04-05 23:59:31 +08:00
}
2019-04-07 23:49:08 +08:00
2019-04-25 02:01:18 +08:00
Log.d(TAG, String.format(" prepare book %s, file.exists()? %s", file.getPath(), file.exists()));
if (!file.exists()) {
String error = "下载内容失败";
if( !NetUtil.isNetworkConnected()){
error = "连不上网络";
}
Log.d(TAG, String.format("prepare book loadChaptContent retrying " ));
// return chaptChars( index);
2019-04-23 22:45:08 +08:00
return error.toCharArray();
2019-04-05 23:59:31 +08:00
}
2019-04-23 22:45:08 +08:00
if (mChapters.size() > index && NetUtil.isNetworkConnected()) {
2019-04-05 23:59:31 +08:00
2019-04-23 22:45:08 +08:00
if (!chaptDownStatus.containsKey(index + 1) || chaptDownStatus.get(index + 1).equals(DownloadStatus.failure)) {
2019-04-05 23:59:31 +08:00
2019-04-03 18:09:00 +08:00
2019-04-23 22:45:08 +08:00
File file2 = new File(fileChapterName(index + 1));
if (!file2.exists()) {
Log.d(TAG, String.format(" prepare book to load next chapt %s,down status %s ", index + 1, chaptDownStatus.get(index + 1)));
chaptDownStatus.put(index + 1, DownloadStatus.downloading);
loadChaptContent(index + 1);
}
}
2019-04-02 17:41:53 +08:00
}
2019-04-23 22:45:08 +08:00
if (index > 1 && index - 1 < mChapters.size() && NetUtil.isNetworkConnected()) {
2019-04-20 00:26:49 +08:00
2019-04-23 22:45:08 +08:00
if (!chaptDownStatus.containsKey(index - 1) || chaptDownStatus.get(index - 1).equals(DownloadStatus.failure)) {
File file2 = new File(fileChapterName(index - 1));
2019-04-20 00:26:49 +08:00
2019-04-23 22:45:08 +08:00
if (!file2.exists()) {
Log.d(TAG, String.format(" prepare book to load pre chapt %s,down status %s ", index - 1, chaptDownStatus.get(index - 1)));
chaptDownStatus.put(index - 1, DownloadStatus.downloading);
loadChaptContent(index - 1);
}
2019-04-02 17:41:53 +08:00
2019-04-23 22:45:08 +08:00
}
2019-04-20 00:26:49 +08:00
}
2019-04-02 17:41:53 +08:00
2019-04-23 22:45:08 +08:00
int size = (int) file.length();
2019-04-02 17:41:53 +08:00
if (size < 0) {
2019-04-23 22:45:08 +08:00
Log.e(TAG, "prepare book chaptChars: Error during reading"+ fileChapterName(index) );
// throw new RuntimeException("Error during reading " + fileChapterName(index));
2019-04-02 17:41:53 +08:00
}
block = new char[size / 2];
2019-04-23 22:45:08 +08:00
InputStreamReader reader = null;
try {
reader =
new InputStreamReader(
new FileInputStream(file),
charachterType
);
long l = reader.read(block);
if (reader.read(block) != block.length) {
// throw new RuntimeException("Error during reading " + fileChapterName(index));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
2019-04-02 17:41:53 +08:00
}
2019-04-23 22:45:08 +08:00
} catch (JSONException | IOException e) {
2019-04-03 18:09:00 +08:00
e.printStackTrace();
2019-04-05 23:59:31 +08:00
} catch (InterruptedException e) {
e.printStackTrace();
2019-04-02 17:41:53 +08:00
}
Cache cache = new Cache();
cache.setSize(block.length);
cache.setData(new WeakReference<char[]>(block));
chaptCache.put(index, cache);
// myArray.set(index, new WeakReference<char[]>(block));
}
return block;
}
2019-04-05 23:59:31 +08:00
2019-04-25 02:01:18 +08:00
Map<Integer,Integer> fileRetryCnt = new HashMap<Integer,Integer>();
2019-04-15 23:26:24 +08:00
private void loadChaptContent(final int chapterIndex) throws JSONException, InterruptedException {
2019-04-05 23:59:31 +08:00
/* 章节内容没有缓存在本地
1. 根据本地的章节网络地址信息读取章节内容到本地若读取失败则
2. 查询主服务器若有地址更新则更新本地信息并重复1若没有更新地址则地址无效返回章节内容正待手打
*/
//
2019-04-20 00:26:49 +08:00
if(!NetUtil.isNetworkConnected() || mChapters.size()==0){
handler.sendEmptyMessage(1);
return ;
}
2019-04-16 23:11:00 +08:00
final int index = mChapters.size() < chapterIndex ? 1 : chapterIndex;
2019-04-15 23:26:24 +08:00
if(mChapters.size() <chapterIndex){
Log.d(TAG,String.format("loadChaptContent----wrong index, chapter size %s,load index %s,bookname %s", mChapters.size(),index,mNovel.getName() ));
2019-04-06 23:04:42 +08:00
2019-04-15 23:26:24 +08:00
}
2019-04-05 23:59:31 +08:00
Chapter chapter = mChapters.get(index -1);
String url = chapter.getChapterUrl();
if( TextUtils.isEmpty( url)){
2019-04-18 17:19:42 +08:00
handler.sendEmptyMessage(1);
2019-04-05 23:59:31 +08:00
return ;
}
long startTime= new Date().getTime();
Log.d(TAG,String.format("loadChaptContent----start download %s from %s", chapter.getChapterName() ,url ));
setDownloadFlag(false);
2019-04-25 02:01:18 +08:00
Log.d( TAG,String.format("loadChaptContent isDownloadChapt: %s",isDownloadChapt));
2019-04-05 23:59:31 +08:00
JSONObject siteJson = new JSONObject();
siteJson.put("chapterContentRegex", mSiteRule.getChapterContentRegex());
siteJson.put("chapterContentDumpRegex", mSiteRule.getChapterContentDumpRegex());
Request request = getTagRequest(url, 0);
2019-04-05 23:59:31 +08:00
HttpMethods.getOkClient().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
2019-04-20 00:26:49 +08:00
if(e.toString().contains("closed") ||e.getMessage().contains("Canceled"))
{
// return;
}
2019-04-25 02:01:18 +08:00
// handler.sendEmptyMessage(123);
// handler.sendEmptyMessage(1);
2019-04-08 23:16:20 +08:00
chaptDownStatus.put(index,DownloadStatus.failure);
2019-04-05 23:59:31 +08:00
setDownloadFlag(true);
2019-04-25 02:01:18 +08:00
Log.d( TAG,String.format("prepare book loadChaptContent fail, isDownloadChapt: %s",isDownloadChapt));
2019-04-07 23:49:08 +08:00
e.printStackTrace();
// throw new RuntimeException("Error during writing " + fileChapterName( index));
2019-04-05 23:59:31 +08:00
}
@Override
public void onResponse(Call call, Response response){
ResponseBody body = response.body();
if (body != null ) {
if(response.code()!=200){
2019-04-25 02:01:18 +08:00
Log.d(TAG, "prepare book loadChaptContent----network failure returnCode " + response.code());
2019-04-05 23:59:31 +08:00
setDownloadFlag(true);
2019-04-08 23:16:20 +08:00
chaptDownStatus.put(index,DownloadStatus.failure);
2019-04-25 02:01:18 +08:00
Log.d( TAG,String.format("prepare book loadChaptContent error %s ,isDownloadChapt: %s", response.code(),isDownloadChapt));
2019-04-05 23:59:31 +08:00
handler.sendEmptyMessage(1);
return;
}
try {
2019-04-16 23:11:00 +08:00
2019-04-05 23:59:31 +08:00
String bodyStr = body.string();
String title = chapter.getChapterName();
String chapterContent = title+ "\n" + NovelParseUtil.getChapterContent(bodyStr, siteJson);
char[] buf = chapterContent.toCharArray();
File file = new File(fileChapterName(index));
file.createNewFile();
final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(index)), charachterType);//"UTF-16LE"); // UTF-16LE 比 utf-8 文件小
writer.write(buf);
writer.close();
2019-04-25 02:01:18 +08:00
Log.d( TAG,String.format("prepare book loadChaptContent file created: %s, thread %s", file.getPath(), Thread.currentThread().getName()));
2019-04-07 23:49:08 +08:00
handler.sendEmptyMessage(123);
setDownloadFlag(true);
2019-04-05 23:59:31 +08:00
} catch (IOException | JSONException e) {
e.printStackTrace();
Log.e(TAG, "onResponse: prepare book error ",e );
chaptDownStatus.put(index,DownloadStatus.failure);
return;
// throw new RuntimeException("Error during writing " + fileChapterName( index));
2019-04-05 23:59:31 +08:00
}
finally {
body.close();
handler.sendEmptyMessage(123);
2019-04-07 23:49:08 +08:00
setDownloadFlag(true);
2019-04-05 23:59:31 +08:00
}
chapter.setNovelId(mNovel.getId());
chapter.setChapterPath(fileChapterName(index));
if(chapter.getId()>0) {
chapter.update(chapter.getId());
}else{
chapter.save();
}
2019-04-07 23:49:08 +08:00
setDownloadFlag(true);
2019-04-08 23:16:20 +08:00
chaptDownStatus.put(index,DownloadStatus.success);
2019-04-16 23:11:00 +08:00
Log.d(TAG,String.format(" prepare book loadChaptContent---- finished download %s, cost time %s ,content path %s ,thread %s", chapter.getChapterName(), new Date().getTime() -startTime ,chapter.getChapterPath() , Thread.currentThread().getName() ));
2019-04-05 23:59:31 +08:00
}
}
});
}
/***
*
* @param url
* @param maxAge
* @return
*/
private Request getTagRequest(String url, int maxAge) {
Request.Builder builder = new Request.Builder()
2019-04-05 23:59:31 +08:00
.tag(mNovel.getNovelId()) //标记 请求的tag,切换小说或离开小说界面(BookActivity) 时 取消未执行完毕的 此tag的所有请求
.url(url)
.removeHeader("Pragma")
.header("Cache-Control", "public, max-age=" + 0)
// .header("Accept-Encoding","gzip, deflate, sdch")
.header("Accept-Language","zh-CN,zh;q=0.9")
.header( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
.header( "Upgrade-Insecure-Requests", "1")
;
return builder.build();
2019-04-05 23:59:31 +08:00
}
2019-04-02 17:41:53 +08:00
public boolean isChapterTitle(String line){
return (line.length() <= 30 && (line.matches(".*第.{1,8}章.*") || line.matches(".*第.{1,8}节.*"))) ;
}
2019-04-05 23:59:31 +08:00
2019-04-02 17:41:53 +08:00
}