1876 lines
		
	
	
		
			73 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
		
		
			
		
	
	
			1876 lines
		
	
	
		
			73 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.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.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 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; | |||
|  | 
 | |||
|  |     public void setNovel(Novel novel) { | |||
|  |         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>(); | |||
|  |     private   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("书本错误 code 001"); //无目标网站 | |||
|  |            // return; | |||
|  |         } | |||
|  | 
 | |||
|  |         if(nvs.getSites().length > 0){ | |||
|  |             for (Site site:nvs.getSites() ) { | |||
|  |                 if(!TextUtils.isEmpty(mNovel.getDomain()) && site.getDomain().equals(mNovel.getDomain())){ | |||
|  |                     mSite = site; | |||
|  |                     break; | |||
|  |                 } | |||
|  |             } | |||
|  | 
 | |||
|  |             if(mSite ==null) | |||
|  |                 for (Site site:nvs.getSites() ) { | |||
|  |                     if(site.getSelectedByDefault()){ | |||
|  |                         mSite = site; | |||
|  |                         break; | |||
|  |                     } | |||
|  |                 } | |||
|  |             if(mSite ==null) | |||
|  |                 mSite =nvs.getSites()[0]; | |||
|  |         } | |||
|  |          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.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() { | |||
|  |         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("目录正则表达式下载完成,开始读取章节信息") ); | |||
|  | 
 | |||
|  |                 if(mSiteRule.getChapterUrlRegexOnMulu().length>0) { | |||
|  |                     mMuluStatus = MuluStatus.isDownloading; | |||
|  |                     long startTime= new Date().getTime(); | |||
|  |                     Log.d(TAG,String.format("prepare book loadChapts----start download %s,maxAge %s,  目录 from %s",  mNovel.getName() ,mNovel.getMaxAge() ,mSite.getMuluUrl() )); | |||
|  |                     new Thread(){ | |||
|  |                         @Override | |||
|  |                         public void run() { | |||
|  |                             Log.d(TAG, "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(),mNovel.getMaxAge(),mSiteRule); | |||
|  | 
 | |||
|  |                                /* if (mChapters != null){ | |||
|  |                                     for (Chapter chapter:mChapters) { | |||
|  |                                         Log.i(TAG,   String.format("prepare book to get chaps readChaptersAsync %s-->%s",chapter.getChapterUrl(), chapter.getChapterName())); | |||
|  |                                     } | |||
|  |                                 }*/ | |||
|  | 
 | |||
|  | 
 | |||
|  |                             } catch (JSONException e) { | |||
|  |                                 Log.e(TAG, "prepare book error on parese :", e); | |||
|  |                             } | |||
|  | 
 | |||
|  |                             if (mChapters == null ||mChapters.size()== 0) { | |||
|  |                                 readChaptersAsync(); | |||
|  |                             }else | |||
|  |                             { | |||
|  |                                 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 )); | |||
|  |                                 mMuluStatus = MuluStatus.isDone; | |||
|  |                                 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); | |||
|  |             } | |||
|  |         }*/ | |||
|  | 
 | |||
|  |     } | |||
|  | 
 | |||
|  |     public void setChapterNo(int chapterNo) { | |||
|  |         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; | |||
|  |         } | |||
|  |         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(); | |||
|  |         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); | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  |     } | |||
|  | 
 | |||
|  |     private void clearBook() { | |||
|  |         charPosition.clear(); | |||
|  |         this.muluRetryCount=0; | |||
|  |         this.downloadStatus = DownloadStatus.notStart; | |||
|  |         chaptDownStatus.clear(); | |||
|  |         chaptCache.clear(); | |||
|  |         fileRetryCnt.clear(); | |||
|  |         siteRuleRetryCnt=0; | |||
|  |         caprint.clear(); | |||
|  |     } | |||
|  | 
 | |||
|  |     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)){ | |||
|  |            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{ | |||
|  |             chaptDownStatus.put(chaptId,DownloadStatus.downloading); | |||
|  |             fileRetryCnt.put(chaptId,11 ); | |||
|  |         } | |||
|  | 
 | |||
|  |         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(); | |||
|  |         } | |||
|  |         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;//TODO: mChangeChapId 换源时不要变 | |||
|  |                 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 <200){ | |||
|  |                 try { | |||
|  |                     Thread.sleep(50); | |||
|  |                     splet++; | |||
|  |                     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( ) { | |||
|  |         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(); | |||
|  |         Request request = getTagRequest(url,REUtil.getDomain(url), mNovel.getMaxAge()); | |||
|  | 
 | |||
|  |         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; | |||
|  | 
 | |||
|  |                     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(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(); | |||
|  |                     } | |||
|  |                     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)); | |||
|  |            if( mChapters.size()> mNovel.getChaptCnt()){ | |||
|  |                mNovel.setChaptCnt(mChapters.size()); | |||
|  |                mNovel.update(mNovel.getId()); | |||
|  |            } | |||
|  | 
 | |||
|  |         } 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(); | |||
|  |         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 ) { | |||
|  |         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); | |||
|  | 
 | |||
