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

1030 lines
36 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.novelbook.android.utils;
import android.app.ProgressDialog;
import android.content.ContentValues;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.google.gson.Gson;
import com.novelbook.android.BookActivity;
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.OnSuccessAndFaultListener;
import com.novelbook.android.netutils.OnSuccessAndFaultSub;
import org.json.JSONException;
import org.json.JSONObject;
import org.litepal.LitePal;
import java.io.Console;
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;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
public class BookUtil {
public static final String TAG ="BookUtil";
private static final String storagePath = FileUtils.getDiskCacheDir(MyApp.applicationContext);//Environment.getExternalStorageDirectory() + "/zhuike";
private static final String cachedPath = storagePath + "/cache/";
private static final String chapterPath = storagePath + "/chapter/";
private static final String charachterType = "utf-8";//"UTF-16LE";
private Context mContext;
private ProgressDialog progressDialog;
private MuluStatus mMuluStatus; //目录是否下载完成
private Gson gson = new Gson();
public void setContext(Context context) {
this.mContext = context;
}
//存储的字符数
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 String m_strCharsetName;
private String bookName;
private String bookPath;
public void setBookLen(long bookLen) {
this.bookLen = bookLen;
}
private long bookLen;
private long position;
private Novel mNovel;
public void setNovel(Novel novel) {
this.mNovel = novel;
}
//当前目录网站列表
private NovelSites mNovelSites;
//当前目录网站
private Site mSite;
private SiteRule mSiteRule;
public void setNovelSites(NovelSites nvs) {
this.mNovelSites = nvs;
if(nvs.getSites().length ==0){
return;
}
mSite =nvs.getSites()[0];
if(nvs.getSites().length > 0)
for (Site site:nvs.getSites() ) {
if(site.getSelectedByDefault()){
mSite = site;
break;
}
}
getSiteRule();
}
private void setSiteInfo() {
File file = new File(getChapterPath() +mSite.getDomain());
if(!file.exists()){
file.mkdir();
}
mNovel.setDomain(mSite.getDomain());
mNovel.setMuluUrl(mSite.getMuluUrl());
mNovel.update(mNovel.getId());
}
public void getTargetSites(){
BookSubscribe.getNovelSites(mNovel.getNovelId(),new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() {
@Override
public void onSuccess(String result) {
//成功
try {
NovelSites nvs = (NovelSites) gson.fromJson(result,NovelSites.class);
//pageFactory.prepareBook(mNovel,nvs, BookActivity.this);
setNovelSites(nvs);
} catch ( Exception e) {
e.printStackTrace();
}
// Toast.makeText(mContext,"getMuluInfo 请求成功 " ,Toast.LENGTH_SHORT).show();
}
@Override
public void onFault(String errorMsg) {
//失败
// Toast.makeText(mContext,"getMuluInfo 请求失败"+errorMsg,Toast.LENGTH_SHORT).show();
}
},null));
}
private void getSiteRule() {
mSiteRule = null;
BookSubscribe.getSiteRule(mSite.getDomain(),new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() {
@Override
public void onSuccess(String result) {
//成功
SiteRule sr = (SiteRule)gson.fromJson(result,SiteRule.class);
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;
setSiteInfo();
readChaptersAsync();
}
@Override
public void onFault(String errorMsg) {
//失败
Log.d(TAG,"error on get sitRule: "+errorMsg);
}
},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);
}
}*/
}
public void setChapterNo(int chapterNo) {
this.chapterNo = chapterNo;
}
public int getChapterNo() {
return chapterNo;
}
private int chapterNo;//当前章节
public String getLineBreakChar(){
return "\n";
}
public BookUtil(){
checkAndCreateDir(storagePath);
checkAndCreateDir(chapterPath);
checkAndCreateDir(cachedPath);
}
enum MuluStatus{
isDownloading,
isDone,
failed
}
private void showProgressDialog() {
if ( null == progressDialog) {
progressDialog =new ProgressDialog(mContext);
}
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();
}
}
public synchronized void openBook(Novel novel) throws IOException, InterruptedException {
this.mNovel = novel;
//如果当前缓存不是要打开的书本就缓存书本同时删除缓存
//TODO 构建新的缓存策略几个选项1每本书一个缓存 2控制缓存总大小超过限制删除旧缓存 3网络小说的缓存
boolean isLocalImport = TextUtils.isEmpty( novel.getNovelId());
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{ //读取目录列表
MuluStatus m = mMuluStatus;
// Log.d(TAG,String.format("mulu on Site %s download status %s",mSite.getDomain(),mMuluStatus));
while(mMuluStatus == MuluStatus.isDownloading){
Thread.sleep(50);
Log.d(TAG,String.format("waiting for mulu downloading ,mMuluStatus %s" ,mMuluStatus));
if(mMuluStatus == MuluStatus.failed){
dismissProgressDialog();
throw new RuntimeException("读取资源失败,请检查网络");
}
}
}
// dismissProgressDialog();
}
// String getMuluUrl() {
// return "https://www.qu.la/book/390/";
// }
/* void readChapters( String url){
Request request = getTagRequest(url);
ResponseBody body =null;
try {
long startTime= new Date().getTime();
Log.d(TAG,String.format("loadChaptContent----start download %s 目录 from %s", mNovel.getName() ,url ));
Response response = HttpMethods.getOkClient().newCall(request).execute();
Log.d(TAG,String.format("loadChaptContent----end download %s 目录, 目录数量 %s, cost %s", mNovel.getName() , mChapters.size(), new Date().getTime() -startTime ));
startTime= new Date().getTime();
body = response.body();
String bodyStr = body.string();
Log.d(TAG, "onResponse: " +bodyStr);
buildCharacters(bodyStr,url);
Log.d(TAG,String.format("loadChaptContent----end build %s 目录, 目录数量 %s, cost %s", mNovel.getName() , mChapters.size(), new Date().getTime() -startTime ));
} catch (IOException e) {
e.printStackTrace();
}finally {
if(body!=null){
body.close();;
}
}
}*/
void readChaptersAsync( ) {
String url = mSite.getMuluUrl();
Request request = getTagRequest(url);
mMuluStatus = MuluStatus.isDownloading;
long startTime= new Date().getTime();
Log.d(TAG,String.format("loadChaptContent----start download %s 目录 from %s", mNovel.getName() ,url ));
HttpMethods.getOkClient().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: " + e.getMessage());
if( mNovelSites.getSites().length ==1){ //仅有一个rule,且失败了
mMuluStatus = MuluStatus.failed;
return;
}
//try next site
for(Site st : mNovelSites.getSites() ){
if(!st.getDomain().equals(mSite.getDomain())){
mSite =st;
break;
}
}
// readChaptersAsync();
getSiteRule();
}
@Override
public void onResponse(Call call, Response response){
ResponseBody body = response.body();
if(response.code()!=200){
mMuluStatus = MuluStatus.failed;
return;
}
if (body != null) {
try {
String bodyStr = body.string();
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();
buildCharacters(bodyStr,url);
Log.d(TAG,String.format("loadChaptContent----end download %s 目录, 目录数量 %s, cost %s", mNovel.getName() , mChapters.size(), new Date().getTime() -startTime2 ));
mMuluStatus = MuluStatus.isDone;
} catch (IOException e) {
e.printStackTrace();
}finally {
body.close();
}
}
}
});
}
void buildCharacters( String content ,String url){
try {
JSONObject siteJson = new JSONObject();
siteJson.put("chapterUrlPattern", mSiteRule.getChapterUrlPattern());
siteJson.put("chapterUrlRegexOnMulu", mSiteRule.getChapterUrlRegexOnMulu());//示例接口表达式有问题
siteJson.put("chapterUrlRegexOnMulu", "<dd> <a[^>]*href=\"(/book/[\\d]+/[\\d]+\\.html)\">([^<]+)</a></dd>");
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 != null) {
int lastReadChapt = mNovel.getLastReadChapt();
// int index =lastReadChapt*2-2;
lastReadChapt = lastReadChapt >=mChapters.size() ? mChapters.size() -1:lastReadChapt;
lastReadChapt = lastReadChapt <=0 ? 1:lastReadChapt;
mCurrentChapter =mChapters.get(lastReadChapt-1);
}*/
} catch (JSONException e) {
// } catch (JSONException | IOException e) {
Log.d(TAG,String.format("mulu on Site %s download status %s",mSite.getDomain(),mMuluStatus));
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){
position += 1;
if (position > bookLen){
position = bookLen;
return -1;
}
char result = chaptCurrent(); //current();
if (back) {
position -= 1;
}
return result;
}
public char[] nextLine(){
if (position >= bookLen){
return null;
}
String line = "";
while (position < bookLen){
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(){
char[] charArray = chaptChars(chapterNo);
return charArray[(int)position-1];
}
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 {
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();
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.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 getBookLen(){
return bookLen;
}
protected String fileName(int index) {
return cachedPath + mNovel.getName() + index ;
}
protected String fileChapterName(int chaptId ) {
if(!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("loadChaptContent",String.format("set download flat",isDownloadChapt) );
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
int wt = msg.what;
dismissProgressDialog();
if (msg.what == 123) {
isDownloadChapt =true;
Log.d("loadChaptContent",String.format("handler msg, download %s",isDownloadChapt) );
}else if(msg.what==1){
isDownloadChapt =true;
Toast.makeText(mContext,"网络错误",Toast.LENGTH_LONG).show();
}
}
};
private Map<Integer,Cache> chaptCache = new HashMap<Integer,Cache>();
//获取chapter 缓存
public char[] chaptChars(int index) {
char[] block=null;
if(chaptCache.containsKey(Integer.valueOf(index))) {
block = chaptCache .get(index).getData().get();
}
if (block == null) {
// cleanCacheFile(); //to remove
try {
File file = new File(fileChapterName(index));
if(!file.exists()) {
if(mChapters ==null || mChapters.size() ==0){
String error = "网络错误";
return error.toCharArray();
}
Log.d(TAG,String.format("loadChaptContent----start %s" ,new Date().toString() ));
//showProgressDialog();//why not show
Log.d( "loadChaptContent",String.format("begin to load content for chapter %s",index));
Log.d( "loadChaptContent",String.format("isDownloadChapt: %s",isDownloadChapt));
if(getDownloadStatus() ) {
loadChaptContent(index);
}
Log.d( "loadChaptContent",String.format("showing dialog " ));
// Log.d(TAG,String.format("showing progress diaglog......"));
int maxSleep =6000;
int slepttime =0;
// while(!file.exists() && !getDownloadStatus()){//&& slepttime <maxSleep){
while( !getDownloadStatus() && slepttime <maxSleep){
Thread.sleep(50);
slepttime+=50;
Log.d("loadChaptContent",String.format("loadChaptContent slept %s for downloading,isDownload %s ",slepttime,getDownloadStatus() ) );
}
Log.d("loadChaptContent",String.format("loadChaptContent slept %s for downloading ",slepttime ) );
Log.d( "loadChaptContent",String.format("dismissing dialog " ));
dismissProgressDialog();
Log.d(TAG,String.format("loadChaptContent slept %s for downloading chaptercontent ",slepttime ));
}
Log.d( "loadChaptContent",String.format(" %s, file.exists()? %s", file.getPath(),file.exists()));
if(!file.exists()) {
String error = "万里长城";
return error.toCharArray();
}
if(mChapters.size() > index ) {
File file2 = new File(fileChapterName(index+1));
if(!file2.exists()) {
loadChaptContent(index + 1);
}
}
int size = (int)file.length();
if (size < 0) {
throw new RuntimeException("Error during reading " + fileChapterName(index));
}
block = new char[size / 2];
InputStreamReader 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));
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Error during reading " + fileChapterName(index));
} catch (JSONException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
dismissProgressDialog();
}
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;
}
private void loadChaptContent(int index) throws JSONException, InterruptedException {
/* 章节内容没有缓存在本地
1. 根据本地的章节网络地址信息,读取章节内容到本地,若读取失败则
2. 查询主服务器若有地址更新则更新本地信息并重复1若没有更新地址则地址无效返回章节内容正待手打
*/
//
Chapter chapter = mChapters.get(index -1);
String url = chapter.getChapterUrl();
if( TextUtils.isEmpty( url)){
return ;
}
long startTime= new Date().getTime();
Log.d(TAG,String.format("loadChaptContent----start download %s from %s", chapter.getChapterName() ,url ));
setDownloadFlag(false);
Log.d( "loadChaptContent",String.format("loadChaptContent isDownloadChapt: %s",isDownloadChapt));
JSONObject siteJson = new JSONObject();
siteJson.put("chapterContentRegex", mSiteRule.getChapterContentRegex());
siteJson.put("chapterContentDumpRegex", mSiteRule.getChapterContentDumpRegex());
Request request = getTagRequest(url);
HttpMethods.getOkClient().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
handler.sendEmptyMessage(123);
handler.sendEmptyMessage(1);
setDownloadFlag(true);
Log.d( "loadChaptContent",String.format("loadChaptContent fail, isDownloadChapt: %s",isDownloadChapt));
e.printStackTrace();
// throw new RuntimeException("Error during writing " + fileChapterName( index));
}
@Override
public void onResponse(Call call, Response response){
ResponseBody body = response.body();
if (body != null ) {
if(response.code()!=200){
Log.d(TAG, "loadChaptContent----network failure returnCode " + response.code());
setDownloadFlag(true);
Log.d( "loadChaptContent",String.format("loadChaptContent error %s ,isDownloadChapt: %s", response.code(),isDownloadChapt));
handler.sendEmptyMessage(1);
return;
}
try {
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();
Log.d( "loadChaptContent",String.format("loadChaptContent file created: %s", file.getPath()));
handler.sendEmptyMessage(123);
setDownloadFlag(true);
} catch (IOException | JSONException e) {
e.printStackTrace();
throw new RuntimeException("Error during writing " + fileChapterName( index));
}
finally {
body.close();
handler.sendEmptyMessage(123);
setDownloadFlag(true);
}
chapter.setNovelId(mNovel.getId());
chapter.setChapterPath(fileChapterName(index));
chapter.save();
setDownloadFlag(true);
Log.d(TAG,String.format("loadChaptContent---- finished download %s, cost time %s ,content path %s ", chapter.getChapterName(), new Date().getTime() -startTime ,chapter.getChapterPath() ));
}
}
});
}
private Request getTagRequest(String url) {
return new Request.Builder()
.tag(mNovel.getNovelId()) //标记 请求的tag,切换小说或离开小说界面(BookActivity) 时 取消未执行完毕的 此tag的所有请求
.url(url)
// .header("User-Agent", "OkHttp Example")
.build();
}
public boolean isChapterTitle(String line){
return (line.length() <= 30 && (line.matches(".*第.{1,8}章.*") || line.matches(".*第.{1,8}节.*"))) ;
}
}