parent
							
								
									96f8998920
								
							
						
					
					
						commit
						dfbd75e655
					
				|  | @ -2,7 +2,7 @@ | |||
| <litepal> | ||||
|     <dbname value="book" ></dbname> | ||||
| 
 | ||||
|     <version value="9" ></version> | ||||
|     <version value="11" ></version> | ||||
| 
 | ||||
|     <list> | ||||
|         <mapping class="com.novelbook.android.db.Chapter"></mapping> | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ package com.novelbook.android.Fragments; | |||
| 
 | ||||
| import android.app.ProgressDialog; | ||||
| import android.os.Bundle; | ||||
| import android.support.v4.widget.SwipeRefreshLayout; | ||||
| import android.support.v7.widget.LinearLayoutManager; | ||||
| import android.text.TextUtils; | ||||
| import android.util.Log; | ||||
|  | @ -68,7 +69,7 @@ public class CatalogFragment extends BasicFragment implements MarkActivity.Sortc | |||
|     boolean isFirstLoad = true; | ||||
|     @Override | ||||
|     protected  void fillData() { | ||||
|         catalogueList.clear(); | ||||
| 
 | ||||
|         catalogueList.addAll(pageFactory.getChapters()); | ||||
| 
 | ||||
|        // int currentChp =pageFactory.getCurrentChapter()-1; | ||||
|  | @ -78,10 +79,8 @@ public class CatalogFragment extends BasicFragment implements MarkActivity.Sortc | |||
|             currentChp = catalogueList.size() -currentChp-1; | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         catalogueAdapter = new CatalogueAdapter(getContext(), catalogueList); | ||||
|         catalogueAdapter.setData(catalogueList); | ||||
|         catalogueAdapter.setCharter(currentChp+1); | ||||
|         lv_catalogue.setAdapter(catalogueAdapter); | ||||
|         catalogueAdapter.setCahedChapters(catalogCached); | ||||
|         catalogueAdapter.notifyDataSetChanged(); | ||||
| 
 | ||||
|  | @ -102,8 +101,9 @@ public class CatalogFragment extends BasicFragment implements MarkActivity.Sortc | |||
|     } | ||||
| 
 | ||||
