2148 lines
84 KiB
Plaintext
2148 lines
84 KiB
Plaintext
|
package com.novelbook.android.utils;
|
|||
|
|
|||
|
import android.app.ProgressDialog;
|
|||
|
import android.content.ContentValues;
|
|||
|
import android.content.Context;
|
|||
|
|
|||
|
|
|||
|
import android.os.AsyncTask;
|
|||
|
import android.os.Bundle;
|
|||
|
import android.os.Handler;
|
|||
|
import android.os.Message;
|
|||
|
import android.text.TextUtils;
|
|||
|
import android.util.Log;
|
|||
|
import android.widget.TextView;
|
|||
|
import android.widget.Toast;
|
|||
|
|
|||
|
import com.google.gson.Gson;
|
|||
|
import com.novelbook.android.BuildConfig;
|
|||
|
import com.novelbook.android.MyApp;
|
|||
|
import com.novelbook.android.bean.Cache;
|
|||
|
import com.novelbook.android.bean.NovelSites;
|
|||
|
import com.novelbook.android.bean.Site;
|
|||
|
import com.novelbook.android.db.SiteRule;
|
|||
|
import com.novelbook.android.db.Chapter;
|
|||
|
import com.novelbook.android.db.Novel;
|
|||
|
import com.novelbook.android.netsubscribe.BookSubscribe;
|
|||
|
import com.novelbook.android.netutils.HttpMethods;
|
|||
|
import com.novelbook.android.netutils.NetUtil;
|
|||
|
import com.novelbook.android.netutils.OnSuccessAndFaultListener;
|
|||
|
import com.novelbook.android.netutils.OnSuccessAndFaultSub;
|
|||
|
|
|||
|
|
|||
|
import org.json.JSONException;
|
|||
|
import org.json.JSONObject;
|
|||
|
import org.litepal.LitePal;
|
|||
|
import org.litepal.util.Const;
|
|||
|
import org.w3c.dom.Text;
|
|||
|
|
|||
|
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.nio.charset.Charset;
|
|||
|
import java.security.KeyManagementException;
|
|||
|
import java.security.NoSuchAlgorithmException;
|
|||
|
import java.security.cert.CertificateException;
|
|||
|
import java.util.ArrayList;
|
|||
|
import java.util.Date;
|
|||
|
import java.util.HashMap;
|
|||
|
import java.util.List;
|
|||
|
import java.util.Map;
|
|||
|
import java.util.Random;
|
|||
|
|
|||
|
import javax.net.ssl.HostnameVerifier;
|
|||
|
import javax.net.ssl.SSLContext;
|
|||
|
import javax.net.ssl.SSLSession;
|
|||
|
import javax.net.ssl.TrustManager;
|
|||
|
import javax.net.ssl.X509TrustManager;
|
|||
|
|
|||
|
import okhttp3.Call;
|
|||
|
import okhttp3.Callback;
|
|||
|
import okhttp3.Request;
|
|||
|
import okhttp3.Response;
|
|||
|
import okhttp3.ResponseBody;
|
|||
|
|
|||
|
|
|||
|
public class BookUtil {
|
|||
|
public static final String TAG ="BookUtil";
|
|||
|
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/";
|
|||
|
private static final String charachterType = "utf-8";//"UTF-16LE";
|
|||
|
|
|||
|
private Context mContext;
|
|||
|
private ProgressDialog progressDialog;
|
|||
|
MuluStatus mMuluStatus; //目录是否下载完成
|
|||
|
private Gson gson = new Gson();
|
|||
|
public void setContext(Context context) {
|
|||
|
this.mContext = context;
|
|||
|
}
|
|||
|
|
|||
|
public boolean isReadingCatalogs() {
|
|||
|
return mMuluStatus == MuluStatus.isDownloading;
|
|||
|
}
|
|||
|
|
|||
|
//存储的字符数
|
|||
|
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<>();
|
|||
|
//目录
|
|||
|
private List<Chapter> mChapters = new ArrayList<>();
|
|||
|
//当前章节
|
|||
|
// private Chapter mCurrentChapter;
|
|||
|
|
|||
|
public List<Chapter> getChapters() {
|
|||
|
return mChapters;
|
|||
|
}
|
|||
|
|
|||
|
public void setChapters(List<Chapter> chapters) {
|
|||
|
this.mChapters = chapters;
|
|||
|
}
|
|||
|
private final int MSG_FILLCONTENTDONE=1;
|
|||
|
private final int MSG_READCHAPTER_FAIL=2;
|
|||
|
private final int MSG_READCHAPTER_SUCCESS=3;
|
|||
|
private static final int MSG_READBOOK_FAIL = 4;
|
|||
|
private static final int MSG_READBOOK_EMPTY_CONTENT = 5;
|
|||
|
|
|||
|
private String m_strCharsetName;
|
|||
|
private String bookName;
|
|||
|
private String bookPath;
|
|||
|
|
|||
|
public void setChapterLen(long chapterLen) {
|
|||
|
this.chapterLen = chapterLen;
|
|||
|
}
|
|||
|
private long bookLen;
|
|||
|
private long chapterLen;
|
|||
|
// private long position;
|
|||
|
private Map<Integer,Long> charPosition = new HashMap<Integer,Long>();
|
|||
|
|
|||
|
private Novel mNovel;
|
|||
|
|
|||
|
private void clearBook() {
|
|||
|
/* try{
|
|||
|
throw new Exception("chapters cleared");
|
|||
|
}catch (Exception e){
|
|||
|
Log.e(TAG, "prepare book: clearbook called", e);
|
|||
|
}*/
|
|||
|
chaptId=0;
|
|||
|
charPosition.clear();
|
|||
|
this.muluRetryCount=0;
|
|||
|
this.downloadStatus = DownloadStatus.notStart;
|
|||
|
chaptDownStatus.clear();
|
|||
|
chaptCache.clear();
|
|||
|
fileRetryCnt.clear();
|
|||
|
siteRuleRetryCnt=0;
|
|||
|
isChangeSource=false;
|
|||
|
mChapters.clear();
|
|||
|
myArray.clear();
|
|||
|
|
|||
|
}
|
|||
|
public void setNovel(Novel novel) {
|
|||
|
clearBook();
|
|||
|
this.mNovel = novel;
|
|||
|
|
|||
|
}
|
|||
|
public Novel getNovel( ) {
|
|||
|
return mNovel ;
|
|||
|
}
|
|||
|
//当前目录网站列表
|
|||
|
private NovelSites mNovelSites;
|
|||
|
//当前目录网站
|
|||
|
private Site mSite;
|
|||
|
private SiteRule mSiteRule;
|
|||
|
|
|||
|
private Map<Integer,Cache> chaptCache = new HashMap<Integer,Cache>();
|
|||
|
protected Map<Integer,DownloadStatus> chaptDownStatus = new HashMap<Integer, DownloadStatus>();
|
|||
|
DownloadStatus downloadStatus = DownloadStatus.notStart;
|
|||
|
|
|||
|
|
|||
|
public Chapter getChapter(int chapId){
|
|||
|
chapId = chapId >0 ?chapId : 1;
|
|||
|
|
|||
|
Log.d(TAG, String.format("prepare book getChapter: chaptId %s,mChapters.size() %s ",chapId,mChapters.size()));
|
|||
|
if(chapId > mChapters.size() || mChapters.size() ==0){
|
|||
|
return Chapter.getChapter(mNovel.getId(), mNovel.getDomain()==null?"":mNovel.getDomain(),chapId);
|
|||
|
}else{
|
|||
|
return mChapters.get(chapId-1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public NovelSites getmNovelSites() {
|
|||
|
return mNovelSites;
|
|||
|
}
|
|||
|
|
|||
|
public synchronized void openBook(Novel novel, long chapter) throws IOException, InterruptedException {
|
|||
|
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())) {
|
|||
|
cleanCacheFile();
|
|||
|
this.bookPath = mNovel.getNovelPath();
|
|||
|
bookName = FileUtils.getFileName(bookPath);
|
|||
|
cacheBook();
|
|||
|
}
|
|||
|
}
|
|||
|
}else{ //读取目录列表
|
|||
|
Log.d(TAG, String.format("prepare book %s open chapter %s in background.... mMuluStatus %s,mSiteRule %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;
|
|||
|
}
|
|||
|
|
|||
|
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 %s,mSiteRule %s,thread %s",mNovel.getName(),mMuluStatus,mSiteRule,Thread.currentThread().getName()) );
|
|||
|
|
|||
|
int sleptTime =0;
|
|||
|
while( mSiteRule ==null || mMuluStatus==null || mMuluStatus == MuluStatus.isDownloading){
|
|||
|
|
|||
|
sleptTime++;
|
|||
|
if(sleptTime >400 || sleptTime >30 && !NetUtil.isNetworkConnected()){
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
Thread.sleep(50);
|
|||
|
if(mMuluStatus == MuluStatus.failed){
|
|||
|
Log.d(TAG,String.format("prepare book %s failed ,mMuluStatus %s,msiteRule %s,slept %s" ,mNovel.getName(),mMuluStatus,mSiteRule,sleptTime*50));
|
|||
|
// throw new RuntimeException("读取资源失败,请检查网络");
|
|||
|
}
|
|||
|
}
|
|||
|
Log.d(TAG,String.format("prepare book %s waiting for mulu downloading ,mMuluStatus %s,msiteRule %s,slept %s" ,mNovel.getName(),mMuluStatus,mSiteRule,sleptTime*50));
|
|||
|
|
|||
|
}
|
|||
|
// dismissProgressDialog();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public void setNovelSites(NovelSites nvs) {
|
|||
|
|
|||
|
this.mNovelSites = nvs;
|
|||
|
|
|||
|
Log.d(TAG, String.format("prepare book %s get novel sites count %s .",mNovel.getName(), nvs.getSites().length) );
|
|||
|
if(nvs.getSites().length ==0){
|
|||
|
throw new RuntimeException("书本错误 no site, code 001"); //无目标网站
|
|||
|
// return;
|
|||
|
}
|
|||
|
mSite =null;
|
|||
|
if(nvs.getSites().length > 0){
|
|||
|
for (Site site:nvs.getSites() ) {
|
|||
|
if(TextUtils.isEmpty(site.getMuluUrl())){
|
|||
|
continue;
|
|||
|
}
|
|||
|
if(!TextUtils.isEmpty(mNovel.getDomain()) && site.getDomain().equals(mNovel.getDomain())){
|
|||
|
mSite = site;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if(mSite ==null) {
|
|||
|
for (Site site : nvs.getSites()) {
|
|||
|
if(TextUtils.isEmpty(site.getMuluUrl())){
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (site.getSelectedByDefault()) {
|
|||
|
mSite = site;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if(mSite ==null) {
|
|||
|
for (Site site : nvs.getSites()) {
|
|||
|
if(TextUtils.isEmpty(site.getMuluUrl())){
|
|||
|
continue;
|
|||
|
}
|
|||
|
mSite = site;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
if(mSite!=null) {
|
|||
|
getSiteRule();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void setSiteInfo() {
|
|||
|
|
|||
|
File file = new File(getChapterPath() +mSite.getDomain());
|
|||
|
if(!file.exists()){
|
|||
|
file.mkdir();
|
|||
|
}
|
|||
|
mNovel.setDomain(mSite.getDomain());
|
|||
|
mNovel.setDomainName(mSite.getName());
|
|||
|
mNovel.setMuluUrl(mSite.getMuluUrl());
|
|||
|
mNovel.setToDefault("isUpdated");
|
|||
|
mNovel.update(mNovel.getId());
|
|||
|
}
|
|||
|
|
|||
|
public void getTargetSites(){
|
|||
|
Log.d(TAG, "prepare book: getTargetSites" );
|
|||
|
BookSubscribe.getNovelSites(mNovel.getNovelId(),new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() {
|
|||
|
@Override
|
|||
|
public void onSuccess(String result) {
|
|||
|
//成功
|
|||
|
try {
|
|||
|
Log.d(TAG, String.format("prepare book %s get target sites done.thread %s",mNovel.getName(),Thread.currentThread().getName()) );
|
|||
|
|
|||
|
NovelSites nvs = (NovelSites) gson.fromJson(result,NovelSites.class);
|
|||
|
//pageFactory.prepareBook(mNovel,nvs, BookActivity.this);
|
|||
|
setNovelSites(nvs);
|
|||
|
|
|||
|
|
|||
|
} catch ( Exception e) {
|
|||
|
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);
|
|||
|
e.printStackTrace();
|
|||
|
}
|
|||
|
|
|||
|
// Toast.makeText(mContext,"getMuluInfo 请求成功 " ,Toast.LENGTH_SHORT).show();
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onFault(String errorMsg) {
|
|||
|
Log.d(TAG, String.format("prepare book %s get target sites fail.thread %s ,msg %s",mNovel.getName(),Thread.currentThread().getName(),errorMsg) );
|
|||
|
|
|||
|
//失败
|
|||
|
// Toast.makeText(mContext,"getMuluInfo 请求失败"+errorMsg,Toast.LENGTH_SHORT).show();
|
|||
|
}
|
|||
|
},null));
|
|||
|
}
|
|||
|
|
|||
|
int siteRuleRetryCnt =0;
|
|||
|
public void getSiteRule() {
|
|||
|
getSiteRule(false);
|
|||
|
}
|
|||
|
public void getSiteRule(boolean isForceRefresh) {
|
|||
|
mSiteRule = null;
|
|||
|
if(mSite==null){
|
|||
|
return;
|
|||
|
}
|
|||
|
BookSubscribe.getSiteRule(mSite.getDomain(),new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() {
|
|||
|
@Override
|
|||
|
public void onSuccess(String result) {
|
|||
|
siteRuleRetryCnt =0;
|
|||
|
Log.d(TAG, "prepare book siteRule:" +result);
|
|||
|
//成功
|
|||
|
SiteRule sr= new SiteRule();
|
|||
|
try {
|
|||
|
sr = (SiteRule) gson.fromJson(result, SiteRule.class);
|
|||
|
}catch (Exception e){
|
|||
|
Log.e(TAG, "prepare book error on gson: ", e);
|
|||
|
}
|
|||
|
|
|||
|
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;
|
|||
|
if(TextUtils.isEmpty(mSite.getName())){
|
|||
|
mSite.setName(sr.getName());
|
|||
|
};
|
|||
|
setSiteInfo();
|
|||
|
Log.d(TAG, String.format("prepare book %s 目录正则表达式下载完成,开始读章节信息. muluRegex size %s, thread %s ",mNovel.getName(),mSiteRule.getChapterUrlRegexOnMulu().length, Thread.currentThread().getName()) );
|
|||
|
|
|||
|
Log.d(TAG, String.format("目录正则表达式下载完成,开始读取章节信息") );
|
|||
|
|
|||
|
int maxAge = isForceRefresh? 0:mNovel.getMaxAge() ;
|
|||
|
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() ,maxAge ,mSite.getMuluUrl() ));
|
|||
|
new Thread(){
|
|||
|
@Override
|
|||
|
public void run() {
|
|||
|
Log.d(TAG, "to get chaps............................>");
|
|||
|
Log.d(TAG, "to get chaps siteRule:" +result);
|
|||
|
Log.d(TAG, "to get chaps mulu:" + mSite.getMuluUrl() );
|
|||
|
String[] chaps = new String[0];
|
|||
|
try {
|
|||
|
JSONObject siteJson = new JSONObject(result);
|
|||
|
|
|||
|
mChapters = NovelParseUtil.getChapters(mSite.getMuluUrl(), siteJson,mSite.getDomain(),maxAge,mSiteRule);
|
|||
|
|
|||
|
if (mChapters != null){
|
|||
|
/* int i=0;
|
|||
|
for (Chapter chapter:mChapters) {
|
|||
|
i++;
|
|||
|
// Log.i(TAG, String.format("prepare book to get chaps readChaptersAsync %s-->%s",chapter.getChapterUrl(), chapter.getChapterName()));
|
|||
|
if(chapter.getChapterName().equals(mNovel.getChapterName())){
|
|||
|
if(i<mChapters.size()-1){
|
|||
|
mNovel.setChapterName(mChapters.get(mChapters.size()-1).getChapterName());
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}*/
|
|||
|
|
|||
|
checkLastUpdatedChapter();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
} catch (JSONException e) {
|
|||
|
Log.e(TAG, "prepare book error on parese :", e);
|
|||
|
}
|
|||
|
|
|||
|
if (mChapters == null ||mChapters.size()== 0) {
|
|||
|
readChaptersAsync();
|
|||
|
}else
|
|||
|
{
|
|||
|
|
|||
|
mMuluStatus = MuluStatus.isDone;
|
|||
|
handler.sendEmptyMessage(MSG_READCHAPTER_SUCCESS);
|
|||
|
Log.d(TAG,String.format("prepare book loadChapts----end download %s 目录, 目录数量 %s, cost %s", mNovel.getName() , mChapters.size(), new Date().getTime() -startTime ));
|
|||
|
|
|||
|
Log.d(TAG, String.format("prepare book %s 章节信息完成.",mNovel.getName()) );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
}.start();
|
|||
|
|
|||
|
|
|||
|
}else{
|
|||
|
readChaptersAsync();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onFault(String errorMsg) {
|
|||
|
//失败
|
|||
|
Log.e(TAG,"error on get sitRule: "+errorMsg);
|
|||
|
siteRuleRetryCnt++;
|
|||
|
if(siteRuleRetryCnt <Constants.retryCnt){
|
|||
|
getSiteRule();
|
|||
|
}
|
|||
|
}
|
|||
|
},mContext));
|
|||
|
|
|||
|
/*
|
|||
|
if(mSiteRule==null && mSite!=null) {
|
|||
|
List<SiteRule> srs = LitePal.where("domain=?", mSite.getDomain()).find(SiteRule.class);
|
|||
|
if (srs.size() > 0) {
|
|||
|
mSiteRule = srs.get(0);
|
|||
|
}
|
|||
|
}*/
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void reportMsg(String reportType,String url,String content,String headers,String httpStatus){
|
|||
|
|
|||
|
/* String msg = String.format("{\"type\":%s, \"id\":%s ,\"name\":\"%s\",\"site\":\"%s\",\"url\":\"%s\",\"content\":\"%s\",\"requestHeader\":\"%s\",\"httpStatus\":\"%s\"}," ,
|
|||
|
reportType ,mNovel.getId(),mNovel.getName(),mSite.getDomain(),url ,content,headers,httpStatus);
|
|||
|
*/
|
|||
|
String key =mNovel.getNovelId()+url;
|
|||
|
if(Constants.REPORT_HIS.contains(key)){
|
|||
|
return;
|
|||
|
}
|
|||
|
Constants.REPORT_HIS.add(key);
|
|||
|
String msg = String.format("{\"type\":\"%s\", \"novelId\":%s ,\"site\":\"%s\",\"url\":\"%s\",\"httpStatus\":\"%s\",\"content\":\"%s\"}" ,
|
|||
|
reportType ,mNovel.getNovelId(),mSite.getDomain(),url ,httpStatus,content);
|
|||
|
|
|||
|
BookSubscribe.reportMsg(reportType ,msg);
|
|||
|
}
|
|||
|
private void checkLastUpdatedChapter() {
|
|||
|
/* if(BuildConfig.LOG_DEBUG) {
|
|||
|
if(mChapters.size()>1) {
|
|||
|
reportMsg(Constants.REPORT_NEW_UPDATE,"", mNovel.getChapterName()+" 测试用例", "", "");
|
|||
|
}
|
|||
|
}*/
|
|||
|
for (int i=mChapters.size()-1;i>0;i--) {
|
|||
|
if(mChapters.get(i).getChapterName().equals(mNovel.getChapterName())){
|
|||
|
if(i<mChapters.size()-1){
|
|||
|
|
|||
|
mNovel.setChapterName(mChapters.get(mChapters.size()-1).getChapterName());
|
|||
|
Log.d(TAG, "prepare book: set novel lastchaptname " + mNovel.getLastReadChapt());
|
|||
|
|
|||
|
reportMsg(Constants.REPORT_NEW_UPDATE,"",mNovel.getChapterName(),"","");
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if( mChapters.size()> mNovel.getChaptCnt()){
|
|||
|
mNovel.setChaptCnt(mChapters.size());
|
|||
|
mNovel.update(mNovel.getId());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void setChapterNo(int chapterNo) {
|
|||
|
|
|||
|
/* try{
|
|||
|
throw new Exception();
|
|||
|
}catch (Exception e){
|
|||
|
Log.e(TAG, "prepare book setChapterNo: who set chaptno "+ chapterNo,e );
|
|||
|
}*/
|
|||
|
|
|||
|
|
|||
|
this.chapterNo = chapterNo;
|
|||
|
/*
|
|||
|
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));
|
|||
|
}
|
|||
|
*/
|
|||
|
}
|
|||
|
|
|||
|
public int getChapterNo() {
|
|||
|
|
|||
|
if(chapterNo > mChapters.size()){
|
|||
|
Log.d(TAG, String.format(" prepare book getChapterNo ,chapterNo %s, getChapters().size() %s ,mChangeChapId %s" ,chapterNo , mChapters.size(),mChangeChapId) );
|
|||
|
if(mChangeChapId>0){
|
|||
|
return mChangeChapId;
|
|||
|
}
|
|||
|
// chapterNo=1;
|
|||
|
if(mChapters.size()>0){
|
|||
|
return 1;
|
|||
|
}
|
|||
|
}
|
|||
|
chapterNo = chapterNo<=0 ?1 :chapterNo;
|
|||
|
|
|||
|
Log.d(TAG, String.format(" prepare book getChapterNo ,chapterNo %s, getChapters().size() %s " ,chapterNo , mChapters.size()) );
|
|||
|
return chapterNo;
|
|||
|
}
|
|||
|
|
|||
|
private int chapterNo;//当前章节
|
|||
|
|
|||
|
|
|||
|
public String getLineBreakChar(){
|
|||
|
return "\n";
|
|||
|
}
|
|||
|
|
|||
|
public BookUtil(){
|
|||
|
checkAndCreateDir(storagePath);
|
|||
|
checkAndCreateDir(chapterPath);
|
|||
|
checkAndCreateDir(cachedPath);
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public boolean isBusy() {
|
|||
|
return false;
|
|||
|
|
|||
|
}
|
|||
|
private long tmpChaptLen=0;
|
|||
|
|
|||
|
public void setTmpChaptLen(long tmpChaptLen) {
|
|||
|
this.tmpChaptLen = tmpChaptLen;
|
|||
|
}
|
|||
|
|
|||
|
private boolean isChangeSource =false;
|
|||
|
private int mChangeChapId;
|
|||
|
private String mChangeTitle;
|
|||
|
|
|||
|
public void changeSite(String domain){
|
|||
|
for (Site site:mNovelSites.getSites() ) {
|
|||
|
if(site.getDomain().equals(domain)){
|
|||
|
mSite = site;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
setSiteInfo();
|
|||
|
|
|||
|
|
|||
|
isChangeSource = true;
|
|||
|
mChapters.clear();
|
|||
|
Log.e(TAG, "prepare book: clearbook called ,changeSite()" );
|
|||
|
getSiteRule();
|
|||
|
}
|
|||
|
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) );
|
|||
|
|
|||
|
clearBook();
|
|||
|
// isDownloadChapt =false;
|
|||
|
mChangeChapId = chapId;
|
|||
|
mChangeTitle =chapTitle;
|
|||
|
changeSite(domain);
|
|||
|
|
|||
|
BookTask btsk = new BookTask();
|
|||
|
btsk.execute( domain, chapId+"", chapTitle);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
public Site getSite() {
|
|||
|
return mSite !=null? mSite :new Site();
|
|||
|
}
|
|||
|
|
|||
|
public boolean chaptCached(int num) {
|
|||
|
File f = new File(fileChapterName(num));
|
|||
|
return f.exists();
|
|||
|
}
|
|||
|
|
|||
|
public boolean retryDownLoadContent(int chaptId) {
|
|||
|
if(chaptDownStatus.containsKey(chaptId)){
|
|||
|
Log.d(TAG, "prepare book retryDownLoadContent:chaptDownStatus.get(chaptId) " +chaptDownStatus.get(chaptId) );
|
|||
|
if( chaptDownStatus.get(chaptId) == DownloadStatus.failure){
|
|||
|
if(fileRetryCnt.containsKey(chaptId)){
|
|||
|
if(fileRetryCnt.get(chaptId) < Constants.retryCnt){
|
|||
|
fileRetryCnt.put(chaptId,fileRetryCnt.get(chaptId)+1 );
|
|||
|
|
|||
|
}else{
|
|||
|
return false;
|
|||
|
}
|
|||
|
}else {
|
|||
|
fileRetryCnt.put(chaptId, 1 );
|
|||
|
}
|
|||
|
|
|||
|
}else{
|
|||
|
return false;
|
|||
|
}
|
|||
|
}else{
|
|||
|
Log.d(TAG, "prepare book retryDownLoadContent:to start new download " );
|
|||
|
chaptDownStatus.put(chaptId,DownloadStatus.downloading);
|
|||
|
fileRetryCnt.put(chaptId,1 );
|
|||
|
}
|
|||
|
|
|||
|
if(fileRetryCnt.get(chaptId) < Constants.retryCnt) {
|
|||
|
try {
|
|||
|
loadChaptContent(chaptId);
|
|||
|
chaptDownStatus.put(chaptId,DownloadStatus.downloading);
|
|||
|
} catch (JSONException e) {
|
|||
|
e.printStackTrace();
|
|||
|
} catch (InterruptedException e) {
|
|||
|
e.printStackTrace();
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* delete cache chapter file
|
|||
|
* and reload the chapter
|
|||
|
*/
|
|||
|
public void refreshChapter() {
|
|||
|
File file = new File(fileChapterName(chapterNo));
|
|||
|
if(file.exists()){
|
|||
|
file.delete();
|
|||
|
}
|
|||
|
fileRetryCnt.clear();
|
|||
|
chaptDownStatus.clear();
|
|||
|
if(chaptCache.containsKey(chapterNo)){
|
|||
|
chaptCache.remove(chapterNo);
|
|||
|
}
|
|||
|
if(pagefactory!=null) {
|
|||
|
pagefactory.changeChapter(chapterNo);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
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, String.format("changing Source: target domain %s chaptId %s, chapt title %s,mChangeChapId %s "
|
|||
|
,domain,chapId,chapTitle,mChangeChapId) );
|
|||
|
|
|||
|
int chId=chapId;//chapterNo;
|
|||
|
String title ="";
|
|||
|
mChangeChapId = mChangeChapId >=1 ?mChangeChapId :1;
|
|||
|
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) || title.contains(mChangeTitle) || mChangeTitle.contains(title)) {
|
|||
|
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;
|
|||
|
title = mChangeTitle;
|
|||
|
break;
|
|||
|
}
|
|||
|
i++;
|
|||
|
}
|
|||
|
|
|||
|
if (!title.equals(mChangeTitle)) {
|
|||
|
i = 1;
|
|||
|
for (Chapter chapter : mChapters) {
|
|||
|
// Log.d(TAG, "changing Source: finding chapter " + i + ":" + chapter.getChapterName());
|
|||
|
if ( mChangeTitle.contains(chapter.getChapterName())
|
|||
|
||chapter.getChapterName().contains(mChangeTitle)
|
|||
|
){
|
|||
|
Log.d(TAG, "changing Source:successed find chapter by original title " + i + ":" + mChangeTitle);
|
|||
|
chId = i;
|
|||
|
title = chapter.getChapterName();
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
i++;
|
|||
|
}
|
|||
|
|
|||
|
i = 1;
|
|||
|
for (Chapter chapter : mChapters) {
|
|||
|
// Log.d(TAG, "changing Source: finding chapter " + i + ":" + chapter.getChapterName());
|
|||
|
if ( chapter.getChapterName().startsWith(mChangeTitle)
|
|||
|
||mChangeTitle.startsWith(chapter.getChapterName() )
|
|||
|
|
|||
|
){
|
|||
|
Log.d(TAG, "changing Source:successed find chapter by original title " + i + ":" + mChangeTitle);
|
|||
|
chId = i;
|
|||
|
title = chapter.getChapterName();
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
i++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* if (!title.contains(mChangeTitle)) {
|
|||
|
i = 1;
|
|||
|
for (Chapter chapter : mChapters) {
|
|||
|
// Log.d(TAG, "changing Source: finding chapter " + i + ":" + chapter.getChapterName());
|
|||
|
if (mChangeTitle.contains(chapter.getChapterName())) {
|
|||
|
Log.d(TAG, "changing Source:successed find chapter by original title " + i + ":" + mChangeTitle);
|
|||
|
chId = i;
|
|||
|
title = chapter.getChapterName();
|
|||
|
break;
|
|||
|
}
|
|||
|
i++;
|
|||
|
}
|
|||
|
}*/
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
chId = chId <= mChapters.size() ? chId: mChapters.size();
|
|||
|
Log.d(TAG, "changing Source: to open chapter with new site source " + chId + " : "+ mChangeTitle );
|
|||
|
if(pagefactory!=null)
|
|||
|
pagefactory.changeChapter(chId);
|
|||
|
// mChangeChapId=0;
|
|||
|
// 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 && splet <Constants.MAX_SLEEP_4_CHAPT_DOWNLOAD){
|
|||
|
try {
|
|||
|
Thread.sleep(50);
|
|||
|
splet+=50;
|
|||
|
Log.d(TAG, String.format("prepare book 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 有问题
|
|||
|
|
|||
|
*/
|
|||
|
/* 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();*//*
|
|||
|
|
|||
|
}
|
|||
|
*/
|
|||
|
enum MuluStatus{
|
|||
|
isDownloading,
|
|||
|
isDone,
|
|||
|
failed
|
|||
|
}
|
|||
|
/*private void showProgressDialog(String title,boolean canBreak) {
|
|||
|
if ( null == progressDialog) {
|
|||
|
progressDialog =new ProgressDialog(mContext);
|
|||
|
|
|||
|
}
|
|||
|
progressDialog.setMessage(title);
|
|||
|
progressDialog.setCancelable(canBreak);
|
|||
|
progressDialog.show();
|
|||
|
// progressDialog.show(mContext,"网络不给力","正努力加载",false,true);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void dismissProgressDialog() {
|
|||
|
if ( null != progressDialog) {
|
|||
|
progressDialog.dismiss();
|
|||
|
}
|
|||
|
}
|
|||
|
*/
|
|||
|
private void checkAndCreateDir(String path){
|
|||
|
File file = new File(path);
|
|||
|
if (!file.exists()){
|
|||
|
file.mkdir();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
int muluRetryCount =0;
|
|||
|
|
|||
|
void readChaptersAsync(){
|
|||
|
readChaptersAsync(false);
|
|||
|
}
|
|||
|
void readChaptersAsync(boolean isForceRefresh ) {
|
|||
|
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;
|
|||
|
}
|
|||
|
String url = mSite.getMuluUrl();
|
|||
|
int maxAge= isForceRefresh ?0 : mNovel.getMaxAge();
|
|||
|
if(!isHttpOrHttps(url)){
|
|||
|
return ;
|
|||
|
}
|
|||
|
|
|||
|
Request request = getTagRequest(url,REUtil.getDomain(url),maxAge);
|
|||
|
|
|||
|
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 ));
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* if(muluRetryCount<3){
|
|||
|
muluRetryCount++;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if(muluRetryCount>=3) {
|
|||
|
return;
|
|||
|
}*/
|
|||
|
|
|||
|
HttpMethods.getOkClient().newCall(request).enqueue(new Callback() {
|
|||
|
@Override
|
|||
|
public void onFailure(Call call, IOException e) {
|
|||
|
// 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));
|
|||
|
|
|||
|
// handler.sendEmptyMessage(3);
|
|||
|
|
|||
|
//TODO 如果是取消了访问,则返回
|
|||
|
|
|||
|
if (e.toString()!=null && e.toString().contains("closed") || e.getMessage()!=null && e.getMessage().contains("Canceled")) {
|
|||
|
Log.d(TAG, String.format("prepare book loadChapts---- canceled %s 目录 from %s", mNovel.getName(), url));
|
|||
|
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
mMuluStatus = MuluStatus.failed;
|
|||
|
|
|||
|
if (muluRetryCount < Constants.muluRetryCnt) {
|
|||
|
try {
|
|||
|
long sleeptime =100;
|
|||
|
if(mSiteRule!=null) {
|
|||
|
sleeptime = mSiteRule.getMiniInterval4AccessChapter();
|
|||
|
}
|
|||
|
Thread.sleep(sleeptime);
|
|||
|
|
|||
|
} catch (InterruptedException e1) {
|
|||
|
e1.printStackTrace();
|
|||
|
}
|
|||
|
muluRetryCount++;
|
|||
|
Log.d(TAG,String.format("prepare book loadChapts----failed, retrying count %s",muluRetryCount ));
|
|||
|
readChaptersAsync();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Log.d(TAG,String.format("prepare book loadChapts----failed, site count %s",mNovelSites.getSites().length ));
|
|||
|
if (mNovelSites.getSites().length == 1) { //仅有一个rule,且失败了
|
|||
|
|
|||
|
// mMuluStatus = MuluStatus.failed;
|
|||
|
reportMsg( Constants.REPORT_REX_MULU_ERROR,url,"",getRequestHeader(request), "");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//try next site
|
|||
|
Message msg =Message.obtain();
|
|||
|
msg.what =MSG_READCHAPTER_FAIL;
|
|||
|
msg.arg1 =chapterNo;
|
|||
|
Bundle bundleData = new Bundle();
|
|||
|
|
|||
|
for (Site st : mNovelSites.getSites()) {
|
|||
|
if (!st.getDomain().equals(mSite.getDomain())) {
|
|||
|
//mSite = st;
|
|||
|
mNovel.setDomain(st.getDomain());
|
|||
|
mNovel.setDomainName(mSite.getName());
|
|||
|
bundleData.putString("siteName", st.getName());
|
|||
|
msg.setData(bundleData);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
// mNovel.setDomain(mSite.getDomain());
|
|||
|
muluRetryCount=0;
|
|||
|
fileRetryCnt.clear();
|
|||
|
siteRuleRetryCnt=0;
|
|||
|
chaptCache.clear();
|
|||
|
|
|||
|
|
|||
|
handler.sendMessage(msg);
|
|||
|
// handler.sendEmptyMessage(MSG_READCHAPTER_FAIL);
|
|||
|
// readChaptersAsync();
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
@Override
|
|||
|
public void onResponse(Call call, Response response){
|
|||
|
ResponseBody body = response.body();
|
|||
|
/* if(BuildConfig.LOG_DEBUG) {
|
|||
|
reportMsg( Constants.REPORT_REX_MULU_ERROR,url,"",getRequestHeader(request),response.code()+"");
|
|||
|
}*/
|
|||
|
if(response.code()!=200){
|
|||
|
Log.d(TAG,String.format("prepare book loadChapts----failed, %s 目录 from %s,return code %s", mNovel.getName() ,url,response.code() ));
|
|||
|
// handler.sendEmptyMessage(3);
|
|||
|
mMuluStatus = MuluStatus.failed;
|
|||
|
if(muluRetryCount <Constants.retryCnt){
|
|||
|
Log.d(TAG,String.format("prepare book loadChapts----failed, response code %s retrying count %s",response.code(), muluRetryCount ));
|
|||
|
muluRetryCount++;
|
|||
|
readChaptersAsync();
|
|||
|
}else{
|
|||
|
|
|||
|
reportMsg( Constants.REPORT_REX_MULU_ERROR,url,"",getRequestHeader(request),response.code()+"");
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// mChangeChapId =0;
|
|||
|
muluRetryCount =0;
|
|||
|
if (body != null) {
|
|||
|
Log.d(TAG, String.format("prepare book %s 章节信息读取成功.thread %s",mNovel.getName(),Thread.currentThread().getName()) );
|
|||
|
try {
|
|||
|
// String bodyStr = body.string();
|
|||
|
String bodyStr =NovelParseUtil.enconding(body ,mSiteRule.getEncoding());
|
|||
|
|
|||
|
// 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();
|
|||
|
buildChapters(bodyStr,url);
|
|||
|
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()) );
|
|||
|
handler.sendEmptyMessage(MSG_READCHAPTER_SUCCESS); //通知换源过程已读到目录
|
|||
|
} catch (IOException e) {
|
|||
|
e.printStackTrace();
|
|||
|
}finally {
|
|||
|
body.close();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
void buildChapters( String content ,String url){
|
|||
|
|
|||
|
// Log.d(TAG, "buildChapters: " +content);
|
|||
|
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;
|
|||
|
}
|
|||
|
try {
|
|||
|
JSONObject siteJson = new JSONObject();
|
|||
|
|
|||
|
siteJson.put("chapterUrlPattern", mSiteRule.getChapterUrlPattern());
|
|||
|
/* 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", "");
|
|||
|
//
|
|||
|
|
|||
|
mChapters = NovelParseUtil.getChapters(mSite.getDomain(),url, content, siteJson);
|
|||
|
Log.d(TAG,String.format("mulu on Site %s download status %s",mSite.getDomain(),mMuluStatus));
|
|||
|
|
|||
|
checkLastUpdatedChapter();
|
|||
|
} 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);
|
|||
|
e.printStackTrace();
|
|||
|
} finally {
|
|||
|
// result.close();
|
|||
|
// if (result2 != null) result2.close();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
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,int chaptId){
|
|||
|
// Log.d(TAG, String.format(" loadchapt next(), back %s, chaptId %s, position %s, tmpChaptLen %s",back,chaptId,charPosition.get(chaptId),tmpChaptLen ));
|
|||
|
charPosition.put(chaptId,charPosition.get(chaptId)+1) ;
|
|||
|
if (charPosition.get(chaptId) > tmpChaptLen){
|
|||
|
charPosition.put(chaptId,tmpChaptLen) ;
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
char result = chaptCurrent(chaptId); //current();
|
|||
|
if (back) {
|
|||
|
charPosition.put(chaptId,charPosition.get(chaptId)-1) ;
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
/*public char[] nextLine(){
|
|||
|
if (position >= tmpChaptLen){
|
|||
|
return null;
|
|||
|
}
|
|||
|
String line = "";
|
|||
|
while (position < tmpChaptLen){
|
|||
|
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(int chaptId){
|
|||
|
// chapterNo = mChapters.size() < chapterNo ? 1 : chapterNo;
|
|||
|
// Log.d(TAG, String.format(" loadchapt chaptCurrent() ,chapterNo %s, getChapters().size() %s " ,chaptId , mChapters.size()) );
|
|||
|
char[] charArray = chaptChars(chaptId);
|
|||
|
|
|||
|
|
|||
|
int i = (int) (charPosition.get(chaptId) -1);//(int)position-1;
|
|||
|
i =i>0?i:0;
|
|||
|
i = i< charArray.length? i:charArray.length-1;
|
|||
|
|
|||
|
// Log.d(TAG, String.format(" loadchapt chaptCurrent(), char position %s - %s, char '%s' " ,i,charPosition.get(chaptId) -1,charArray[i]) );
|
|||
|
return charArray[i];
|
|||
|
}
|
|||
|
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 >= charPosition.get(chaptId) ){
|
|||
|
cachePos = i;
|
|||
|
pos = (int) (charPosition.get(chaptId) - 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(int chaptId){
|
|||
|
return charPosition.get(chaptId);
|
|||
|
}
|
|||
|
|
|||
|
public void setPostition(int chaptId,long position){
|
|||
|
charPosition.put(chaptId,position) ;
|
|||
|
}
|
|||
|
|
|||
|
//缓存书本
|
|||
|
private void cacheBook() throws IOException {
|
|||
|
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,mNovel.getId());
|
|||
|
}else{
|
|||
|
m_strCharsetName = mNovel.getCharset();
|
|||
|
}
|
|||
|
|
|||
|
File file = new File(bookPath);
|
|||
|
InputStreamReader reader = new InputStreamReader(new FileInputStream(file),m_strCharsetName);
|
|||
|
int index = 0;
|
|||
|
bookLen = 0;
|
|||
|
mChapters.clear();
|
|||
|
Log.e(TAG, "prepare book: clearbook called ,cacheBook()" );
|
|||
|
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;
|
|||
|
|
|||
|
Chapter bookChapter = null;
|
|||
|
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());
|
|||
|
mChapters.add(bookChapter);
|
|||
|
}
|
|||
|
|
|||
|
bookChapter = new Chapter();
|
|||
|
bookChapter.setNovelId(mNovel.getId());
|
|||
|
bookChapter.setNovelChapterStartPos(start);
|
|||
|
bookChapter.setChapterName(str.replaceAll("###",""));
|
|||
|
bookChapter.setNovelPath(bookPath);
|
|||
|
bookChapter.setIndex(chaptId+1);
|
|||
|
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) {
|
|||
|
bookChapter = new Chapter();
|
|||
|
bookChapter.setNovelId(mNovel.getId());
|
|||
|
bookChapter.setNovelChapterStartPos(start);
|
|||
|
bookChapter.setChapterName(str.replaceAll("###",""));
|
|||
|
bookChapter.setNovelPath(bookPath);
|
|||
|
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();
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
Chapter bookChapter = new Chapter();
|
|||
|
bookChapter.setBookId(mNovel.getId());
|
|||
|
|
|||
|
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);
|
|||
|
mChapters.add(bookChapter);
|
|||
|
*/
|
|||
|
}
|
|||
|
}
|
|||
|
if(writer!=null) {
|
|||
|
writer.close();
|
|||
|
}
|
|||
|
if(bookChapter!=null) {
|
|||
|
bookChapter.setLength((int)(size - start));
|
|||
|
bookChapter.setChapterPath(fileChapterName(chaptId) );
|
|||
|
bookChapter.update(bookChapter.getId());
|
|||
|
mChapters.add(bookChapter);
|
|||
|
}
|
|||
|
}catch (Exception e){
|
|||
|
e.printStackTrace();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void createChapContent(){
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public List<Chapter> getmChapters(){
|
|||
|
return mChapters;
|
|||
|
}
|
|||
|
|
|||
|
public long getChapterLen(){
|
|||
|
return chapterLen;
|
|||
|
}
|
|||
|
|
|||
|
protected String fileName(int index) {
|
|||
|
return cachedPath + mNovel.getName() + index ;
|
|||
|
}
|
|||
|
public String fileChapterName(int chaptId ) {
|
|||
|
checkAndCreateDir(chapterPath);
|
|||
|
if(mNovel!=null && !TextUtils.isEmpty(mNovel.getDomain())){
|
|||
|
|
|||
|
return getChapterPath() +mNovel.getDomain()+"/"+ chaptId ;
|
|||
|
}
|
|||
|
return getChapterPath() + chaptId ;
|
|||
|
}
|
|||
|
|
|||
|
String getChapterPath(){
|
|||
|
File file = new File(chapterPath +mNovel.getId());
|
|||
|
if(!file.exists()){
|
|||
|
file.mkdir();
|
|||
|
}
|
|||
|
return chapterPath +mNovel.getId()+"/";
|
|||
|
}
|
|||
|
|
|||
|
//获取书本缓存
|
|||
|
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;
|
|||
|
}
|
|||
|
|
|||
|
/*boolean isDownloadChapt =false;
|
|||
|
synchronized boolean getDownloadStatus(){
|
|||
|
return isDownloadChapt;
|
|||
|
}
|
|||
|
synchronized void setDownloadFlag(boolean flag){
|
|||
|
isDownloadChapt = flag;
|
|||
|
Log.d(TAG,String.format("set download flat",isDownloadChapt) );
|
|||
|
}*/
|
|||
|
public ChangeSource pagefactory;
|
|||
|
Handler handler = new Handler() {
|
|||
|
@Override
|
|||
|
public void handleMessage(Message msg) {
|
|||
|
|
|||
|
int wt = msg.what;
|
|||
|
Log.d(TAG, String.format("prepare book get message what %s ,obj %s",msg.what,msg.obj));
|
|||
|
handlerMsg(msg);
|
|||
|
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
void handlerMsg(Message msg){
|
|||
|
if (msg.what == MSG_FILLCONTENTDONE) {
|
|||
|
// isDownloadChapt =true;
|
|||
|
Log.d(TAG,String.format("handler msg, download %s",true) );
|
|||
|
}else if(msg.what==MSG_READCHAPTER_FAIL){
|
|||
|
try {
|
|||
|
Toast.makeText(mContext, "网络拥堵,已帮您切换其它源", Toast.LENGTH_LONG).show();
|
|||
|
}catch (Exception e){
|
|||
|
Log.e(TAG, "handlerMsg:toast error ", e);
|
|||
|
}
|
|||
|
// getSiteRule();
|
|||
|
// pagefactory .changeChapter(getChapterNo());
|
|||
|
|
|||
|
|
|||
|
String targetSiteName = msg.getData().getString("siteName");
|
|||
|
Log.d(TAG, String.format("prepare book changing Source:target %s -- %s to open chapter %s"
|
|||
|
,mNovel.getDomain(),targetSiteName,msg.arg1));
|
|||
|
if(pagefactory!=null)
|
|||
|
pagefactory.changeSource(targetSiteName, mNovel.getDomain(),msg.arg1,getChapter(msg.arg1).getChapterName());
|
|||
|
|
|||
|
|
|||
|
// isDownloadChapt =true;
|
|||
|
// Toast.makeText(mContext,"网络错误",Toast.LENGTH_LONG).show();
|
|||
|
}else if(msg.what==MSG_READCHAPTER_SUCCESS){ //change source
|
|||
|
isChangeSource =false;
|
|||
|
Log.d(TAG, "prepare book 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);
|
|||
|
|
|||
|
}
|
|||
|
*/
|
|||
|
}else if(msg.what==MSG_READBOOK_FAIL ) { //change source
|
|||
|
if(pagefactory!=null)
|
|||
|
pagefactory.drawStatus(PageFactory.Status.FAIL);
|
|||
|
}
|
|||
|
else if(msg.what==MSG_READBOOK_EMPTY_CONTENT ) { //change source
|
|||
|
if(pagefactory!=null)
|
|||
|
pagefactory.drawStatus(PageFactory.Status.CONTENTPARESERROR);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
private enum DownloadStatus{
|
|||
|
notStart,
|
|||
|
downloading,
|
|||
|
failure,
|
|||
|
success,
|
|||
|
emptyContent
|
|||
|
}
|
|||
|
|
|||
|
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()) {
|
|||
|
|
|||
|
new Thread(){
|
|||
|
@Override
|
|||
|
public void run() {
|
|||
|
try {
|
|||
|
loadChaptContent(index);
|
|||
|
} catch (JSONException e) {
|
|||
|
e.printStackTrace();
|
|||
|
} catch (InterruptedException e) {
|
|||
|
e.printStackTrace();
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}.start();
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
//获取chapter 缓存
|
|||
|
public char[] chaptChars(final int index) {
|
|||
|
// Log.d(TAG, String.format("prepare book begin to load content for chapter %s ------------------------------------------------------------------------->", index));
|
|||
|
char[] block=null;
|
|||
|
if(chaptCache.containsKey(Integer.valueOf(index))) {
|
|||
|
block = chaptCache .get(index).getData().get();
|
|||
|
// Log.d(TAG, String.format("chaptChars get block in cache, chapter: %s", index));
|
|||
|
|
|||
|
}
|
|||
|
// Log.d(TAG, String.format("prepare book begin to load content for chapter %s", index));
|
|||
|
if (block == null) {
|
|||
|
// cleanCacheFile(); //to remove
|
|||
|
try {
|
|||
|
File file = new File(fileChapterName(index));
|
|||
|
Log.d(TAG, String.format("prepare book begin to load content for chapter %s,file exists?%s", index,file.exists()));
|
|||
|
if ( !file.exists()) {
|
|||
|
if(getNovel().isLocalBook()){
|
|||
|
return "".toCharArray();
|
|||
|
}
|
|||
|
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()));
|
|||
|
|
|||
|
if (mMuluStatus == null) {
|
|||
|
Log.e(TAG, String.format("prepare book loadChapts---- 还未有目录信息,出错了 %s 目录, 目录数量 %s, MuluStatus %s ,thread %s", mNovel.getName(), mChapters.size(), mMuluStatus, Thread.currentThread().getName()));
|
|||
|
getTargetSites();
|
|||
|
}
|
|||
|
if( mChapters.size() ==0) {
|
|||
|
if (mMuluStatus != MuluStatus.isDownloading){
|
|||
|
getSiteRule();
|
|||
|
}
|
|||
|
}
|
|||
|
int maxSleep = Constants.MAX_SLEEP_4_CHAPT_DOWNLOAD;
|
|||
|
int slepttime = 0;
|
|||
|
|
|||
|
while (NetUtil.isNetworkConnected() && slepttime < maxSleep &&(mMuluStatus ==null || mMuluStatus == MuluStatus.isDownloading)) {
|
|||
|
try {
|
|||
|
Thread.sleep(50);
|
|||
|
slepttime+=50;
|
|||
|
Log.d(TAG, String.format("prepare book loadChapts----等待中 %s 目录, 目录数量 %s, slept %s, MuluStatus %s", mNovel.getName(), mChapters.size(), slepttime, mMuluStatus));
|
|||
|
|
|||
|
} catch (InterruptedException e) {
|
|||
|
e.printStackTrace();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
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(), slepttime, mMuluStatus, Thread.currentThread().getName()));
|
|||
|
String error = "网络不给力";
|
|||
|
return error.toCharArray();
|
|||
|
}
|
|||
|
|
|||
|
Log.d(TAG, String.format("prepare book loadChaptContent----start %s", new Date().toString()));
|
|||
|
Log.d(TAG, String.format("prepare book chaptDownStatus.containsKey %s ? %s", Integer.valueOf(index),chaptDownStatus.containsKey(Integer.valueOf(index))));
|
|||
|
|
|||
|
|
|||
|
if (!chaptDownStatus.containsKey(Integer.valueOf(index)) || !file.exists() &&chaptDownStatus.get(Integer.valueOf(index))== DownloadStatus.success ) {
|
|||
|
chaptDownStatus.put(index, DownloadStatus.downloading);
|
|||
|
Log.d(TAG, String.format("prepare book put chaptDownStatus index %s,start to load chapcontent", index));
|
|||
|
loadChaptContent(index);
|
|||
|
}else{
|
|||
|
Log.d(TAG, String.format("prepare book chaptDownStatus for chapt %s status %s", Integer.valueOf(index),chaptDownStatus.get(Integer.valueOf(index))));
|
|||
|
}
|
|||
|
Log.d(TAG, String.format(" prepare book loadChaptContent %s for downloading, chaptDownStatus %s, thread %s ",
|
|||
|
index, chaptDownStatus.get(Integer.valueOf(index)), Thread.currentThread().getName()));
|
|||
|
|
|||
|
|
|||
|
|
|||
|
slepttime = 0;
|
|||
|
// while(!file.exists() && !getDownloadStatus()){//&& slepttime <maxSleep){
|
|||
|
// while( !getDownloadStatus() && slepttime <maxSleep){
|
|||
|
|
|||
|
/* while (NetUtil.isNetworkConnected() && !getDownloadStatus() && chaptDownStatus.get(Integer.valueOf(index)) == DownloadStatus.downloading && slepttime < maxSleep) {
|
|||
|
Thread.sleep(50);
|
|||
|
slepttime += 50;
|
|||
|
Log.d(TAG, String.format(" prepare book loadChaptContent slept %s for downloading,isDownload %s ,thread %s ", slepttime, getDownloadStatus(), Thread.currentThread().getName()));
|
|||
|
}*/
|
|||
|
while (!file.exists() && NetUtil.isNetworkConnected() && chaptDownStatus.get(Integer.valueOf(index)) == DownloadStatus.downloading && slepttime < maxSleep ) {
|
|||
|
Thread.sleep(200);
|
|||
|
slepttime += 200;
|
|||
|
Log.d(TAG, String.format(" prepare book loadChaptContent %s , slept %s for downloading, thread %s ",index, slepttime, Thread.currentThread().getName()));
|
|||
|
}
|
|||
|
Log.d(TAG, String.format("prepare book loadChaptContent slept %s for downloading ", slepttime));
|
|||
|
|
|||
|
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);
|
|||
|
chaptDownStatus.put(index, DownloadStatus.downloading);
|
|||
|
if(mSiteRule!=null) {
|
|||
|
Thread.sleep(mSiteRule.getMiniInterval4AccessChapter());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Log.d(TAG, String.format(" prepare book %s, file.exists()? %s", file.getPath(), file.exists()));
|
|||
|
if (!file.exists()) {
|
|||
|
String error = "";
|
|||
|
if( !NetUtil.isNetworkConnected()){
|
|||
|
error = "";
|
|||
|
|
|||
|
}
|
|||
|
// loadChaptContent(index);
|
|||
|
chaptDownStatus.put( index , DownloadStatus.failure);
|
|||
|
|
|||
|
Log.d(TAG, String.format("prepare book loadChaptContent retrying " ));
|
|||
|
// return chaptChars( index);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
handler.sendEmptyMessage(MSG_READBOOK_FAIL);
|
|||
|
return error.toCharArray();
|
|||
|
}
|
|||
|
if( Constants.PRE_LOAD_CHAPT) {
|
|||
|
|
|||
|
|
|||
|
if (mChapters.size() > index && NetUtil.isNetworkConnected()) {
|
|||
|
|
|||
|
if (!chaptDownStatus.containsKey(index + 1) || chaptDownStatus.get(index + 1).equals(DownloadStatus.failure)) {
|
|||
|
|
|||
|
|
|||
|
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);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if (index > 1 && index - 1 < mChapters.size() && NetUtil.isNetworkConnected()) {
|
|||
|
|
|||
|
if (!chaptDownStatus.containsKey(index - 1) || chaptDownStatus.get(index - 1).equals(DownloadStatus.failure)) {
|
|||
|
File file2 = new File(fileChapterName(index - 1));
|
|||
|
|
|||
|
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);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
// mChangeChapId =0;
|
|||
|
int size = (int) file.length();
|
|||
|
if (size < 0) {
|
|||
|
Log.e(TAG, "prepare book chaptChars: Error during reading"+ fileChapterName(index) );
|
|||
|
// throw new RuntimeException("Error during reading " + fileChapterName(index));
|
|||
|
}
|
|||
|
block = new char[size / 2];
|
|||
|
InputStreamReader reader = null;
|
|||
|
try {
|
|||
|
reader =
|
|||
|
new InputStreamReader(
|
|||
|
new FileInputStream(file),
|
|||
|
charachterType
|
|||
|
// mSiteRule.getEncoding()
|
|||
|
);
|
|||
|
|
|||
|
long l = reader.read(block);
|
|||
|
|
|||
|
// Log.d(TAG, String.format("loadchapt: load from file chaptId %s,--->%s",index, new String(block )));
|
|||
|
/* for (char c :block
|
|||
|
) {
|
|||
|
Log.d(TAG, String.valueOf(c));
|
|||
|
}*/
|
|||
|
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();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} catch (JSONException | IOException e) {
|
|||
|
e.printStackTrace();
|
|||
|
} catch (InterruptedException e) {
|
|||
|
e.printStackTrace();
|
|||
|
}
|
|||
|
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));
|
|||
|
Log.d(TAG, String.format("prepare book content reading finish, chapter %s", index));
|
|||
|
}
|
|||
|
return block;
|
|||
|
}
|
|||
|
|
|||
|
boolean isHttpOrHttps(String url){
|
|||
|
if(TextUtils.isEmpty(url) || !url.toLowerCase().startsWith("http") && !url.toLowerCase().startsWith("https")){
|
|||
|
Log.d(TAG, String.format("prepare book isHttpOrHttps: url % is bad for request ",url));
|
|||
|
return false ;
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
Map<Integer,Integer> fileRetryCnt = new HashMap<Integer,Integer>();
|
|||
|
private void loadChaptContent(final int chapterIndex) throws JSONException, InterruptedException {
|
|||
|
/* 章节内容没有缓存在本地
|
|||
|
1. 根据本地的章节网络地址信息,读取章节内容到本地,若读取失败则
|
|||
|
2. 查询主服务器,若有地址更新则更新本地信息,并重复1,若没有更新地址,则地址无效,返回章节内容正待手打
|
|||
|
*/
|
|||
|
//
|
|||
|
if(!NetUtil.isNetworkConnected() || mChapters.size()==0||mSite ==null){
|
|||
|
handler.sendEmptyMessage(1);
|
|||
|
return ;
|
|||
|
}
|
|||
|
|
|||
|
final int index = mChapters.size() < chapterIndex ? 1 : chapterIndex;
|
|||
|
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() ));
|
|||
|
|
|||
|
}
|
|||
|
Chapter chapter = mChapters.get(index -1);
|
|||
|
String refUrl=mSite.getMuluUrl();
|
|||
|
if(index>1){
|
|||
|
refUrl = mChapters.get(index -2).getChapterUrl();
|
|||
|
}
|
|||
|
String url = chapter.getChapterUrl();
|
|||
|
if( TextUtils.isEmpty( url)){
|
|||
|
handler.sendEmptyMessage(1);
|
|||
|
return ;
|
|||
|
}
|
|||
|
long startTime= new Date().getTime();
|
|||
|
Log.d(TAG,String.format("prepare book loadChaptContent----start download %s from %s", chapter.getChapterName() ,url ));
|
|||
|
|
|||
|
// setDownloadFlag(false);
|
|||
|
|
|||
|
|
|||
|
JSONObject siteJson = new JSONObject();
|
|||
|
siteJson.put("chapterContentRegex", mSiteRule.getChapterContentRegex());
|
|||
|
siteJson.put("chapterContentDumpRegex", mSiteRule.getChapterContentDumpRegex());
|
|||
|
|
|||
|
if(!isHttpOrHttps(url)){
|
|||
|
return ;
|
|||
|
}
|
|||
|
|
|||
|
Request request = getTagRequest(url, refUrl,-1);
|
|||
|
|
|||
|
/*try {
|
|||
|
Response response = HttpMethods.getOkClient().newCall(request).execute();
|
|||
|
Log.d( TAG,String.format("prepare book loadChaptContent get response, thread %s", Thread.currentThread().getName()));
|
|||
|
ResponseBody body = response.body();
|
|||
|
if (body != null ) {
|
|||
|
|
|||
|
if(response.code()!=200){
|
|||
|
Log.d(TAG, "prepare book loadChaptContent----network failure returnCode " + response.code());
|
|||
|
// setDownloadFlag(true);
|
|||
|
chaptDownStatus.put(index,DownloadStatus.failure);
|
|||
|
Log.d( TAG,String.format("prepare book loadChaptContent error %s ,isDownloadChapt: %s", response.code(),false));
|
|||
|
handler.sendEmptyMessage(1);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
if(mSiteRule==null){
|
|||
|
return;
|
|||
|
}
|
|||
|
*//* Charset charset = body.contentType().charset();
|
|||
|
if(charset!=null){
|
|||
|
String name = charset.displayName();
|
|||
|
}*//*
|
|||
|
// String bodyStr = body.string();
|
|||
|
// bodyStr =NovelParseUtil.enconding(bodyStr,mSiteRule.getEncoding());
|
|||
|
|
|||
|
// Log.d( TAG,String.format("prepare book content %s", body ));
|
|||
|
|
|||
|
|
|||
|
String bodyStr =NovelParseUtil.enconding(body,mSiteRule.getEncoding());
|
|||
|
if(TextUtils.isEmpty(bodyStr)){
|
|||
|
Log.e( TAG,String.format("prepare book loadChaptContent %s isEmpty,retry....", index, Thread.currentThread().getName()));
|
|||
|
chaptDownStatus.put(index,DownloadStatus.failure);
|
|||
|
return;
|
|||
|
}
|
|||
|
// Log.d( TAG,String.format("prepare book encoded content %s", bodyStr ));
|
|||
|
bodyStr = NovelParseUtil.getChapterContent(bodyStr, siteJson);
|
|||
|
*//* if(BuildConfig.LOG_DEBUG) {
|
|||
|
reportMsg(Constants.REPORT_REX_CHAPTER_CONTENT_ERROR, url,"",getRequestHeader(request),200+"");//TODO: remove
|
|||
|
}*//*
|
|||
|
if(TextUtils.isEmpty(bodyStr) || bodyStr.trim().length()<10 ){
|
|||
|
Log.e( TAG,String.format("prepare book loadChaptContent %s isEmpty,reporting empty ....", index ));
|
|||
|
|
|||
|
reportMsg(Constants.REPORT_REX_CHAPTER_CONTENT_ERROR, url,bodyStr,getRequestHeader(request),200+"");
|
|||
|
chaptDownStatus.put(index,DownloadStatus.failure);
|
|||
|
// bodyStr += Constants.BAD_CHAR +Constants.BAD_CHAR +"内容正在搜索中,请稍后刷新内容";
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
String title = chapter.getChapterName();
|
|||
|
String chapterContent = title+ "\n" + bodyStr;
|
|||
|
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 文件小
|
|||
|
// final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(index)), mSiteRule.getEncoding() );//charachterType);//"UTF-16LE"); // UTF-16LE 比 utf-8 文件小
|
|||
|
writer.write(buf);
|
|||
|
writer.close();
|
|||
|
Log.d( TAG,String.format("prepare book loadChaptContent file created: %s, thread %s", file.getPath(), Thread.currentThread().getName()));
|
|||
|
handler.sendEmptyMessage(MSG_FILLCONTENTDONE);
|
|||
|
// setDownloadFlag(true);
|
|||
|
} 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));
|
|||
|
}
|
|||
|
finally {
|
|||
|
body.close();
|
|||
|
|
|||
|
handler.sendEmptyMessage(MSG_FILLCONTENTDONE);
|
|||
|
// setDownloadFlag(true);
|
|||
|
}
|
|||
|
chapter.setNovelId(mNovel.getId());
|
|||
|
chapter.setChapterPath(fileChapterName(index));
|
|||
|
chapter.setDomain(mSite.getDomain());
|
|||
|
if(chapter.getId()>0) {
|
|||
|
chapter.update(chapter.getId());
|
|||
|
}else{
|
|||
|
chapter.save();
|
|||
|
}
|
|||
|
//setDownloadFlag(true);
|
|||
|
chaptDownStatus.put(index,DownloadStatus.success);
|
|||
|
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() ));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} catch (IOException e) {
|
|||
|
|
|||
|
Log.e(TAG, "onResponse: prepare book error ",e );
|
|||
|
}*/
|
|||
|
|
|||
|
HttpMethods.getOkClient().newCall(request).enqueue(new Callback() {
|
|||
|
@Override
|
|||
|
public void onFailure(Call call, IOException e) {
|
|||
|
if(e!=null &&
|
|||
|
(e.toString().contains("closed")
|
|||
|
||e.getMessage()!=null && e.getMessage().contains("Canceled")))
|
|||
|
{
|
|||
|
Log.d(TAG, "onFailure: prepare book cancled request ,return, " + request.url());
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// handler.sendEmptyMessage(MSG_FILLCONTENTDONE);
|
|||
|
// handler.sendEmptyMessage(1);
|
|||
|
|
|||
|
|
|||
|
chaptDownStatus.put(index,DownloadStatus.failure);
|
|||
|
// setDownloadFlag(true);
|
|||
|
Log.e( TAG,String.format("prepare book loadChaptContent %s fail, isDownloadChapt: %s",index,false),e);
|
|||
|
// e.printStackTrace();
|
|||
|
// throw new RuntimeException("Error during writing " + fileChapterName( index));
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onResponse(Call call, Response response){
|
|||
|
Log.d( TAG,String.format("prepare book loadChaptContent get response, thread %s", Thread.currentThread().getName()));
|
|||
|
ResponseBody body = response.body();
|
|||
|
if (body != null ) {
|
|||
|
|
|||
|
if(response.code()!=200){
|
|||
|
Log.d(TAG, "prepare book loadChaptContent----network failure returnCode " + response.code());
|
|||
|
// setDownloadFlag(true);
|
|||
|
chaptDownStatus.put(index,DownloadStatus.failure);
|
|||
|
Log.d( TAG,String.format("prepare book loadChaptContent error %s ,isDownloadChapt: %s", response.code(),false));
|
|||
|
handler.sendEmptyMessage(1);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
if(mSiteRule==null){
|
|||
|
return;
|
|||
|
}
|
|||
|
Charset charset = body.contentType().charset();
|
|||
|
if(charset!=null){
|
|||
|
String name = charset.displayName();
|
|||
|
}
|
|||
|
// String bodyStr = body.string();
|
|||
|
// bodyStr =NovelParseUtil.enconding(bodyStr,mSiteRule.getEncoding());
|
|||
|
|
|||
|
// Log.d( TAG,String.format("prepare book content %s", body ));
|
|||
|
|
|||
|
|
|||
|
String bodyStr =NovelParseUtil.enconding(body,mSiteRule.getEncoding());
|
|||
|
if(TextUtils.isEmpty(bodyStr)){
|
|||
|
Log.e( TAG,String.format("prepare book loadChaptContent %s isEmpty,retry....", index, Thread.currentThread().getName()));
|
|||
|
chaptDownStatus.put(index,DownloadStatus.failure);
|
|||
|
return;
|
|||
|
}
|
|||
|
// Log.d( TAG,String.format("prepare book encoded content %s", bodyStr ));
|
|||
|
bodyStr = NovelParseUtil.getChapterContent(bodyStr, siteJson);
|
|||
|
/* if(BuildConfig.LOG_DEBUG) {
|
|||
|
reportMsg(Constants.REPORT_REX_CHAPTER_CONTENT_ERROR, url,"",getRequestHeader(request),200+"");//TODO: remove
|
|||
|
}*/
|
|||
|
if(TextUtils.isEmpty(bodyStr) || bodyStr.trim().length()<10 ){
|
|||
|
Log.e( TAG,String.format("prepare book loadChaptContent %s isEmpty,reporting empty ....", index ));
|
|||
|
|
|||
|
reportMsg(Constants.REPORT_REX_CHAPTER_CONTENT_ERROR, url,bodyStr,getRequestHeader(request),200+"");
|
|||
|
chaptDownStatus.put(index,DownloadStatus.failure);
|
|||
|
// bodyStr += Constants.BAD_CHAR +Constants.BAD_CHAR +"内容正在搜索中,请稍后刷新内容";
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
String title = chapter.getChapterName();
|
|||
|
String chapterContent = title+ "\n" + bodyStr;
|
|||
|
char[] buf = chapterContent.toCharArray();
|
|||
|
File file = new File(fileChapterName(index));
|
|||
|
Log.d( TAG,"prepare book to create file " +fileChapterName(index));
|
|||
|
file.createNewFile();
|
|||
|
|
|||
|
final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(index)), charachterType);//"UTF-16LE"); // UTF-16LE 比 utf-8 文件小
|
|||
|
// final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(index)), mSiteRule.getEncoding() );//charachterType);//"UTF-16LE"); // UTF-16LE 比 utf-8 文件小
|
|||
|
writer.write(buf);
|
|||
|
writer.close();
|
|||
|
Log.d( TAG,String.format("prepare book loadChaptContent file created: %s, thread %s", file.getPath(), Thread.currentThread().getName()));
|
|||
|
handler.sendEmptyMessage(MSG_FILLCONTENTDONE);
|
|||
|
// setDownloadFlag(true);
|
|||
|
} 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));
|
|||
|
}
|
|||
|
finally {
|
|||
|
body.close();
|
|||
|
|
|||
|
handler.sendEmptyMessage(MSG_FILLCONTENTDONE);
|
|||
|
// setDownloadFlag(true);
|
|||
|
}
|
|||
|
chapter.setNovelId(mNovel.getId());
|
|||
|
chapter.setChapterPath(fileChapterName(index));
|
|||
|
chapter.setDomain(mSite.getDomain());
|
|||
|
if(chapter.getId()>0) {
|
|||
|
chapter.update(chapter.getId());
|
|||
|
}else{
|
|||
|
chapter.save();
|
|||
|
}
|
|||
|
//setDownloadFlag(true);
|
|||
|
chaptDownStatus.put(index,DownloadStatus.success);
|
|||
|
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() ));
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/***
|
|||
|
*
|
|||
|
* @param url
|
|||
|
* @param maxAge
|
|||
|
* @return
|
|||
|
*/
|
|||
|
private Request getTagRequest(String url, String refUrl ,int maxAge) {
|
|||
|
|
|||
|
try {
|
|||
|
Request.Builder builder = new Request.Builder()
|
|||
|
.tag(mNovel.getNovelId()) //标记 请求的tag,切换小说或离开小说界面(BookActivity) 时 取消未执行完毕的 此tag的所有请求
|
|||
|
.url(url)
|
|||
|
.removeHeader("Pragma");
|
|||
|
|
|||
|
if (!TextUtils.isEmpty(refUrl)) {
|
|||
|
builder.header("Referer", refUrl);
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i < mSiteRule.getHeaders().length; i += 2) {
|
|||
|
builder.header(mSiteRule.getHeaders()[i], mSiteRule.getHeaders()[i + 1]);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (mSiteRule.getUserAgents() != null && mSiteRule.getUserAgents().length > 0) {
|
|||
|
String siteAgent = mSiteRule.getUserAgents()[new Random().nextInt(mSiteRule.getUserAgents().length - 1)];
|
|||
|
|
|||
|
Log.d(TAG, "prepare book on getTagRequest:add site user agent " + siteAgent);
|
|||
|
builder.removeHeader("User-Agent").addHeader("User-Agent", siteAgent); //加 随机agent
|
|||
|
|
|||
|
} else {
|
|||
|
builder.removeHeader("User-Agent").addHeader("User-Agent", HttpMethods.USERAGENT);
|
|||
|
}
|
|||
|
|
|||
|
if (maxAge > 0) {
|
|||
|
builder.header("Cache-Control", "public, max-age=" + maxAge);
|
|||
|
}
|
|||
|
return builder.build();
|
|||
|
}catch (Exception er){
|
|||
|
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
private String getRequestHeader(Request request) {
|
|||
|
|
|||
|
String head = String.format("\"Referer\":\"%s\",\"User-Agent\":\"%s\",\"Cache-Control\":\"%s\"",
|
|||
|
request.header("Referer"),request.header("User-Agent"), request.header("Cache-Control")
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
for (int i = 0; i < mSiteRule.getHeaders().length; i += 2) {
|
|||
|
|
|||
|
head += String.format(",\"%s\":\"%s\"",mSiteRule.getHeaders()[i], mSiteRule.getHeaders()[i + 1]) ;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return "{" + head +"}";
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public boolean isChapterTitle(String line){
|
|||
|
return (line.length() <= 30 && (line.matches(".*第.{1,8}章.*") || line.matches(".*第.{1,8}节.*"))) ;
|
|||
|
}
|
|||
|
|
|||
|
void clear(){
|
|||
|
clearBook();
|
|||
|
mContext=null;
|
|||
|
this.pagefactory =null;
|
|||
|
|
|||
|
}
|
|||
|
}
|