|  |              } | |||
|  |              */ | |||
|  |          } | |||
|  |      } | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  |  private enum DownloadStatus{ | |||
|  |      notStart, | |||
|  |      downloading, | |||
|  |      failure, | |||
|  |      success | |||
|  |  } | |||
|  | 
 | |||
|  |  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; | |||
|  |  } | |||
|  | 
 | |||
|  |     List<Integer> caprint = new ArrayList<Integer>(); | |||
|  | 
 | |||
|  |     //获取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)); | |||
|  | 
 | |||
|  |             if(!caprint.contains(index)) { | |||
|  |                 caprint.add(index); | |||
|  |              //   Log.d(TAG, String.format("chaptChars: load from cache chaptId %s,--->%s", index, new String(block))); | |||
|  |             } | |||
|  |         } | |||
|  |       //  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 slept = 0; | |||
|  |                     while (NetUtil.isNetworkConnected() && slept < 50 &&(mMuluStatus ==null || mMuluStatus == MuluStatus.isDownloading)) { | |||
|  |                         try { | |||
|  |                             Thread.sleep(50); | |||
|  |                             slept++; | |||
|  |                             Log.d(TAG, String.format("prepare book loadChapts----等待中 %s  目录, 目录数量 %s, slept %s, MuluStatus %s", mNovel.getName(), mChapters.size(), slept, 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(), slept, 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))) { | |||
|  |                         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())); | |||
|  | 
 | |||
|  | 
 | |||
|  |                     int maxSleep = 10000; | |||
|  |                     int 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(50); | |||
|  |                         slepttime += 50; | |||
|  |                         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); | |||
|  | 
 | |||
|  | 
 | |||
|  |                     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; | |||
|  |     } | |||
|  | 
 | |||
|  |     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()); | |||
|  |     Request request = getTagRequest(url, refUrl,-1); | |||
|  |     HttpMethods.getOkClient().newCall(request).enqueue(new Callback() { | |||
|  |         @Override | |||
|  |         public void onFailure(Call call, IOException e) { | |||
|  |            /* if(e.toString().contains("closed") ||e.getMessage().contains("Canceled")) | |||
|  |             { | |||
|  |                // return; | |||
|  |             }*/ | |||
|  | 
 | |||
|  |          //   handler.sendEmptyMessage(MSG_FILLCONTENTDONE); | |||
|  |         //    handler.sendEmptyMessage(1); | |||
|  | 
 | |||
|  | 
 | |||
|  |             chaptDownStatus.put(index,DownloadStatus.failure); | |||
|  |           //  setDownloadFlag(true); | |||
|  |             Log.d( TAG,String.format("prepare book loadChaptContent %s fail, isDownloadChapt: %s",index,false)); | |||
|  |            // 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, "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()); | |||
|  |                     String   bodyStr =NovelParseUtil.enconding(body,mSiteRule.getEncoding()); | |||
|  |                   if(TextUtils.isEmpty(bodyStr)){ | |||
|  |                       Log.d( TAG,String.format("prepare book  loadChaptContent %s isEmpty,retry....", index,   Thread.currentThread().getName())); | |||
|  |                       chaptDownStatus.put(index,DownloadStatus.failure); | |||
|  |                       return; | |||
|  |                   } | |||
|  |                     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 文件小 | |||
|  |                   //  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) { | |||
|  | 
 | |||
|  |         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); | |||
|  |         } | |||
|  | 
 | |||
|  | //                .header( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8") | |||
|  | //                .header( "Upgrade-Insecure-Requests", "1") | |||
|  |         //   .header("content-type", "text/html; charset=utf-8") | |||
|  |         //   .header("Content-Type", "text/plain; charset=utf-8") | |||
|  |         //   .header( "Accept", "*/*") | |||
|  |         ; | |||
|  |        /* if(mSiteRule!=null && !TextUtils.isEmpty(mSiteRule.getEncoding())  ){ | |||
|  |             builder.header("Accept-Encoding",mSiteRule.getEncoding()); | |||
|  |         } | |||
|  | */ | |||
|  |         if (maxAge > 0) { | |||
|  |             builder.header("Cache-Control", "public, max-age=" + maxAge); | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  |         return builder.build(); | |||
|  | 
 | |||
|  |     } | |||
|  | 
 | |||
|  | 
 | |||
|  |     public boolean isChapterTitle(String line){ | |||
|  |         return (line.length() <= 30 && (line.matches(".*第.{1,8}章.*") || line.matches(".*第.{1,8}节.*")))  ; | |||
|  |     } | |||
|  | 
 | |||
|  | 
 | |||
|  | } |