| @OnClick(R.id.btnRefresh) | ||||
|     void refresh(View view){ | ||||
|     loadData() ; | ||||
|     void refresh(View view) { | ||||
|     pageFactory.refreshCate(); | ||||
|     loadData(); | ||||
| } | ||||
| 
 | ||||
|     ArrayList<Chapter> revertArray(){ | ||||
|  | @ -144,6 +144,10 @@ public class CatalogFragment extends BasicFragment implements MarkActivity.Sortc | |||
|     public void loadData(){ | ||||
|         showProgressDialog(false,"请稍等"); | ||||
| 
 | ||||
|         catalogueList.clear(); | ||||
|         catalogueAdapter = new CatalogueAdapter(getContext(), catalogueList); | ||||
| 
 | ||||
|         lv_catalogue.setAdapter(catalogueAdapter); | ||||
|         Log.d(TAG, String .format("prepare book: start to open book cate of  %s" ,  pageFactory.getNovle().getName())); | ||||
| 
 | ||||
|         new Thread() { | ||||
|  | @ -219,9 +223,23 @@ public class CatalogFragment extends BasicFragment implements MarkActivity.Sortc | |||
|     protected void initViews() { | ||||
|         lv_catalogue.setFastScrollEnabled(true); | ||||
|         ((MarkActivity) getActivity()).setSortcat(this); | ||||
| 
 | ||||
|         //lv_catalogue.setFastScrollStyle(R.style.FastScrollTheme); //不起作用 | ||||
|     } | ||||
|     void initSwipeRefreshLayout(){ | ||||
|         super.initSwipeRefreshLayout(); | ||||
|         mSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { | ||||
|             @Override | ||||
|             public void onRefresh() { | ||||
| 
 | ||||
|                 // 开始刷新,设置当前为刷新状态 | ||||
|                 //swipeRefreshLayout.setRefreshing(true); | ||||
|                 isAsc =true; | ||||
|                 refresh(btnRefresh); | ||||
| 
 | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|     @Override | ||||
|     public void setFTag() { | ||||
| 
 | ||||
|  |  | |||
|  | @ -620,13 +620,15 @@ public class ReadActivity extends  Activity_base implements SpeechSynthesizerLis | |||
|             } | ||||
|         }*/ | ||||
|         else if (id == R.id.action_change_source) { | ||||
|            if(  pageFactory.getChapters().size()>0) { | ||||
|         //   if(  pageFactory.getChapters().size()>0) { | ||||
|                Intent intent = new Intent(ReadActivity.this, Activity_ChgSource.class); | ||||
|                intent.putExtra(Activity_ChgSource.EXTR_ID, pageFactory.getCurrentChapter()); | ||||
|                intent.putExtra(Activity_ChgSource.EXTR_TITLE, pageFactory.getChapterName()); | ||||
|                intent.putExtra(Activity_ChgSource.EXTR_SITE, pageFactory.getSite()); | ||||
|                startActivity(intent); | ||||
|            } | ||||
|        //    }else{ | ||||
| 
 | ||||
|        //    } | ||||
|         } | ||||
| 
 | ||||
|         return super.onOptionsItemSelected(item); | ||||
|  |  | |||
|  | @ -50,6 +50,9 @@ public class CatalogueAdapter extends BaseAdapter { | |||
|     public void setCharter(int charter){ | ||||
|         currentCharter = charter; | ||||
|     } | ||||
|     public void setData(List<Chapter> bookCatalogueList){ | ||||
|         this.bookCatalogueList = bookCatalogueList; | ||||
|     } | ||||
| 
 | ||||
|     public void setCahedChapters(List<Integer> listCached ){ | ||||
|         bookCatalogueListCached =listCached; | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ public class SiteRule extends LitePalSupport { | |||
|     private String name; | ||||
|     @Column(unique = true, nullable = false) | ||||
|     private String domain; | ||||
|     private String encoding; | ||||
|   //  private String chapterUrlRegexOnMulu; | ||||
|     private RegexOnMulu[] chapterUrlRegexOnMulu; | ||||
|     private String chapterContentDumpRegex; | ||||
|  | @ -30,6 +31,14 @@ public class SiteRule extends LitePalSupport { | |||
|         this.id = id; | ||||
|     } | ||||
| 
 | ||||
|     public String getEncoding() { | ||||
|         return encoding; | ||||
|     } | ||||
| 
 | ||||
|     public void setEncoding(String encoding) { | ||||
|         this.encoding = encoding; | ||||
|     } | ||||
| 
 | ||||
|     public String getChapterContentRegex() { | ||||
|         return chapterContentRegex; | ||||
|     } | ||||
|  |  | |||
|  | @ -0,0 +1,131 @@ | |||
| package com.novelbook.android.netutils; | ||||
| 
 | ||||
| import android.text.TextUtils; | ||||
| import android.util.Log; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.lang.reflect.Field; | ||||
| import java.lang.reflect.Modifier; | ||||
| 
 | ||||
| import okhttp3.Headers; | ||||
| import okhttp3.Interceptor; | ||||
| import okhttp3.Request; | ||||
| import okhttp3.Response; | ||||
| import okhttp3.ResponseBody; | ||||
| import okhttp3.internal.http.RealResponseBody; | ||||
| 
 | ||||
| public class EncodingInterceptor implements Interceptor { | ||||
| private final static String TAG= EncodingInterceptor.class.getSimpleName(); | ||||
| 
 | ||||
|     /** | ||||
|      * 自定义编码 | ||||
|      */ | ||||
|     private String encoding; | ||||
| 
 | ||||
|     public EncodingInterceptor(String encoding) { | ||||
|         this.encoding = encoding; | ||||
|     } | ||||
| 
 | ||||
|     @Override public Response intercept(Interceptor.Chain chain) throws IOException { | ||||
|         Request request = chain.request(); | ||||
|         long start = System.nanoTime(); | ||||
|         Log.d(TAG, String.format("EncodingInterceptor Sending request: %s, headers:%s ", request.url(), request.headers())); | ||||
|         Response response = chain.proceed(request); | ||||
|         long end = System.nanoTime(); | ||||
|         Log.d(TAG,String.format("EncodingInterceptor Received response for %s in %.1fms%n %s", response.request().url(), (end - start) / 1e6d,  response.headers()) ); | ||||
| 
 | ||||
| 
 | ||||
|         String contentType = response.header("Content-Type"); | ||||
|         if (!TextUtils.isEmpty(contentType) && contentType.contains("charset")) { | ||||
|             return response; | ||||
|         } | ||||
| 
 | ||||
|         //add header | ||||
|          response.newBuilder() | ||||
|                 .removeHeader("Pragma") | ||||
|                 .header("Content-Type", (!TextUtils.isEmpty(contentType) ? contentType + "; ":"" ) + "charset=" + encoding) | ||||
|                 .build(); | ||||
|         //body charset | ||||
|       /*  String contentTypeString =  response.body().contentType().charset().name() ; | ||||
|         if (!TextUtils.isEmpty(contentTypeString) && contentTypeString.contains("charset")) { | ||||
|              return response; | ||||
|         } | ||||
|         contentTypeString =  (!TextUtils.isEmpty(contentTypeString) ? contentTypeString + "; ":"" ) + "charset=" + encoding; | ||||
|   */ | ||||
| 
 | ||||
| 
 | ||||
|         settingClientCustomEncoding(response); | ||||
|         return response; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * setting client custom encoding when server not return encoding | ||||
|      * @param response | ||||
|      * @throws IOException | ||||
|      */ | ||||
|     private void settingClientCustomEncoding(Response response) throws IOException { | ||||
|      //   setHeaderContentType(response); | ||||
|         setBodyContentType(response); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * set contentType in headers | ||||
|      * @param response | ||||
|      * @throws IOException | ||||
|      */ | ||||
|     private void setHeaderContentType(Response response) throws IOException { | ||||
|         String contentType = response.header("Content-Type"); | ||||
|         if (!TextUtils.isEmpty(contentType) && contentType.contains("charset")) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // build new headers | ||||
|         Headers headers = response.headers(); | ||||
|         Headers.Builder builder = headers.newBuilder(); | ||||
|         builder.removeAll("Content-Type"); | ||||
|         builder.add("Content-Type", (!TextUtils.isEmpty(contentType) ? contentType + "; ":"" ) + "charset=" + encoding); | ||||
|         headers = builder.build(); | ||||
|         // setting headers using reflect | ||||
|         Class  _response = Response.class; | ||||
|         try { | ||||
|             Field field = _response.getDeclaredField("headers"); | ||||
|             field.setAccessible(true); | ||||
|             field.set(response, headers); | ||||
|         } catch (NoSuchFieldException e) { | ||||
|             throw new IOException("use reflect to setting header occurred an error", e); | ||||
|         } catch (IllegalAccessException e) { | ||||
|             throw new IOException("use reflect to setting header occurred an error", e); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * set body contentType | ||||
|      * @param response | ||||
|      * @throws IOException | ||||
|      */ | ||||
|     private void setBodyContentType(Response response) throws IOException { | ||||
|         ResponseBody body = response.body(); | ||||
|         // setting body contentTypeString using reflect | ||||
|         Class tmp = RealResponseBody.class; | ||||
|         if(  !(body  instanceof RealResponseBody)){ | ||||
|             return; | ||||
|         } | ||||
|         Class<? extends ResponseBody> aClass = body.getClass(); | ||||
|         try { | ||||
|             Field field = aClass.getDeclaredField("contentTypeString"); | ||||
|             field.setAccessible(true); | ||||
|       /*      Field modifiersField = Field.class.getDeclaredField("modifiers"); | ||||
|             modifiersField.setAccessible(true); | ||||
|             modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);*/ | ||||
|             String contentTypeString = String.valueOf(field.get(body)); | ||||
|             if (!TextUtils.isEmpty(contentTypeString) && contentTypeString.contains("charset")) { | ||||
|                 return; | ||||
|             } | ||||
|             field.set(body, (!TextUtils.isEmpty(contentTypeString) ? contentTypeString + "; ":"" ) + "charset=" + encoding); | ||||
|         } catch (NoSuchFieldException e) { | ||||
|             throw new IOException("use reflect to setting header occurred an error", e); | ||||
|         } catch (IllegalAccessException e) { | ||||
|             throw new IOException("use reflect to setting header occurred an error", e); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -150,9 +150,9 @@ public class HttpMethods { | |||
|                */ | ||||
|                 Request.Builder requestBuilder = originalRequest.newBuilder() | ||||
|                        //  .addHeader("Accept-Encoding", "gzip") | ||||
|                         .addHeader("Accept-Encoding", Locale.getDefault().toString() ) | ||||
|                     //    .addHeader("Accept-Encoding", Locale.getDefault().toString() ) | ||||
|                         //   .addHeader("Accept", "application/json") | ||||
|                         //     .addHeader("Content-Type", "application/json; charset=utf-8") | ||||
|                          //     .addHeader("Content-Type", "application/json; charset=utf-8") | ||||
|                       //  .addHeader("Device", "Android") | ||||
|                         .removeHeader("User-Agent").addHeader("User-Agent",NetUtil.getUserAgent()) //加 随机agent | ||||
|                         .tag(NetUtil.currentRequestTag) | ||||
|  | @ -178,6 +178,11 @@ public class HttpMethods { | |||
|         loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); | ||||
|         //设置 Debug Log 模式 | ||||
|         okHttpBuilder.addInterceptor(loggingInterceptor); | ||||
| 
 | ||||
|         //设置编码 | ||||
|      //   EncodingInterceptor encodingInterceptor = new EncodingInterceptor("gbk"); | ||||
|       //  okHttpBuilder.addInterceptor(encodingInterceptor); | ||||
| 
 | ||||
| //        } | ||||
| 
 | ||||
|         /** | ||||
|  |  | |||
|  | @ -163,7 +163,7 @@ public class OnSuccessAndFaultSub extends DisposableObserver<ResponseBody> | |||
|         } catch (Exception e2) { | ||||
|             Log.e(TAG, "prepare book onError: ",e ); | ||||
|         } finally { | ||||
|             Log.e("OnSuccessAndFaultSub", "error:" + e.getMessage()); | ||||
|             Log.e("OnSuccessAndFaultSub", "error:" + e); | ||||
|             //            mOnSuccessAndFaultListener.onFault("error:" + e.getMessage()); | ||||
|             dismissProgressDialog(); | ||||
|             progressDialog = null; | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ 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; | ||||
|  | @ -38,6 +39,7 @@ import java.io.IOException; | |||
| import java.io.InputStreamReader; | ||||
| import java.io.OutputStreamWriter; | ||||
| import java.lang.ref.WeakReference; | ||||
| import java.nio.charset.Charset; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Date; | ||||
| import java.util.HashMap; | ||||
|  | @ -198,15 +200,26 @@ public class BookUtil { | |||
|             throw new RuntimeException("书本错误 code 001"); //无目标网站 | ||||
|            // return; | ||||
|         } | ||||
|         mSite =nvs.getSites()[0]; | ||||
|         if(nvs.getSites().length > 0) | ||||
|         for (Site site:nvs.getSites() ) { | ||||
|             if(site.getSelectedByDefault()){ | ||||
|                 mSite = site; | ||||
|                 break; | ||||
| 
 | ||||
|         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(); | ||||
|          getSiteRule(); | ||||
|     } | ||||
| 
 | ||||
|     private void setSiteInfo() { | ||||
|  | @ -252,7 +265,7 @@ public class BookUtil { | |||
|             } | ||||
|         },null)); | ||||
|     } | ||||
|     private void getSiteRule() { | ||||
|     public void getSiteRule() { | ||||
|         mSiteRule = null; | ||||
|         BookSubscribe.getSiteRule(mSite.getDomain(),new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() { | ||||
|             @Override | ||||
|  | @ -296,22 +309,24 @@ public class BookUtil { | |||
|                             try { | ||||
|                                 JSONObject siteJson = new JSONObject(result); | ||||
| 
 | ||||
|                                 chaps = NovelParseUtil.getChapters(mSite.getMuluUrl(), siteJson); | ||||
|                                 mChapters = NovelParseUtil.getChapters(mSite.getMuluUrl(), siteJson,mSite.getDomain(),mNovel.getMaxAge(),mSiteRule.getEncoding()); | ||||
| 
 | ||||
|                                 if (chaps != null) | ||||
|                                     for (String s : chaps) { | ||||
|                                         Log.d(TAG, "prepare book to get chaps readChaptersAsync: chapt: " + s); | ||||
|                                 if (mChapters != null){ | ||||
|                                     for (Chapter chapter:mChapters) { | ||||
|                                         Log.d(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 (chaps == null || chaps.length == 0) { | ||||
|                             if (mChapters == null ||mChapters.size()== 0) { | ||||
|                                 readChaptersAsync(); | ||||
|                             }else | ||||
|                             { | ||||
| 
 | ||||
|                                 handler.sendEmptyMessage(3); | ||||
|                                 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()) ); | ||||
|  | @ -700,7 +715,9 @@ int 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 = 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(); | ||||
|  | @ -785,20 +802,20 @@ int muluRetryCount =0; | |||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public int next(boolean back){ | ||||
|     public int next(boolean back,int chaptId){ | ||||
|         position += 1; | ||||
|         if (position > tmpChaptLen){ | ||||
|             position = tmpChaptLen; | ||||
|             return -1; | ||||
|         } | ||||
|         char result = chaptCurrent(); //current(); | ||||
|         char result = chaptCurrent(chaptId); //current(); | ||||
|         if (back) { | ||||
|             position -= 1; | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     public char[] nextLine(){ | ||||
|     /*public char[] nextLine(){ | ||||
|         if (position >= tmpChaptLen){ | ||||
|             return null; | ||||
|         } | ||||
|  | @ -816,7 +833,7 @@ int muluRetryCount =0; | |||
|             line += wordChar; | ||||
|         } | ||||
|         return line.toCharArray(); | ||||
|     } | ||||
|     }*/ | ||||
| 
 | ||||
|     public char[] preLine(){ | ||||
|         if (position <= 0){ | ||||
|  | @ -839,14 +856,17 @@ int muluRetryCount =0; | |||
| 
 | ||||
|         return line.toCharArray(); | ||||
|     } | ||||
|     public char chaptCurrent(){ | ||||
| 
 | ||||
|     public char chaptCurrent(int chaptId){ | ||||
|       //  chapterNo = mChapters.size() < chapterNo ? 1 : chapterNo; | ||||
|        // Log.d(TAG, String.format(" prepare book  chaptCurrent() ,chapterNo %s,  getChapters().size() %s " ,chapterNo , mChapters.size()) ); | ||||
|         char[] charArray = chaptChars(chapterNo); | ||||
|         char[] charArray = chaptChars(chaptId); | ||||
| 
 | ||||
| 
 | ||||
|         int i = (int)position-1; | ||||
|         i =i>0?i:0; | ||||
|         i = i< charArray.length? i:charArray.length-1; | ||||
| 
 | ||||
|         return charArray[i]; | ||||
|     } | ||||
|     public char current(){ | ||||
|  | @ -1258,6 +1278,7 @@ int muluRetryCount =0; | |||
|         char[] block=null; | ||||
|         if(chaptCache.containsKey(Integer.valueOf(index))) { | ||||
|             block = chaptCache .get(index).getData().get(); | ||||
|           //  Log.d(TAG, String.format("prepare book  get block in cache, chapter: %s", index)); | ||||
|         } | ||||
|       //  Log.d(TAG, String.format("prepare book  begin to load content for chapter %s", index)); | ||||
|         if (block == null) { | ||||
|  | @ -1389,6 +1410,7 @@ int muluRetryCount =0; | |||
|                             new InputStreamReader( | ||||
|                                     new FileInputStream(file), | ||||
|                                     charachterType | ||||
|                                   //  mSiteRule.getEncoding() | ||||
|                             ); | ||||
| 
 | ||||
|                     long l = reader.read(block); | ||||
|  | @ -1472,6 +1494,7 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte | |||
| 
 | ||||
|         @Override | ||||
|         public void onResponse(Call call, Response response){ | ||||
| 
 | ||||
|             ResponseBody body = response.body(); | ||||
|             if (body != null ) { | ||||
|                 if(response.code()!=200){ | ||||
|  | @ -1485,7 +1508,13 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte | |||
| 
 | ||||
|                 try { | ||||
| 
 | ||||
|                     String bodyStr = body.string(); | ||||
|                   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()); | ||||
|                     String title = chapter.getChapterName(); | ||||
|                     String chapterContent = title+ "\n" + NovelParseUtil.getChapterContent(bodyStr, siteJson); | ||||
|                     char[] buf = chapterContent.toCharArray(); | ||||
|  | @ -1493,6 +1522,7 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte | |||
|                     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())); | ||||
|  | @ -1541,13 +1571,17 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte | |||
|                 .tag(mNovel.getNovelId()) //标记 请求的tag,切换小说或离开小说界面(BookActivity) 时 取消未执行完毕的 此tag的所有请求 | ||||
|                 .url(url) | ||||
|                 .removeHeader("Pragma") | ||||
|                 .header("Cache-Control", "public, max-age=" + 0) | ||||
|                //  .header("Accept-Encoding","gzip, deflate, sdch") | ||||
|                 .header("Cache-Control", "public, max-age=" + maxAge) | ||||
| 
 | ||||
|                 .header("Accept-Language","zh-CN,zh;q=0.9") | ||||
|                 .header( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8") | ||||
|                 .header( "Upgrade-Insecure-Requests", "1") | ||||
|               //   .header("content-type", "text/html; charset=utf-8") | ||||
|                 ; | ||||
| 
 | ||||
|        /* if(mSiteRule!=null && !TextUtils.isEmpty(mSiteRule.getEncoding())  ){ | ||||
|             builder.header("Accept-Encoding",mSiteRule.getEncoding()); | ||||
|         } | ||||
| */ | ||||
|         return builder.build(); | ||||
| 
 | ||||
|     } | ||||
|  |  | |||
|  | @ -1,9 +1,10 @@ | |||
| package com.novelbook.android.utils; | ||||
| 
 | ||||
| import android.text.TextUtils; | ||||
| 
 | ||||
| import android.util.Log; | ||||
| 
 | ||||
| import com.novelbook.android.db.Chapter; | ||||
| import com.novelbook.android.db.SiteRule; | ||||
| import com.novelbook.android.netutils.HttpMethods; | ||||
| 
 | ||||
| import org.json.JSONArray; | ||||
|  | @ -11,8 +12,12 @@ import org.json.JSONException; | |||
| import org.json.JSONObject; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| import java.io.UnsupportedEncodingException; | ||||
| import java.nio.charset.Charset; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.Date; | ||||
| import java.util.HashMap; | ||||
| import java.util.LinkedHashMap; | ||||
| import java.util.List; | ||||
|  | @ -21,6 +26,7 @@ import java.util.Set; | |||
| 
 | ||||
| import okhttp3.Request; | ||||
| import okhttp3.Response; | ||||
| import okhttp3.ResponseBody; | ||||
| 
 | ||||
| public class NovelParseUtil { | ||||
|     private static final String TAG=NovelParseUtil.class.getSimpleName(); | ||||
|  | @ -93,6 +99,9 @@ public class NovelParseUtil { | |||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     public static String getChapterContent(String html, JSONObject siteJson) throws JSONException  { | ||||
|         String chapterContentRegex = siteJson.getString("chapterContentRegex"); | ||||
|         String text = REUtil.group(chapterContentRegex, html, 1); | ||||
|  | @ -127,7 +136,33 @@ public class NovelParseUtil { | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     public static String[] getChapters(String url, JSONObject siteJson) throws JSONException { | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     public static List<Chapter> getChaptersLst(String[] rows,String domain){ | ||||
| 
 | ||||
|         ArrayList<Chapter> lst = new ArrayList<Chapter>(); | ||||
|        int j=0; | ||||
|         for (int i=0;i<rows.length;i+=2) { | ||||
|             j++; | ||||
|             Chapter chapter = new Chapter(); | ||||
|             chapter.setChapterUrl( rows[i]); | ||||
|             chapter.setChapterName(  rows[i+1]); | ||||
|             chapter.setDomain(domain); | ||||
|             chapter.setIndex(j); //第几章 | ||||
|             lst.add(chapter); | ||||
| 
 | ||||
|         } | ||||
|         return lst; | ||||
|     } | ||||
| 
 | ||||
|     public static List<Chapter> getChapters(String url, JSONObject siteJson,String domain,int maxAage,String encoding) throws JSONException { | ||||
|        return  getChaptersLst(getChapters(url,siteJson,maxAage,encoding),domain); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public static String[] getChapters(String url, JSONObject siteJson, int maxAge,String encoding) throws JSONException { | ||||
|         //if (!siteJson.keys().("chapterUrlRegexOnMulu")) return null; | ||||
|         String chapterUrlRegexOnMulu = siteJson.getString("chapterUrlRegexOnMulu"); | ||||
|        // if(TextUtils.isEmpty(chapterUrlRegexOnMulu)) return null; | ||||
|  | @ -152,7 +187,7 @@ public class NovelParseUtil { | |||
|             Log.d(TAG, "to get chaps source:" + source ); | ||||
|             if (source.startsWith("html:")) { | ||||
|                 String _url = source.substring("html:".length()); | ||||
|                 source = access(_url); | ||||
|                 source = access(_url,maxAge,encoding); | ||||
|                 Log.d(TAG, "to get chaps source:" + source ); | ||||
|             } | ||||
| 
 | ||||
|  | @ -241,33 +276,76 @@ public class NovelParseUtil { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     private static String access(String url) { | ||||
|     private static String access(String url,int maxAge,String encoding) { | ||||
|         Request.Builder builder = new Request.Builder() | ||||
|             //    .tag(mNovel.getNovelId()) //标记 请求的tag,切换小说或离开小说界面(BookActivity) 时 取消未执行完毕的 此tag的所有请求 | ||||
|                 .url(url) | ||||
|                 .removeHeader("Pragma") | ||||
|                 .header("Cache-Control", "public, max-age=" + 0) | ||||
|                 .header("Cache-Control", "public, max-age=" + maxAge) | ||||
|                 //  .header("Accept-Encoding","gzip, deflate, sdch") | ||||
|                 .header("Accept-Language","zh-CN,zh;q=0.9") | ||||
|                 .header( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8") | ||||
|                 .header( "Upgrade-Insecure-Requests", "1") | ||||
|              //   .header("Accept-Language","zh-CN,zh;q=0.9") | ||||
|                // .header( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8") | ||||
|              //   .header( "Upgrade-Insecure-Requests", "1") | ||||
|                // .header("content-type", "text/html; charset=utf-8") | ||||
|                 ; | ||||
| 
 | ||||
|         Request request =builder.build() ; | ||||
|         Response response = null; | ||||
|         try { | ||||
|             Response response =  HttpMethods.getOkClient().newCall(request).execute(); | ||||
|             String s =response.body().string(); | ||||
|             response =  HttpMethods.getOkClient().newCall(request).execute(); | ||||
|             //String s =response.body().string(); | ||||
| 
 | ||||
|             String s = enconding(response.body(),encoding); //new String(response.body().bytes(),  encoding); | ||||
|          //   response.body().close(); | ||||
|             long st = new java.util.Date().getTime(); | ||||
|             Log.d(TAG, "to get chaps access result:" + s ); | ||||
|            return s; | ||||
|             return  s; | ||||
|           //  return enconding(s,encoding); | ||||
|          //  return info; | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|             Log.e(TAG, "access: ", e); | ||||
|         }finally { | ||||
|             if(response!=null) | ||||
|                 response.body().close(); | ||||
|         } | ||||
|         return ""; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| public  static String enconding(ResponseBody body,  String encode) throws UnsupportedEncodingException { | ||||
|         String s=""; | ||||
|         try{ | ||||
|             Charset charset = body.contentType().charset(); | ||||
|             if(charset!=null){ | ||||
|                 s= body.string(); | ||||
|             }else { | ||||
|                 s= new String(body.bytes(), encode); | ||||
|             } | ||||
|         }catch (Exception er){ | ||||
| 
 | ||||
|         }finally { | ||||
|             body.close(); | ||||
|         } | ||||
|         return s; | ||||
| 
 | ||||
|    /* Log.d(TAG, " encoding covert from :" +source ); | ||||
|     long st = new java.util.Date().getTime(); | ||||
|     byte[] b = source.getBytes("utf-8"); | ||||
|  //   String info = new String(b, "utf-8"); | ||||
|     String info = new String(b); | ||||
|     Log.d(TAG, " encoding covert to :" +info ); | ||||
|     Log.d(TAG, "encoding covert :" + encode  +", cost " +( new Date().getTime() -st)); | ||||
|     return  info;*/ | ||||
| 
 | ||||
| /*    long st = new java.util.Date().getTime(); | ||||
|     byte[] b = source.getBytes(encode); | ||||
|     //   String info = new String(b, "utf-8"); | ||||
|     String info = new String(b,"utf-8"); | ||||
|     Log.d(TAG, " encoding covert to :" +info ); | ||||
|     Log.d(TAG, "encoding covert :" + encode  +", cost " +( new Date().getTime() -st)); | ||||
|     return  info;*/ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -380,7 +380,7 @@ public class PageFactory implements ChangeSource{ | |||
|         int pageNo =0; | ||||
|         while(length <chars.length ) { | ||||
|             pageNo++; | ||||
|             TRPage page  = getNextChapterPage(length); | ||||
|             TRPage page  = getNextChapterPage(chaptId,length); | ||||
|             // Log.d(TAG,"prepare book  page.getBegin :" + page.getBegin()+ ",chapter length "+ mBookUtil.getBookLen()); | ||||
| 
 | ||||
|             // if(page.getBegin() == mBookUtil.getBookLen() ){ //最后一页空白的情况。。。 | ||||
|  | @ -401,13 +401,13 @@ public class PageFactory implements ChangeSource{ | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     public TRPage getNextChapterPage(long position){ | ||||
|     public TRPage getNextChapterPage(int chaptId,long position){ | ||||
|         mBookUtil.setPostition(position); | ||||
| 
 | ||||
|         TRPage trPage = new TRPage(); | ||||
|         trPage.setBegin(position +1); | ||||
|       // Log.d(TAG,"page postion next begin:" +  (position + 1) + ""); | ||||
|         trPage.setLines(getNextLines()); | ||||
|         trPage.setLines(getNextLines(chaptId)); | ||||
|      //  Log.d(TAG,"page postion next end:" +mBookUtil.getPosition() + ""); | ||||
|         trPage.setEnd(mBookUtil.getPosition()); | ||||
|         return trPage; | ||||
|  | @ -442,6 +442,7 @@ public class PageFactory implements ChangeSource{ | |||
|     } | ||||
|     public void changeSource(String domain,int chapId,String chapTitle) { | ||||
|         fileRetryCnt.clear(); | ||||
|         chaptMap.clear(); | ||||
|         mBookUtil.changeSource(domain,  chapId,  chapTitle); | ||||
|     } | ||||
| 
 | ||||
|  | @ -1070,7 +1071,7 @@ public static boolean busy(){ | |||
|     } | ||||
| 
 | ||||
|     boolean showChapTitleOnTopWhenNextPage =false; | ||||
|     public List<String> getNextLines(){ | ||||
|     public List<String> getNextLines(int chaptId){ | ||||
|         List<String> lines = new ArrayList<>(); | ||||
|         float width = 0; | ||||
|         float height = 0; | ||||
|  | @ -1079,8 +1080,8 @@ public static boolean busy(){ | |||
|         lines.add("\n");lines.add("\n"); | ||||
|         } | ||||
|         calculateLineCount(); | ||||
|         while (mBookUtil.next(true) != -1){ | ||||
|             char word = (char) mBookUtil.next(false); | ||||
|         while (mBookUtil.next(true,chaptId) != -1){ | ||||
|             char word = (char) mBookUtil.next(false,chaptId); | ||||
|             //判断是否换行 | ||||
|             if ((word + "" ).equals("\n")  ){//   if ((word + "" ).equals("\r") && (((char) mBookUtil.next(true)) + "").equals("\n")){ | ||||
|               //  mBookUtil.next(false); | ||||
|  | @ -1570,5 +1571,9 @@ public static boolean busy(){ | |||
|         } | ||||
|         return new Novel(); | ||||
|     } | ||||
|     public void refreshCate(){ | ||||
|         mBookUtil.getChapters().clear(); | ||||
|         mBookUtil.getSiteRule(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -29,6 +29,11 @@ | |||
|         style="@style/TextViewNovelTitle" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" /> | ||||
|     <android.support.v4.widget.SwipeRefreshLayout | ||||
|         android:id="@+id/swipeLayout" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         android:orientation="vertical"> | ||||
| 
 | ||||
|     <ListView | ||||
|         android:id="@+id/lv_catalogue" | ||||
|  | @ -36,7 +41,7 @@ | |||
|         android:layout_height="match_parent" | ||||
|         android:divider="@color/list_item_divider" | ||||
|         android:dividerHeight="1dp" /> | ||||
| 
 | ||||
|     </android.support.v4.widget.SwipeRefreshLayout> | ||||
|     <Button | ||||
|         android:id="@+id/btnRefresh" | ||||
|         android:layout_width="100dp" | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue