try read book online
This commit is contained in:
		
							parent
							
								
									9fb63f10aa
								
							
						
					
					
						commit
						90af9bbce2
					
				|  | @ -2,12 +2,12 @@ | |||
| <litepal> | ||||
|     <dbname value="book" ></dbname> | ||||
| 
 | ||||
|     <version value="1" ></version> | ||||
|     <version value="3" ></version> | ||||
| 
 | ||||
|     <list> | ||||
|         <mapping class="com.novelbook.android.db.BookChapter"></mapping> | ||||
|         <mapping class="com.novelbook.android.db.Book"></mapping> | ||||
|         <mapping class="com.novelbook.android.db.Chapter"></mapping> | ||||
|         <mapping class="com.novelbook.android.db.Novel"></mapping> | ||||
|         <mapping class="com.novelbook.android.db.BookMarks"></mapping> | ||||
|         <mapping class="com.novelbook.android.db.BookDan"></mapping> | ||||
|         <mapping class="com.novelbook.android.db.SiteRule"></mapping> | ||||
|     </list> | ||||
| </litepal> | ||||
|  | @ -119,7 +119,7 @@ public abstract  class Activity_base extends AppCompatActivity { | |||
|         { | ||||
|             Novel bk = new Novel(); | ||||
|             bk.setAuthor("金庸"); | ||||
|             bk.setNovelName("射雕英雄传" +(char)i); | ||||
|             bk.setName("射雕英雄传" +(char)i); | ||||
|             bk.setNovelType("武侠"); | ||||
|             bk.setDescription("南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事"); | ||||
|             mDatas.add(bk); | ||||
|  |  | |||
|  | @ -109,7 +109,7 @@ public class Activity_createShudan  extends Activity_base  { | |||
|         { | ||||
|             Novel  bk = new Novel (); | ||||
|             bk.setAuthor("金庸" +i); | ||||
|             bk.setNovelName("射雕" +(char)i); | ||||
|             bk.setName("射雕" +(char)i); | ||||
|             bk.setNovelType("cate" +i); | ||||
|             bk.setDescription(" 南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事"); | ||||
|             mData .add(bk); | ||||
|  | @ -185,7 +185,7 @@ public class Activity_createShudan  extends Activity_base  { | |||
|         @Override | ||||
|         public void onBindViewHolder(MyViewHolder holder, int position) { | ||||
| 
 | ||||
|             holder.tvTitle.setText(mDatas.get(position).getNovelName()); | ||||
|             holder.tvTitle.setText(mDatas.get(position).getName()); | ||||
|             holder.tvAuthor.setText(mDatas.get(position).getAuthor()); | ||||
|             holder.tvCate.setText(mDatas.get(position).getNovelType()); | ||||
|             holder.tvDesc.setText(mDatas.get(position).getDescription()); | ||||
|  |  | |||
|  | @ -1,26 +1,41 @@ | |||
| package com.novelbook.android; | ||||
| 
 | ||||
| import android.Manifest; | ||||
| import android.app.AlertDialog; | ||||
| import android.content.Context; | ||||
| import android.content.DialogInterface; | ||||
| import android.os.Build; | ||||
| import android.os.Handler; | ||||
| import android.os.Message; | ||||
| import android.support.v7.widget.LinearLayoutManager; | ||||
| import android.support.v7.widget.RecyclerView; | ||||
| import android.support.v7.widget.Toolbar; | ||||
| import android.text.TextUtils; | ||||
| import android.util.Log; | ||||
| import android.view.MenuItem; | ||||
| import android.view.View; | ||||
| import android.widget.Button; | ||||
| import android.widget.ImageView; | ||||
| import android.widget.TextView; | ||||
| import android.widget.Toast; | ||||
| 
 | ||||
| import com.bumptech.glide.Glide; | ||||
| import com.google.gson.Gson; | ||||
| import com.novelbook.android.adapter.BookListAdapter; | ||||
| import com.novelbook.android.bean.NovelSites; | ||||
| import com.novelbook.android.db.Chapter; | ||||
| import com.novelbook.android.db.Novel; | ||||
| import com.novelbook.android.filechooser.FileChooserActivity; | ||||
| import com.novelbook.android.netsubscribe.BookSubscribe; | ||||
| import com.novelbook.android.netsubscribe.MovieSubscribe; | ||||
| import com.novelbook.android.netutils.HttpMethods; | ||||
| import com.novelbook.android.netutils.OnSuccessAndFaultListener; | ||||
| import com.novelbook.android.netutils.OnSuccessAndFaultSub; | ||||
| import com.novelbook.android.utils.BookUtil; | ||||
| import com.novelbook.android.utils.GsonUtil; | ||||
| import com.novelbook.android.utils.NovelParseUtil; | ||||
| import com.novelbook.android.utils.PageFactory; | ||||
| import com.youth.banner.loader.ImageLoader; | ||||
| 
 | ||||
| import org.json.JSONException; | ||||
| import org.json.JSONObject; | ||||
|  | @ -41,21 +56,45 @@ import okhttp3.Request; | |||
| import okhttp3.Response; | ||||
| import okhttp3.ResponseBody; | ||||
| 
 | ||||
| import static com.novelbook.android.FileActivity.EXTERNAL_STORAGE_REQ_CODE; | ||||
| 
 | ||||
| public class BookActivity extends   Activity_base { | ||||
| 
 | ||||
|     private PageFactory pageFactory; | ||||
|     String novelId="f2619820112625133c14dcb170f5e092"; | ||||
|     String muluUrl="https://www.qu.la/book/390/"; | ||||
|     private Novel mNovel; | ||||
|     private Chapter mChapter; | ||||
|     static String TAG = BookActivity.class.getSimpleName(); | ||||
|     BookListAdapter mAdapter; | ||||
|     // private BookListAdapter mAdapter; | ||||
|     private List<Novel> mData;; | ||||
| 
 | ||||
|     private ArrayList<Chapter> mChapters = new ArrayList<>(); | ||||
|     private Gson gson = new Gson(); | ||||
|     private  List<Chapter> mChapters = new ArrayList<>(); | ||||
|     @BindView(R.id.toolbar) | ||||
|     Toolbar toolbar; | ||||
|     @BindView(R.id.rvBooklist) | ||||
|     RecyclerView rvBooklist; | ||||
|     @BindView(R.id.btnShelf) | ||||
|     Button btnShelf; | ||||
|     @BindView(R.id.imageView) | ||||
|     ImageView imageView; | ||||
|     @BindView(R.id.title) | ||||
|     TextView txtTitle; | ||||
|     @BindView(R.id.desc) | ||||
|     TextView txtDesc; | ||||
|     @BindView(R.id.author) | ||||
|     TextView txtAuth; | ||||
|     @BindView(R.id.category) | ||||
|     TextView txtCategory; | ||||
|     @BindView(R.id.txtDesc2) | ||||
|     TextView txtDesc2; | ||||
|     @BindView(R.id.txtLatestCate) | ||||
|     TextView txtLatestCate; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     @Override | ||||
|     public int getLayoutRes() { | ||||
|  | @ -92,31 +131,111 @@ public class BookActivity extends   Activity_base { | |||
| 
 | ||||
|     @Override | ||||
|     protected void initData() { | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||||
|             checkPermission(BookActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE, EXTERNAL_STORAGE_REQ_CODE,"添加图书需要此权限,请允许"); | ||||
|         } | ||||
|         pageFactory = PageFactory.getInstance(); | ||||
|         setBookInfo();//set title ,data from novel list | ||||
|         if(mNovel==null) { | ||||
|             getBookInfo(); | ||||
|       //  getMuluInfo(); | ||||
|         } | ||||
| 
 | ||||
|         mData =getFakeData(5); | ||||
|         mAdapter = getBookListAdapter(mData); | ||||
|     } | ||||
| 
 | ||||
| @OnClick({R.id.btnRead,R.id.btnCacheBook}) | ||||
|     private void setBookInfo() { | ||||
|     } | ||||
|     private MyLoader loader = new MyLoader(); | ||||
|     public void setBookDetailInfo(  ){ | ||||
|         setShelfButtonText(); | ||||
|         this.txtAuth.setText(mNovel.getAuthor()); | ||||
|         this.txtCategory.setText(mNovel.getNovelType()); | ||||
|         this.txtDesc.setText(mNovel.getDescription()); | ||||
|         this.txtTitle.setText(mNovel.getName()); | ||||
|         this.txtDesc2.setText(mNovel.getDescription()); | ||||
|         this.txtLatestCate.setText(mNovel.getLastestChapterName()); | ||||
|         if(mNovel.getLastUpateTime()>0){ | ||||
|            ; | ||||
|             this.txtLatestCate.setText(  new Date(mNovel.getLastUpateTime()).toString()  +"\n"+txtLatestCate.getText()); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         if(!TextUtils.isEmpty(mNovel.getCover())) { | ||||
|             loader.displayImage(BookActivity.this, mNovel.getCover(), imageView); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
|     private class MyLoader extends ImageLoader { | ||||
|         @Override | ||||
|         public void displayImage(Context context, Object path, ImageView imageView) { | ||||
|             Glide.with(context).load((String) path).into(imageView); | ||||
|         } | ||||
|     } | ||||
|     void setShelfButtonText(){ | ||||
|         String title = mNovel.isOnShelf()?"移除书架":"加入书架"; | ||||
|         btnShelf.setText(title); | ||||
|     } | ||||
| 
 | ||||
|     @OnClick({R.id.btnRead,R.id.btnCacheBook,R.id.btnShelf}) | ||||
|         void submitButton(View view){ | ||||
| 
 | ||||
|         switch (view.getId()) { | ||||
|             case R.id.btnRead: | ||||
|                 testBook(); | ||||
|                 readBook(); | ||||
|                 //testBook(); | ||||
| 
 | ||||
|               //  openBook(new Novel() ); | ||||
|                 break; | ||||
|             case R.id.btnCacheBook: | ||||
|                 cachBook(); | ||||
|                 cacheBook(); | ||||
|                 break; | ||||
| 
 | ||||
|             case R.id.btnShelf: | ||||
|                 shelfBook(); | ||||
|                 break; | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|     private void cachBook() { | ||||
|     private void shelfBook() { | ||||
|         mNovel.setOnShelf(!mNovel.isOnShelf()); | ||||
|         mNovel.save(); | ||||
|         setShelfButtonText(); | ||||
| 
 | ||||
|     } | ||||
|     Handler handler = new Handler() { | ||||
|         @Override | ||||
|         public void handleMessage(Message msg) { | ||||
| 
 | ||||
|             int wt = msg.what; | ||||
| 
 | ||||
|             if (msg.what == 1 ) { | ||||
|                 setBookDetailInfo(); | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|     }; | ||||
|     private void readBook() { | ||||
|         if(mNovel ==null){ | ||||
|             Toast.makeText(this,"网络错误",Toast.LENGTH_LONG); | ||||
|             return; | ||||
|         } | ||||
|         ReadActivity.openBook(mNovel  , BookActivity.this); | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private void getChapters() { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private void cacheBook() { | ||||
|         MovieSubscribe.getData(1,10,new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() { | ||||
|             @Override | ||||
|             public void onSuccess(String result) { | ||||
|  | @ -158,32 +277,33 @@ public class BookActivity extends   Activity_base { | |||
|                     }).setCancelable(true).show(); | ||||
|             return; | ||||
|         } | ||||
|         ReadActivity.openBook(book ,mChapters,this); | ||||
|      //   ReadActivity.openBook(book  ,null,this); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     void getMuluInfo(){ | ||||
|         BookSubscribe.getNovelMulu(novelId,new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() { | ||||
|         BookSubscribe.getNovelSites(novelId,new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() { | ||||
|             @Override | ||||
|             public void onSuccess(String result) { | ||||
|                 //成功 | ||||
|                 try { | ||||
|                     JSONObject jsonObject = new JSONObject(result); | ||||
| 
 | ||||
|                   muluUrl=  jsonObject.getString("muluUrl"); | ||||
|                     NovelSites nvs = (NovelSites) gson.fromJson(result,NovelSites.class); | ||||
|                     pageFactory.prepareBook(mNovel,nvs,BookActivity.this); | ||||
| 
 | ||||
|                 } catch (JSONException e) { | ||||
|                 } catch ( Exception e) { | ||||
|                     e.printStackTrace(); | ||||
|                 } | ||||
| 
 | ||||
|                 Toast.makeText(BookActivity.this,"muluUrl 请求成功:" + muluUrl,Toast.LENGTH_SHORT).show(); | ||||
|                 Toast.makeText(BookActivity.this,"getMuluInfo 请求成功 "  ,Toast.LENGTH_SHORT).show(); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onFault(String errorMsg) { | ||||
|                 //失败 | ||||
|                 Toast.makeText(BookActivity.this,"Novel 请求失败:"+errorMsg,Toast.LENGTH_SHORT).show(); | ||||
|                 Toast.makeText(BookActivity.this,"getMuluInfo 请求失败"+errorMsg,Toast.LENGTH_SHORT).show(); | ||||
|             } | ||||
|         },BookActivity.this)); | ||||
|     } | ||||
|  | @ -197,37 +317,10 @@ public class BookActivity extends   Activity_base { | |||
|             @Override | ||||
|             public void onSuccess(String result) { | ||||
|                 //成功 | ||||
|                 Gson gson = new Gson(); | ||||
| 
 | ||||
|               //  result ={"id":"f2619820112625133c14dcb170f5e092","novelType":"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>","novelType2":"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>½","name":"<EFBFBD><EFBFBD><EFBFBD>Ʋ<EFBFBD><EFBFBD>","author":"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>","cover":"http:\/\/qidian.qpic.cn\/qdbimg\/349573\/1209977\/180","description":"","lastestChapterName":"<EFBFBD>ڰ<EFBFBD><EFBFBD><EFBFBD> <20><>ʼ","lastUpateTime":""} | ||||
|               //  Novel nv = gson.fromJson(result,Novel.class);  //to change id to noveId | ||||
| 
 | ||||
|                 Novel nv = new Novel(); | ||||
|                 try { | ||||
|                     JSONObject jsonObject = new JSONObject(result); | ||||
|                    nv.setNovelId(jsonObject.getString("id")); | ||||
|                //    nv.setLastUpateTime(jsonObject.getLong("lastUpateTime")); | ||||
|                    nv.setAuthor(jsonObject.getString("author")); | ||||
|                    nv.setNovelName(jsonObject.getString("name")); | ||||
|                    nv.setCover(jsonObject.getString("cover")); | ||||
|                     nv.setNovelType(jsonObject.getString("novelType")); | ||||
|                     nv.setNovelType2(jsonObject.getString("novelType2")); | ||||
|                     nv.setLastestChapterName(jsonObject.getString("lastestChapterName")); | ||||
| 
 | ||||
| 
 | ||||
|                 } catch (JSONException e) { | ||||
|                     e.printStackTrace(); | ||||
|                 } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|                 //to load image | ||||
| 
 | ||||
| 
 | ||||
|                 //to load desc | ||||
| 
 | ||||
|                 //... | ||||
| 
 | ||||
|                 Novel nv ; | ||||
|                 nv = gson.fromJson(result,Novel.class); | ||||
|               //   nv = GsonUtil.getNovel(result); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -235,6 +328,7 @@ public class BookActivity extends   Activity_base { | |||
|                 if(!isLocalDbExist){ | ||||
|                  //  nv.saveAsync(); | ||||
|                     nv.save (); | ||||
| 
 | ||||
|                 }else{ | ||||
| 
 | ||||
|                     List<Novel> nvs = LitePal.where("novelId=?",novelId).find(Novel.class); | ||||
|  | @ -243,7 +337,7 @@ public class BookActivity extends   Activity_base { | |||
|                         Log.d(TAG,String.format("novel id %s before update: lastUpdateTime: %s",novel.getId(),novel.getLastUpateTime())); | ||||
|                     } | ||||
| 
 | ||||
|                     nv.setLastUpateTime(new Date().getTime()); | ||||
|                   //  nv.setLastUpateTime(new Date().getTime()); | ||||
|                     nv.updateAll("novelId=?",novelId); | ||||
| 
 | ||||
|                     nvs = LitePal.where("novelId=?",novelId).find(Novel.class); | ||||
|  | @ -258,9 +352,10 @@ public class BookActivity extends   Activity_base { | |||
| 
 | ||||
|                 if(nvs.size()>0) { | ||||
|                     mNovel = nvs.get(0); | ||||
|                     handler.sendEmptyMessage(1); | ||||
|                 } | ||||
| 
 | ||||
|               //  getMuluInfo(); | ||||
|                getMuluInfo(); | ||||
|                 Toast.makeText(BookActivity.this,"Novel 请求成功:"+result,Toast.LENGTH_SHORT).show(); | ||||
|             } | ||||
| 
 | ||||
|  | @ -272,13 +367,13 @@ public class BookActivity extends   Activity_base { | |||
|         },BookActivity.this)); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     void testBook(){ | ||||
| /* | ||||
|     void readChapters( String url){ | ||||
| 
 | ||||
| 
 | ||||
|         //to get mulu list | ||||
| 
 | ||||
|         String url = muluUrl;// "https://www.qu.la/book/161/";//"https://www.qu.la/book/746/"; | ||||
|         url = muluUrl;// "https://www.qu.la/book/161/";//"https://www.qu.la/book/746/"; | ||||
|         Request request = new Request.Builder() | ||||
|                 .url(url) | ||||
|                // .header("User-Agent", "OkHttp Example") | ||||
|  | @ -298,7 +393,7 @@ public class BookActivity extends   Activity_base { | |||
|                         String bodyStr = body.string(); | ||||
|                         Log.d(TAG, "onResponse: " +bodyStr); | ||||
|                         onResponseProcess(bodyStr,url); | ||||
|                         ReadActivity.openBook(mNovel ,mChapters,BookActivity.this); | ||||
|                         ReadActivity.openBook(mNovel  ,mChapter,BookActivity.this); | ||||
|                     } catch (IOException e) { | ||||
|                         e.printStackTrace(); | ||||
|                     }finally { | ||||
|  | @ -315,51 +410,19 @@ void onResponseProcess( String content ,String url){ | |||
|    // HttpResult result  ; | ||||
|    // HttpResult result2 = null; | ||||
|     try { | ||||
| 
 | ||||
| 
 | ||||
|         JSONObject siteJson = new JSONObject(); | ||||
|         siteJson.put("chapterUrlRegexOnMulu", ""); | ||||
|         siteJson.put("chapterUrlPattern", "/book/[\\d]+/[\\d]+\\.html$"); | ||||
| 
 | ||||
|         /* | ||||
|         String[] chapters = NovelParseUtil.getChapters(url, content, siteJson); | ||||
| 
 | ||||
| 
 | ||||
|         if (chapters != null) { | ||||
|             for (int i = 0; i < chapters.length; i += 2) { | ||||
|                Log.d(TAG,String.format("%s-->%s", chapters[i], chapters[i+1])); | ||||
|             } | ||||
|         } | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         siteJson.put("chapterUrlRegexOnMulu", "<dd> <a[^>]*href=\"(/book/[\\d]+/[\\d]+\\.html)\">([^<]+)</a></dd>"); | ||||
|         String[] chapters2 = NovelParseUtil.getChapters(url, content, siteJson); | ||||
|         if (chapters2 != null) { | ||||
|             for (int i = 0; i < chapters2.length; i += 2) { | ||||
|                 Log.d(TAG, String.format("%s-->%s", chapters2[i], chapters2[i + 1])); | ||||
|                 Chapter chapter = new Chapter(); | ||||
|                 chapter.setChapterName(chapters2[i + 1]); | ||||
|                 chapter.setChapterUrl(chapters2[i ]); | ||||
|                 mChapters.add(chapter); | ||||
|         mChapters = NovelParseUtil.getChapters(url, content, siteJson); | ||||
|         if (mChapters != null) { | ||||
|             int lastReadChapt = mNovel.getLastReadChapt(); | ||||
|          //   int index =lastReadChapt*2-2; | ||||
| 
 | ||||
|             } | ||||
|             lastReadChapt = lastReadChapt >=mChapters.size() ? mChapters.size() -1:lastReadChapt; | ||||
|             lastReadChapt = lastReadChapt <=0 ? 1:lastReadChapt; | ||||
|             mChapter =mChapters.get(lastReadChapt-1); | ||||
| 
 | ||||
|            /* | ||||
|             siteJson.put("chapterContentRegex", "<div id=\"content\">([\\s\\S]+?)</div>"); | ||||
|             siteJson.put("chapterContentDumpRegex", "<script>chaptererror();</script>"); | ||||
| 
 | ||||
| 
 | ||||
|             for (int i = 0; i < chapters2.length; i += 2) { | ||||
|                 Request request = new Request.Builder() | ||||
|                         .url(chapters2[i]) | ||||
|                         // .header("User-Agent", "OkHttp Example") | ||||
|                         .build(); | ||||
|                 Response response = HttpMethods.getOkClient().newCall(request).execute(); | ||||
|                //     Log.d(TAG,String.format("%s-->%s\n%s"                     , chapters2[i], chapters2[i+1]      , NovelParseUtil.getChapterContent(response.body().string(), siteJson))); | ||||
|             } | ||||
|             */ | ||||
|         } | ||||
|     } catch (JSONException e) { | ||||
|    // } catch (JSONException | IOException e) { | ||||
|  | @ -368,7 +431,7 @@ void onResponseProcess( String content ,String url){ | |||
|      //   result.close(); | ||||
|      //   if (result2 != null) result2.close(); | ||||
|     } | ||||
| } | ||||
| }*/ | ||||
| 
 | ||||
|     //----------------绑定列表 | ||||
| 
 | ||||
|  | @ -398,126 +461,5 @@ void onResponseProcess( String content ,String url){ | |||
|          super.onStop(); | ||||
|       //   blurLayout.pauseBlur(); | ||||
|     } | ||||
| /* | ||||
|     class BookListAdapter extends RecyclerView.Adapter< BookListAdapter.MyViewHolder> { | ||||
|         private final int EMPTY_VIEW = 1; | ||||
|         private final int PROGRESS_VIEW = 2; | ||||
|         private final int IMAGE_VIEW = 3; | ||||
| 
 | ||||
|         private Context context; | ||||
|         private List<String> mDatas = new ArrayList<String>(); | ||||
|         private OnItemClickListener mOnItemClickListener; | ||||
|         private int listItemID; | ||||
|         public BookListAdapter(Context context,List<String> mDatas,int listItemID,OnItemClickListener clickLitener) { | ||||
|             this.context = context; | ||||
|             this.mDatas = mDatas; | ||||
|             this.mOnItemClickListener = clickLitener; | ||||
|             this.listItemID = listItemID; | ||||
|         } | ||||
|         public BookListAdapter(Context context, OnItemClickListener clickLitener) { | ||||
|             this.context = context; | ||||
|             this.mOnItemClickListener = clickLitener; | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public int getItemViewType(int position) { | ||||
|             if(mDatas.size() == 0){ | ||||
|                 return EMPTY_VIEW; | ||||
|             } else if(mDatas.get(position) == null){ | ||||
|                 return PROGRESS_VIEW; | ||||
|             } else { | ||||
|                 return super.getItemViewType(position); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public  MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) | ||||
|         { | ||||
|              BookListAdapter.MyViewHolder holder = new  BookListAdapter.MyViewHolder(LayoutInflater.from( | ||||
|                     context).inflate(listItemID, parent, | ||||
|                     false)); | ||||
|             return holder; | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         public void setParameters(List<String> mDatas,int listItemID ) { | ||||
|             this.mDatas = mDatas; | ||||
|             this.listItemID = listItemID; | ||||
|         } | ||||
| 
 | ||||
|         public void setOnItemClickLitener(OnItemClickListener mOnItemClickLitener) | ||||
|         { | ||||
|             this.mOnItemClickListener = mOnItemClickLitener; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void onBindViewHolder( BookListAdapter.MyViewHolder holder, int position) | ||||
|         { | ||||
|             holder.tvTitle.setText(mDatas.get(position)); | ||||
|             holder.tvAuthor.setText("金庸" +position); | ||||
|             holder.tvCate.setText("cate"+position); | ||||
|             holder.tvDesc.setText("this is desc " +position); | ||||
|             // 如果设置了回调,则设置点击事件 | ||||
|             if (mOnItemClickListener != null) | ||||
|             { | ||||
|                 holder.itemView.setOnClickListener(new View.OnClickListener() | ||||
|                 { | ||||
|                     @Override | ||||
|                     public void onClick(View v) | ||||
|                     { | ||||
|                         int pos = holder.getLayoutPosition(); | ||||
|                         mOnItemClickListener.onItemClick(holder.itemView, pos); | ||||
|                     } | ||||
|                 }); | ||||
| 
 | ||||
|                 holder.itemView.setOnLongClickListener(new View.OnLongClickListener() | ||||
|                 { | ||||
|                     @Override | ||||
|                     public boolean onLongClick(View v) | ||||
|                     { | ||||
|                         int pos = holder.getLayoutPosition(); | ||||
|                         mOnItemClickListener.onItemLongClick(holder.itemView, pos); | ||||
|                         return false; | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public int getItemCount() | ||||
|         { | ||||
|             return mDatas.size(); | ||||
|         } | ||||
|         public void addData(int position) { | ||||
|             mDatas.add(position, "Insert One"); | ||||
|             notifyItemInserted(position); | ||||
|         } | ||||
| 
 | ||||
|         public void removeData(int position) { | ||||
|             mDatas.remove(position); | ||||
|             notifyItemRemoved(position); | ||||
|         } | ||||
|         class MyViewHolder extends RecyclerView.ViewHolder | ||||
|         { | ||||
|             @BindView(R.id.title) | ||||
|             TextView tvTitle; | ||||
|             @BindView(R.id.author) | ||||
|             TextView tvAuthor; | ||||
|             @BindView(R.id.category) | ||||
|             TextView tvCate; | ||||
|             @BindView(R.id.desc) | ||||
|             TextView tvDesc; | ||||
|             public MyViewHolder(View view) | ||||
|             { | ||||
|                 super(view); | ||||
|                 ButterKnife.bind(this, view); | ||||
|                 //tvTitle = (TextView) view.findViewById(R.id.title); | ||||
|                 // tvAuthor = (TextView) view.findViewById(R.id.author); | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     */ | ||||
| } | ||||
|  |  | |||
|  | @ -157,7 +157,7 @@ public class FileActivity extends Activity_base { | |||
|             for (File file : files) { | ||||
|                 Novel bookList = new Novel(); | ||||
|                 String bookName = Fileutil.getFileNameNoEx(file.getName()); | ||||
|                 bookList.setNovelName(bookName); | ||||
|                 bookList.setName(bookName); | ||||
|                 bookList.setNovelPath(file.getAbsolutePath()); | ||||
|                 bookLists.add(bookList); | ||||
|             } | ||||
|  | @ -206,7 +206,7 @@ public class FileActivity extends Activity_base { | |||
|                     adapter.cancel(); | ||||
|                     break; | ||||
|                 case REPEAT: | ||||
|                     msg = "书本" + repeatBookList.getNovelName() + "重复了"; | ||||
|                     msg = "书本" + repeatBookList.getName() + "重复了"; | ||||
|                     break; | ||||
|             } | ||||
| 
 | ||||
|  |  | |||
|  | @ -119,7 +119,7 @@ public abstract class BasicFragment extends Fragment { | |||
|         { | ||||
|             Novel bk = new Novel(); | ||||
|             bk.setAuthor("金庸"); | ||||
|             bk.setNovelName("射雕英雄传" +(char)i); | ||||
|             bk.setName("射雕英雄传" +(char)i); | ||||
|             bk.setNovelType("武侠"); | ||||
|             bk.setDescription("南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事"); | ||||
|             mDatas.add(bk); | ||||
|  | @ -143,7 +143,7 @@ public abstract class BasicFragment extends Fragment { | |||
|             book.setLastReadPos(book1.getLastReadPos()); | ||||
|             book.setLastReadChapt(book1.getLastReadChapt()); | ||||
|         } | ||||
|         Toast.makeText(activity, book.getNovelName() + "加载",  Toast.LENGTH_SHORT).show(); | ||||
|         Toast.makeText(activity, book.getName() + "加载",  Toast.LENGTH_SHORT).show(); | ||||
| 
 | ||||
|         final String path = book.getNovelPath(); | ||||
|         if(null ==path) { | ||||
|  | @ -167,7 +167,7 @@ public abstract class BasicFragment extends Fragment { | |||
|                     }).setCancelable(true).show(); | ||||
|             return; | ||||
|         } | ||||
|        // ReadActivity.openBook(book ,activity); | ||||
|         ReadActivity.openBook(book ,activity); | ||||
| 
 | ||||
|     } | ||||
|     void showShudanDetail(int shuandanId){ | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ public class BookMarkFragment extends BasicFragment { | |||
|     @BindView(R.id.lv_bookmark) | ||||
|     ListView lv_bookmark; | ||||
| 
 | ||||
|     private String bookpath; | ||||
|     private int novelId; | ||||
|     private String mArgument; | ||||
|     private List<BookMarks> bookMarksList; | ||||
|     private MarkAdapter markAdapter; | ||||
|  | @ -44,10 +44,10 @@ public class BookMarkFragment extends BasicFragment { | |||
|         pageFactory = PageFactory.getInstance(); | ||||
|         Bundle bundle = getArguments(); | ||||
|         if (bundle != null) { | ||||
|             bookpath = bundle.getString(ARGUMENT); | ||||
|             novelId = bundle.getInt(ARGUMENT); | ||||
|         } | ||||
|         bookMarksList = new ArrayList<>(); | ||||
|         bookMarksList = LitePal.where("bookpath = ?", bookpath).find(BookMarks.class); | ||||
|         bookMarksList = LitePal.where("novelId = ?", novelId+"").find(BookMarks.class); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|  | @ -79,7 +79,7 @@ public class BookMarkFragment extends BasicFragment { | |||
|                             public void onClick(DialogInterface dialog, int which) { | ||||
|                                 LitePal.delete(BookMarks.class,bookMarksList.get(position).getId()); | ||||
|                                 bookMarksList.clear(); | ||||
|                                 bookMarksList.addAll(LitePal.where("bookpath = ?", bookpath).find(BookMarks.class)); | ||||
|                                 bookMarksList.addAll(LitePal.where("novelId = ?", novelId+"").find(BookMarks.class)); | ||||
|                                 markAdapter.notifyDataSetChanged(); | ||||
|                             } | ||||
|                         }).setCancelable(true).show(); | ||||
|  | @ -101,13 +101,13 @@ public class BookMarkFragment extends BasicFragment { | |||
| 
 | ||||
|     /** | ||||
|      * 用于从Activity传递数据到Fragment | ||||
|      * @param bookpath | ||||
|      * @param | ||||
|      * @return | ||||
|      */ | ||||
|     public static BookMarkFragment newInstance(String bookpath) | ||||
|     public static BookMarkFragment newInstance(int novelId) | ||||
|     { | ||||
|         Bundle bundle = new Bundle(); | ||||
|         bundle.putString(ARGUMENT, bookpath); | ||||
|         bundle.putInt(ARGUMENT, novelId); | ||||
|         BookMarkFragment bookMarkFragment = new BookMarkFragment(); | ||||
|         bookMarkFragment.setArguments(bundle); | ||||
|         return bookMarkFragment; | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ public class CatalogFragment extends BasicFragment { | |||
|     @Override | ||||
|     protected void initData() { | ||||
|         pageFactory = PageFactory.getInstance(); | ||||
|         catalogueList.addAll(pageFactory.getDirectoryList()); | ||||
|         catalogueList.addAll(pageFactory.getChapters()); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -85,7 +85,7 @@ public class Fragment_Shelf extends BasicFragment { | |||
|         flag = new boolean[100]; | ||||
|        // mDatas = initData(mDatas,'X'); | ||||
| 
 | ||||
|         bookLists = LitePal.findAll(Novel.class); | ||||
|         bookLists = LitePal.where("isOnShelf=? or novelId=? ","1","").find(Novel.class); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -201,7 +201,7 @@ public class Fragment_Shelf extends BasicFragment { | |||
|                 .setBackgroundColor(getResources().getColor(android.R.color.transparent)); | ||||
| 
 | ||||
|         TextView tv =(TextView) bottomSheetDialog.findViewById(R.id.bdTitle); | ||||
|         tv.setText(bookLists.get(position).getNovelName()); | ||||
|         tv.setText(bookLists.get(position).getName()); | ||||
| 
 | ||||
|         bottomSheetDialog.show(); | ||||
|     } | ||||
|  | @ -399,7 +399,7 @@ public class Fragment_Shelf extends BasicFragment { | |||
|         public void onBindViewHolder(MyViewHolder holder, int position) | ||||
|         { | ||||
| 
 | ||||
|             holder.tvTitle.setText(mDatas.get(position).getNovelName()); | ||||
|             holder.tvTitle.setText(mDatas.get(position).getName()); | ||||
|             if(holder.tvAuthor!=null) holder.tvAuthor.setText(mDatas.get(position).getAuthor()); | ||||
|             if(holder.tvCate!=null)   holder.tvCate.setText(mDatas.get(position).getNovelType()); | ||||
|             if(holder.tvDesc!=null)   holder.tvDesc.setText(mDatas.get(position).getDescription()); | ||||
|  |  | |||
|  | @ -72,11 +72,11 @@ public class MarkActivity extends Activity_base { | |||
|             } | ||||
|         }); | ||||
|         if (getSupportActionBar() != null) { | ||||
|             getSupportActionBar().setTitle(FileUtils.getFileName(pageFactory.getBookPath())); | ||||
|             getSupportActionBar().setTitle(pageFactory.getBookName()); | ||||
|         } | ||||
| 
 | ||||
|         setTabsValue(); | ||||
|         pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager(),pageFactory.getBookPath())); | ||||
|         pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager(),pageFactory.getNovle().getId())); | ||||
|         tabs.setViewPager(pager); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -60,7 +60,7 @@ import butterknife.OnClick; | |||
| public class ReadActivity extends  Activity_base implements SpeechSynthesizerListener { | ||||
|     private static final String TAG = "ReadActivity"; | ||||
|     private final static String EXTRA_BOOK = "book"; | ||||
|     private final static String EXTRA_CHAPTERS = "chapters"; | ||||
|    // private final static String EXTRA_CHAPTER = "chapter"; | ||||
|     private final static int MESSAGE_CHANGEPROGRESS = 1; | ||||
| 
 | ||||
|     @BindView(R.id.bookpage) | ||||
|  | @ -106,7 +106,7 @@ public class ReadActivity extends  Activity_base implements SpeechSynthesizerLis | |||
|     private Config config; | ||||
|     private WindowManager.LayoutParams lp; | ||||
|     private Novel book; | ||||
|     private List<Chapter> mChapters; | ||||
|    // private  Chapter  mChapter; | ||||
|     private PageFactory pageFactory; | ||||
|     private int screenWidth, screenHeight; | ||||
|     // popwindow是否显示 | ||||
|  | @ -198,12 +198,12 @@ public class ReadActivity extends  Activity_base implements SpeechSynthesizerLis | |||
|         //获取intent中的携带的信息 | ||||
|         Intent intent = getIntent(); | ||||
|         book = (Novel) intent.getSerializableExtra(EXTRA_BOOK); | ||||
|         mChapters = (ArrayList<Chapter>) intent.getSerializableExtra(EXTRA_CHAPTERS); | ||||
|     //    mChapter = ( Chapter ) intent.getSerializableExtra(EXTRA_CHAPTER); | ||||
|         bookpage.setPageMode(config.getPageMode()); | ||||
|         pageFactory.setPageWidget(bookpage); | ||||
| 
 | ||||
|         try { | ||||
|             pageFactory.openBook(book,mChapters); | ||||
|             pageFactory.openBook(book,this); | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|             Toast.makeText(this, "打开电子书失败", Toast.LENGTH_SHORT).show(); | ||||
|  | @ -474,7 +474,7 @@ public class ReadActivity extends  Activity_base implements SpeechSynthesizerLis | |||
| 
 | ||||
|         if (id == R.id.action_add_bookmark){ | ||||
|             if (pageFactory.getCurrentPage() != null) { | ||||
|                 List<BookMarks> bookMarksList = LitePal.where("bookpath = ? and begin = ?", pageFactory.getBookPath(),pageFactory.getCurrentPage().getBegin() + "").find(BookMarks.class); | ||||
|                 List<BookMarks> bookMarksList = LitePal.where("novelId = ? and begin = ?", pageFactory.getNovle().getId()+"",pageFactory.getCurrentPage().getBegin() + "").find(BookMarks.class); | ||||
| 
 | ||||
|                 if (!bookMarksList.isEmpty()){ | ||||
|                     Toast.makeText(ReadActivity.this, "该书签已存在", Toast.LENGTH_SHORT).show(); | ||||
|  | @ -491,7 +491,7 @@ public class ReadActivity extends  Activity_base implements SpeechSynthesizerLis | |||
|                         bookMarks.setTime(time); | ||||
|                         bookMarks.setBegin(pageFactory.getCurrentPage().getBegin()); | ||||
|                         bookMarks.setText(word); | ||||
|                         bookMarks.setBookpath(pageFactory.getBookPath()); | ||||
|                         bookMarks.setNovelId(pageFactory.getNovle().getId()); | ||||
|                         bookMarks.save(); | ||||
| 
 | ||||
|                         Toast.makeText(ReadActivity.this, "书签添加成功", Toast.LENGTH_SHORT).show(); | ||||
|  | @ -527,14 +527,15 @@ public class ReadActivity extends  Activity_base implements SpeechSynthesizerLis | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public static boolean openBook(final Novel book,final ArrayList<Chapter> chapters ,Activity context) { | ||||
|     public static boolean openBook(final Novel book, Activity context) { | ||||
|         if (book == null){ | ||||
|             throw new NullPointerException("Novel can not be null"); | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         Intent intent = new Intent(context, ReadActivity.class); | ||||
|         intent.putExtra(EXTRA_BOOK, book); | ||||
|         intent.putExtra(EXTRA_CHAPTERS, chapters); | ||||
|       //  intent.putExtra(EXTRA_CHAPTER, chapter); | ||||
| 
 | ||||
|         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); | ||||
|         context.overridePendingTransition(R.anim.in_from_right, R.anim.out_to_left); | ||||
|  |  | |||
|  | @ -80,7 +80,7 @@ public  class BookListAdapter extends RecyclerView.Adapter< MyViewHolder> { | |||
| 
 | ||||
|     @Override | ||||
|     public void onBindViewHolder(MyViewHolder holder, int position) { | ||||
|         holder.tvTitle.setText(mDatas.get(position).getNovelName()); | ||||
|         holder.tvTitle.setText(mDatas.get(position).getName()); | ||||
|         if (holder.tvAuthor != null) holder.tvAuthor.setText(mDatas.get(position).getAuthor()); | ||||
|         if (holder.tvCate != null) holder.tvCate.setText(mDatas.get(position).getNovelType()); | ||||
|         if (holder.tvDesc != null) holder.tvDesc.setText(mDatas.get(position).getDescription()); | ||||
|  |  | |||
|  | @ -15,12 +15,12 @@ import com.novelbook.android.Fragments.CatalogFragment; | |||
| public class MyPagerAdapter extends FragmentPagerAdapter { | ||||
|     private CatalogFragment catalogueFragment; | ||||
|     private BookMarkFragment bookMarkFragment; | ||||
|     private String bookPath; | ||||
|     private int novelId; | ||||
|     private final String[] titles = { "目录", "书签" }; | ||||
| 
 | ||||
|     public MyPagerAdapter(FragmentManager fm,String bookPath) { | ||||
|     public MyPagerAdapter(FragmentManager fm,int novelId) { | ||||
|         super(fm); | ||||
|         this.bookPath = bookPath; | ||||
|         this.novelId = novelId; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|  | @ -42,7 +42,7 @@ public class MyPagerAdapter extends FragmentPagerAdapter { | |||
|                     //创建bookMarkFragment实例时同时把需要intent中的值传入 | ||||
| //                    catalogueFragment = CatalogFragment | ||||
|                    // bookMarkFragment = BookMarkFragment.newInstance(MarkActivity.getBookpath_intent()); | ||||
|                     catalogueFragment = CatalogFragment.newInstance(bookPath); | ||||
|                     catalogueFragment = CatalogFragment.newInstance(""); | ||||
|                 } | ||||
|                 return catalogueFragment; | ||||
| 
 | ||||
|  | @ -51,7 +51,7 @@ public class MyPagerAdapter extends FragmentPagerAdapter { | |||
|                     //catalogueFragment = new CatalogueFragment(); | ||||
|                   //  catalogueFragment = CatalogueFragment.newInstance(MarkActivity.getBookpath_intent()); | ||||
| //                    bookMarkFragment = BookMarkFragment.newInstance(MarkActivity.getBookpath_intent()); | ||||
|                     bookMarkFragment = BookMarkFragment.newInstance(bookPath); | ||||
|                     bookMarkFragment = BookMarkFragment.newInstance(novelId); | ||||
|                 } | ||||
|                 return bookMarkFragment; | ||||
|         } | ||||
|  |  | |||
|  | @ -96,7 +96,7 @@ public class ShelfAdapter extends BaseAdapter implements DragGridListener { | |||
|                 viewHolder.deleteItem_IB.setVisibility(View.INVISIBLE); | ||||
|             } | ||||
|             viewHolder.name.setVisibility(View.VISIBLE); | ||||
|             String fileName = bilist.get(position).getNovelName(); | ||||
|             String fileName = bilist.get(position).getName(); | ||||
|             viewHolder.name.setText(fileName); | ||||
|         }else { | ||||
|             contentView.setVisibility(View.INVISIBLE); | ||||
|  | @ -167,9 +167,9 @@ public class ShelfAdapter extends BaseAdapter implements DragGridListener { | |||
|     public void updateBookPosition (int position,int databaseId,List<Novel> bookLists) { | ||||
|         Novel book = new Novel(); | ||||
|         String bookpath = bookLists.get(position).getNovelPath(); | ||||
|         String bookname = bookLists.get(position).getNovelName(); | ||||
|         String bookname = bookLists.get(position).getName(); | ||||
|         book.setNovelPath(bookpath); | ||||
|         book.setNovelName(bookname); | ||||
|         book.setName(bookname); | ||||
|         book.setLastReadPos(bookLists.get(position).getLastReadPos()); | ||||
|         book.setLastReadChapt(bookLists.get(position).getLastReadChapt()); | ||||
|         book.setCharset(bookLists.get(position).getCharset()); | ||||
|  |  | |||
|  | @ -0,0 +1,22 @@ | |||
| package com.novelbook.android.bean; | ||||
| 
 | ||||
| public class NovelSites { | ||||
|  private  String novelId; | ||||
|  private  Site[] sites; | ||||
| 
 | ||||
|     public String getNovelId() { | ||||
|         return novelId; | ||||
|     } | ||||
| 
 | ||||
|     public void setNovelId(String novelId) { | ||||
|         this.novelId = novelId; | ||||
|     } | ||||
| 
 | ||||
|     public Site[] getSites() { | ||||
|         return sites; | ||||
|     } | ||||
| 
 | ||||
|     public void setSites(Site[] sites) { | ||||
|         this.sites = sites; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,31 @@ | |||
| package com.novelbook.android.bean; | ||||
| 
 | ||||
| public class Site { | ||||
|     private String domain; | ||||
|     private String muluUrl; | ||||
|     private Boolean selectedByDefault; | ||||
| 
 | ||||
|     public String getDomain() { | ||||
|         return domain; | ||||
|     } | ||||
| 
 | ||||
|     public void setDomain(String domain) { | ||||
|         this.domain = domain; | ||||
|     } | ||||
| 
 | ||||
|     public String getMuluUrl() { | ||||
|         return muluUrl; | ||||
|     } | ||||
| 
 | ||||
|     public void setMuluUrl(String muluUrl) { | ||||
|         this.muluUrl = muluUrl; | ||||
|     } | ||||
| 
 | ||||
|     public Boolean getSelectedByDefault() { | ||||
|         return selectedByDefault; | ||||
|     } | ||||
| 
 | ||||
|     public void setSelectedByDefault(Boolean selectedByDefault) { | ||||
|         this.selectedByDefault = selectedByDefault; | ||||
|     } | ||||
| } | ||||
|  | @ -11,7 +11,7 @@ public class BookMarks extends LitePalSupport { | |||
|   //  private int count; | ||||
|     private String text; | ||||
|     private String time; | ||||
|     private String bookpath; | ||||
|     private int novelId; | ||||
|     public int getId() { | ||||
|         return this.id; | ||||
|     } | ||||
|  | @ -44,12 +44,12 @@ public class BookMarks extends LitePalSupport { | |||
|         this.begin = begin; | ||||
|     } | ||||
| 
 | ||||
|     public String getBookpath() { | ||||
|         return this.bookpath; | ||||
|     public int getNovelId() { | ||||
|         return this.novelId; | ||||
|     } | ||||
| 
 | ||||
|     public void setBookpath(String bookpath) { | ||||
|         this.bookpath = bookpath; | ||||
|     public void setNovelId(int novelId  ) { | ||||
|         this.novelId = novelId; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -8,14 +8,22 @@ import java.io.Serializable; | |||
| 
 | ||||
| public class  Chapter extends LitePalSupport implements Serializable { | ||||
|     private int id; | ||||
|     private int novelId; | ||||
|     private String  novelPath; | ||||
|     private int novelId;//本地小说id | ||||
|     private String  novelPath; //离线导入小说文件地址 | ||||
|     private String chapterName; | ||||
|     private long novelChapterStartPos; | ||||
|     private String chapterUrl; | ||||
|     private int length; | ||||
|     private String chapterPath; | ||||
|     private String chapterPath; //缓存地址 | ||||
|     private String domain; //目标 site | ||||
| 
 | ||||
|     public String getDomain() { | ||||
|         return domain; | ||||
|     } | ||||
| 
 | ||||
|     public void setDomain(String domain) { | ||||
|         this.domain = domain; | ||||
|     } | ||||
| 
 | ||||
|     public int getId() { | ||||
|         return id; | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| package com.novelbook.android.db; | ||||
| 
 | ||||
| 
 | ||||
| import org.litepal.annotation.Column; | ||||
| import org.litepal.crud.LitePalSupport; | ||||
| 
 | ||||
| import java.io.Serializable; | ||||
|  | @ -8,13 +9,14 @@ import java.io.Serializable; | |||
| 
 | ||||
| public class Novel extends LitePalSupport implements Serializable{ | ||||
|     private int id; | ||||
|     @Column(unique = true, nullable = true) | ||||
|     private String novelId; | ||||
|     private String novelName; | ||||
|     private String name; | ||||
|     private String domain; | ||||
|     private String muluUrl; | ||||
|     private String novelPath; | ||||
|     private long lastReadPos; | ||||
|     private long lastReadChapt=1; | ||||
|     private int lastReadChapt=1; | ||||
|     private String charset; | ||||
|     private String novelType; | ||||
|     private String novelType2; | ||||
|  | @ -44,12 +46,12 @@ public class Novel extends LitePalSupport implements Serializable{ | |||
|         this.novelId = novelId; | ||||
|     } | ||||
| 
 | ||||
|     public String getNovelName() { | ||||
|         return novelName; | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     public void setNovelName(String novelName) { | ||||
|         this.novelName = novelName; | ||||
|     public void setName(String novelName) { | ||||
|         this.name = novelName; | ||||
|     } | ||||
| 
 | ||||
|     public String getDomain() { | ||||
|  | @ -84,11 +86,11 @@ public class Novel extends LitePalSupport implements Serializable{ | |||
|         this.lastReadPos = lastReadPos; | ||||
|     } | ||||
| 
 | ||||
|     public long getLastReadChapt() { | ||||
|     public int getLastReadChapt() { | ||||
|         return lastReadChapt; | ||||
|     } | ||||
| 
 | ||||
|     public void setLastReadChapt(long lastReadChapt) { | ||||
|     public void setLastReadChapt(int lastReadChapt) { | ||||
|         this.lastReadChapt = lastReadChapt; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,98 @@ | |||
| package com.novelbook.android.db; | ||||
| 
 | ||||
| import org.litepal.annotation.Column; | ||||
| import org.litepal.crud.LitePalSupport; | ||||
| 
 | ||||
| public class SiteRule extends LitePalSupport { | ||||
|     private int id; | ||||
|     private String name; | ||||
|     @Column(unique = true, nullable = false) | ||||
|     private String domain; | ||||
|     private String chapterUrlRegexOnMulu; | ||||
|     private String chapterContentDumpRegex; | ||||
|     private String chapterContentRegex; | ||||
|     private String muluUrlPattern; | ||||
|     private String chapterUrlPattern; | ||||
|     private long miniInterval4AccessChapter; | ||||
|     private String[] headers; | ||||
| 
 | ||||
|     public int getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public void setId(int id) { | ||||
|         this.id = id; | ||||
|     } | ||||
| 
 | ||||
|     public String getChapterContentRegex() { | ||||
|         return chapterContentRegex; | ||||
|     } | ||||
| 
 | ||||
|     public void setChapterContentRegex(String chapterContentRegex) { | ||||
|         this.chapterContentRegex = chapterContentRegex; | ||||
|     } | ||||
| 
 | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     public void setName(String name) { | ||||
|         this.name = name; | ||||
|     } | ||||
| 
 | ||||
|     public String getDomain() { | ||||
|         return domain; | ||||
|     } | ||||
| 
 | ||||
|     public void setDomain(String domain) { | ||||
|         this.domain = domain; | ||||
|     } | ||||
| 
 | ||||
|     public String getChapterUrlRegexOnMulu() { | ||||
|         return chapterUrlRegexOnMulu; | ||||
|     } | ||||
| 
 | ||||
|     public void setChapterUrlRegexOnMulu(String chapterUrlRegexOnMulu) { | ||||
|         this.chapterUrlRegexOnMulu = chapterUrlRegexOnMulu; | ||||
|     } | ||||
| 
 | ||||
|     public String getChapterContentDumpRegex() { | ||||
|         return chapterContentDumpRegex; | ||||
|     } | ||||
| 
 | ||||
|     public void setChapterContentDumpRegex(String chapterContentDumpRegex) { | ||||
|         this.chapterContentDumpRegex = chapterContentDumpRegex; | ||||
|     } | ||||
| 
 | ||||
|     public String getMuluUrlPattern() { | ||||
|         return muluUrlPattern; | ||||
|     } | ||||
| 
 | ||||
|     public void setMuluUrlPattern(String muluUrlPattern) { | ||||
|         this.muluUrlPattern = muluUrlPattern; | ||||
|     } | ||||
| 
 | ||||
|     public String getChapterUrlPattern() { | ||||
|         return chapterUrlPattern; | ||||
|     } | ||||
| 
 | ||||
|     public void setChapterUrlPattern(String chapterUrlPattern) { | ||||
|         this.chapterUrlPattern = chapterUrlPattern; | ||||
|     } | ||||
| 
 | ||||
|     public long getMiniInterval4AccessChapter() { | ||||
|         return miniInterval4AccessChapter; | ||||
|     } | ||||
| 
 | ||||
|     public void setMiniInterval4AccessChapter(long miniInterval4AccessChapter) { | ||||
|         this.miniInterval4AccessChapter = miniInterval4AccessChapter; | ||||
|     } | ||||
| 
 | ||||
|     public String[] getHeaders() { | ||||
|         return headers; | ||||
|     } | ||||
| 
 | ||||
|     public void setHeaders(String[] headers) { | ||||
|         this.headers = headers; | ||||
|     } | ||||
| } | ||||
|  | @ -289,7 +289,7 @@ public class DirectoryFragment extends Fragment implements View.OnClickListener | |||
|     @Override | ||||
|     public void onResume() { | ||||
|         super.onResume(); | ||||
|         bookLists = LitePal.findAll(Novel.class); | ||||
|         bookLists = LitePal.where("isOnShelf=?","1").find(  Novel.class); | ||||
|         listAdapter.notifyDataSetChanged(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -321,8 +321,9 @@ public class DirectoryFragment extends Fragment implements View.OnClickListener | |||
|             for (ListItem item : checkItems) { | ||||
|                 Novel bookList = new Novel(); | ||||
|                 String bookName = FileUtils.getFileName(item.thumb); | ||||
|                 bookList.setNovelName(bookName); | ||||
|                 bookList.setName(bookName); | ||||
|                 bookList.setNovelPath(item.thumb); | ||||
|                 bookList.setOnShelf(true); | ||||
|                 bookLists.add(bookList); | ||||
|             } | ||||
|             SaveBookToSqlLiteTask mSaveBookToSqlLiteTask = new SaveBookToSqlLiteTask(); | ||||
|  | @ -363,7 +364,7 @@ public class DirectoryFragment extends Fragment implements View.OnClickListener | |||
|         protected Integer doInBackground(List<Novel>... params) { | ||||
|             List<Novel> bookLists = params[0]; | ||||
|             for (Novel bookList : bookLists){ | ||||
|                 List<Novel> books = LitePal.where("bookpath = ?", bookList.getNovelPath()).find(Novel.class); | ||||
|                 List<Novel> books = LitePal.where("novelPath = ?", bookList.getNovelPath()).find(Novel.class); | ||||
|                 if (books.size() > 0){ | ||||
|                     repeatBookList = bookList; | ||||
|                     return REPEAT; | ||||
|  | @ -390,12 +391,12 @@ public class DirectoryFragment extends Fragment implements View.OnClickListener | |||
|                 case SUCCESS: | ||||
|                     msg = "导入书本成功"; | ||||
|                     checkItems.clear(); | ||||
|                     bookLists = LitePal.findAll(Novel.class); | ||||
|                     bookLists = LitePal.where("isOnShelf=?","1").find(  Novel.class);//LitePal.findAll(Novel.class); | ||||
|                     listAdapter.notifyDataSetChanged(); | ||||
|                     changgeCheckBookNum(); | ||||
|                     break; | ||||
|                 case REPEAT: | ||||
|                     msg = "书本" + repeatBookList.getNovelName() + "重复了"; | ||||
|                     msg = "书本" + repeatBookList.getName() + "重复了"; | ||||
|                     break; | ||||
|             } | ||||
| 
 | ||||
|  | @ -636,7 +637,7 @@ public class DirectoryFragment extends Fragment implements View.OnClickListener | |||
|             public void onClick(DialogInterface dialog, int which) { | ||||
|                 Novel bookList = new Novel(); | ||||
|                 String bookName = FileUtils.getFileName(path); | ||||
|                 bookList.setNovelName(bookName); | ||||
|                 bookList.setName(bookName); | ||||
|                 bookList.setNovelPath(path); | ||||
| 
 | ||||
|                 boolean isSave = false; | ||||
|  | @ -649,7 +650,7 @@ public class DirectoryFragment extends Fragment implements View.OnClickListener | |||
|                 if (!isSave){ | ||||
|                     bookList.save(); | ||||
|                 } | ||||
|                 ReadActivity.openBook(bookList,null,getActivity()); | ||||
|                 ReadActivity.openBook(bookList, getActivity()); | ||||
|             } | ||||
|         }).show(); | ||||
|     } | ||||
|  |  | |||
|  | @ -34,13 +34,18 @@ public interface HttpApi { | |||
|     @Streaming | ||||
|     Call<ResponseBody> downloadFile(@Url String fileUrl); | ||||
| 
 | ||||
| 
 | ||||
| //http://xiaoshuofenxiang.com/api/g/ | ||||
|     @GET("g") | ||||
|     Observable<ResponseBody> getMasterDomain(); | ||||
|     //http://xiaoshuofenxiang.com/api/n/f2619820112625133c14dcb170f5e092.json | ||||
|     @GET("n/{id}.json") | ||||
|     Observable<ResponseBody> getNovel(@Path("id") String novelId); | ||||
| 
 | ||||
|     //http://xiaoshuofenxiang.com/api/n/f2619820112625133c14dcb170f5e092.mulu-urls.json | ||||
|     @GET("n/{id}.mulu-urls.json") | ||||
|     Observable<ResponseBody> getNovelMulu(@Path("id") String novelId); | ||||
|     Observable<ResponseBody> getNovelSites(@Path("id") String novelId); | ||||
| 
 | ||||
|     @GET("s/{siteName}.json") | ||||
|     Observable<ResponseBody> getNovelRegex(@Path("siteName") String siteName); | ||||
|     //http://xiaoshuofenxiang.com/api/s/www.qu.la.json | ||||
|     @GET("s/{siteDomain}.json") | ||||
|     Observable<ResponseBody> getNovelRule(@Path("siteDomain") String siteDomain); | ||||
| } | ||||
|  |  | |||
|  | @ -22,9 +22,12 @@ public class BookSubscribe { | |||
|         Observable<ResponseBody> observable =  HttpMethods.getInstance().getHttpApi().getNovel(novelId); | ||||
|         HttpMethods.getInstance().toSubscribe(observable, subscriber); | ||||
|     } | ||||
|     public static void getNovelMulu(String novelId,DisposableObserver<ResponseBody> subscriber){ | ||||
|         Observable<ResponseBody> observable =  HttpMethods.getInstance().getHttpApi().getNovelMulu(novelId); | ||||
|     public static void getNovelSites(String novelId,DisposableObserver<ResponseBody> subscriber){ | ||||
|         Observable<ResponseBody> observable =  HttpMethods.getInstance().getHttpApi().getNovelSites(novelId); | ||||
|         HttpMethods.getInstance().toSubscribe(observable, subscriber); | ||||
|     } | ||||
|     public static void getSiteRule(String domain,DisposableObserver<ResponseBody> subscriber){ | ||||
|         Observable<ResponseBody> observable =  HttpMethods.getInstance().getHttpApi().getNovelRule(domain); | ||||
|         HttpMethods.getInstance().toSubscribe(observable, subscriber); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ import retrofit2.converter.gson.GsonConverterFactory; | |||
| 
 | ||||
| public class HttpMethods { | ||||
|     public String TAG = "HttpMethods"; | ||||
|     public static final String CACHE_NAME = "yourApkName"; | ||||
|     public static final String CACHE_NAME = "ZHUIKE"; | ||||
|     public static String BASE_URL = URLConstant.BASE_URL; | ||||
|     private static final int DEFAULT_CONNECT_TIMEOUT = 30; | ||||
|     private static final int DEFAULT_WRITE_TIMEOUT = 30; | ||||
|  |  | |||
|  | @ -8,6 +8,8 @@ import com.novelbook.android.MyApp; | |||
| 
 | ||||
| import java.util.Random; | ||||
| 
 | ||||
| import okhttp3.Call; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Created by 眼神 on 2018/3/27. | ||||
|  | @ -86,7 +88,19 @@ public class NetUtil { | |||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     public static void cancelRequest(String tag) { | ||||
|         for (Call call : HttpMethods.getOkClient().dispatcher().queuedCalls()) { | ||||
|             if (call.request().tag().equals(tag)) | ||||
|                 call.cancel(); | ||||
|         } | ||||
| 
 | ||||
|         //B) go through the running calls and cancel if the tag matches: | ||||
|         for (Call call : HttpMethods.getOkClient().dispatcher().runningCalls()) { | ||||
|             if (call.request().tag().equals(tag)) | ||||
|                 call.cancel(); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public static String getUserAgent(){ | ||||
|       String[] uas = { | ||||
|  |  | |||
|  | @ -75,17 +75,17 @@ import butterknife.ButterKnife; | |||
|     { | ||||
|         holder.tvCateName .setText(mDatas.get(0).getNovelType()); | ||||
| 
 | ||||
|         holder.tvTitle.setText(mDatas.get(0).getNovelName()); | ||||
|         holder.tvTitle.setText(mDatas.get(0).getName()); | ||||
|         holder.tvAuthor.setText(mDatas.get(0).getAuthor()); | ||||
|         holder.tvCate.setText(mDatas.get(0).getNovelType()); | ||||
|         holder.tvDesc.setText(mDatas.get(0).getDescription()); | ||||
| 
 | ||||
|         holder.tvTitle2.setText(mDatas.get(1).getNovelName()); | ||||
|         holder.tvTitle2.setText(mDatas.get(1).getName()); | ||||
|         holder.tvAuthor2.setText(mDatas.get(1).getAuthor()); | ||||
|         holder.tvCate2.setText(mDatas.get(1).getNovelType()); | ||||
|         holder.tvDesc2.setText(mDatas.get(1).getDescription()); | ||||
| 
 | ||||
|         holder.tvTitle3.setText(mDatas.get(2).getNovelName()); | ||||
|         holder.tvTitle3.setText(mDatas.get(2).getName()); | ||||
|         holder.tvAuthor3.setText(mDatas.get(2).getAuthor()); | ||||
|         holder.tvCate3.setText(mDatas.get(2).getNovelType()); | ||||
|         holder.tvDesc3.setText(mDatas.get(2).getDescription()); | ||||
|  |  | |||
|  | @ -1,22 +1,36 @@ | |||
| package com.novelbook.android.utils; | ||||
| 
 | ||||
| import android.app.ProgressDialog; | ||||
| import android.content.ContentValues; | ||||
| import android.os.Environment; | ||||
| import android.content.Context; | ||||
| 
 | ||||
| 
 | ||||
| import android.os.Handler; | ||||
| import android.os.Looper; | ||||
| import android.os.Message; | ||||
| import android.text.TextUtils; | ||||
| import android.util.Log; | ||||
| import android.widget.Toast; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import com.novelbook.android.MyApp; | ||||
| import com.novelbook.android.bean.Cache; | ||||
| import com.novelbook.android.bean.NovelSites; | ||||
| import com.novelbook.android.bean.Site; | ||||
| import com.novelbook.android.db.SiteRule; | ||||
| import com.novelbook.android.db.Chapter; | ||||
| import com.novelbook.android.db.Novel; | ||||
| import com.novelbook.android.netsubscribe.BookSubscribe; | ||||
| import com.novelbook.android.netutils.HttpMethods; | ||||
| import com.novelbook.android.netutils.OnSuccessAndFaultListener; | ||||
| import com.novelbook.android.netutils.OnSuccessAndFaultSub; | ||||
| 
 | ||||
| 
 | ||||
| import org.json.JSONException; | ||||
| import org.json.JSONObject; | ||||
| import org.litepal.LitePal; | ||||
| 
 | ||||
| import java.io.Console; | ||||
| import java.io.File; | ||||
| import java.io.FileInputStream; | ||||
| import java.io.FileOutputStream; | ||||
|  | @ -25,20 +39,32 @@ import java.io.InputStreamReader; | |||
| import java.io.OutputStreamWriter; | ||||
| import java.lang.ref.WeakReference; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Date; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import okhttp3.Call; | ||||
| import okhttp3.Callback; | ||||
| import okhttp3.Request; | ||||
| import okhttp3.Response; | ||||
| import okhttp3.ResponseBody; | ||||
| 
 | ||||
| 
 | ||||
| public class BookUtil { | ||||
|     public static final  String TAG ="BookUtil"; | ||||
|     private static final String storagePath = Environment.getExternalStorageDirectory() + "/zhuike"; | ||||
|     private static final String storagePath =  FileUtils.getDiskCacheDir(MyApp.applicationContext);//Environment.getExternalStorageDirectory() + "/zhuike"; | ||||
|     private static final String cachedPath = storagePath + "/cache/"; | ||||
|     private static final String chapterPath = storagePath + "/chapter/"; | ||||
|     private static final String charachterType = "utf-8";//"UTF-16LE"; | ||||
|     private Context mContext; | ||||
|     private ProgressDialog progressDialog; | ||||
|     private MuluStatus mMuluStatus; //目录是否下载完成 | ||||
|     private Gson gson = new Gson(); | ||||
|     public void setContext(Context context) { | ||||
|         this.mContext = context; | ||||
|     } | ||||
| 
 | ||||
|     //存储的字符数 | ||||
|     public static final int cachedSize = 30000; | ||||
| //    protected final ArrayList<WeakReference<char[]>> myArray = new ArrayList<>(); | ||||
|  | @ -47,6 +73,9 @@ public class BookUtil { | |||
|     protected final ArrayList<Cache> myArray = new ArrayList<>(); | ||||
|     //目录 | ||||
|     private List<Chapter> mChapters = new ArrayList<>(); | ||||
|     //当前章节 | ||||
|    // private Chapter  mCurrentChapter; | ||||
| 
 | ||||
|     public List<Chapter> getChapters() { | ||||
|         return mChapters; | ||||
|     } | ||||
|  | @ -69,14 +98,70 @@ public class BookUtil { | |||
|     private long position; | ||||
|     private Novel mNovel; | ||||
| 
 | ||||
|     private Chapter mChapter; | ||||
| 
 | ||||
|     public Chapter getChapter() { | ||||
|         return mChapter; | ||||
|     public void setNovel(Novel novel) { | ||||
|         this.mNovel = novel; | ||||
|     } | ||||
| 
 | ||||
|     public void setChapter(Chapter chapter) { | ||||
|         this.mChapter = chapter; | ||||
|     //当前目录网站列表 | ||||
|     private NovelSites mNovelSites; | ||||
|     //当前目录网站 | ||||
|     private Site mSite; | ||||
|     private SiteRule mSiteRule; | ||||
|     public void setNovelSites(NovelSites nvs) { | ||||
| 
 | ||||
|         this.mNovelSites = nvs; | ||||
|         if(nvs.getSites().length ==0){ | ||||
|             return; | ||||
|         } | ||||
|         mSite =nvs.getSites()[0]; | ||||
|         if(nvs.getSites().length > 0) | ||||
|         for (Site site:nvs.getSites() ) { | ||||
|             if(site.getSelectedByDefault()){ | ||||
|                 mSite = site; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         File file = new File(getChapterPath() +mSite.getDomain()); | ||||
|         if(!file.exists()){ | ||||
|             file.mkdir(); | ||||
|         } | ||||
| 
 | ||||
|         getSiteRule(); | ||||
|     } | ||||
| 
 | ||||
|     private void getSiteRule() { | ||||
|         mSiteRule = null; | ||||
|         BookSubscribe.getSiteRule(mSite.getDomain(),new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() { | ||||
|             @Override | ||||
|             public void onSuccess(String result) { | ||||
|                 //成功 | ||||
|                 SiteRule sr = (SiteRule)gson.fromJson(result,SiteRule.class); | ||||
| 
 | ||||
|                 List<SiteRule> srs = LitePal.where("domain=?",sr.getDomain()).limit(1).find(SiteRule.class); | ||||
|                long id = srs.size()==1 ?srs.get(0).getId() :0; | ||||
|                 if(id>0 ){ | ||||
|                     sr.update(id); | ||||
|                  //   mSiteRule =LitePal.find(SiteRule.class,id); | ||||
|                 }else | ||||
|                 { | ||||
|                     sr.save(); | ||||
|                 } | ||||
|                 mSiteRule =sr; | ||||
| 
 | ||||
|                readChaptersAsync(); | ||||
| 
 | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onFault(String errorMsg) { | ||||
|                 //失败 | ||||
| 
 | ||||
|             } | ||||
|         },mContext)); | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public void setChapterNo(int chapterNo) { | ||||
|  | @ -99,6 +184,26 @@ public class BookUtil { | |||
|         checkAndCreateDir(chapterPath); | ||||
|         checkAndCreateDir(cachedPath); | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     enum MuluStatus{ | ||||
|         isDownloading, | ||||
|         isDone, | ||||
|         failed | ||||
|     } | ||||
|     private void showProgressDialog() { | ||||
|         if (  null == progressDialog) { | ||||
|             progressDialog =new ProgressDialog(mContext); | ||||
|         } | ||||
|         progressDialog.show(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     private void dismissProgressDialog() { | ||||
|         if ( null != progressDialog) { | ||||
|             progressDialog.dismiss(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void checkAndCreateDir(String path){ | ||||
|  | @ -108,7 +213,7 @@ public class BookUtil { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public synchronized void openBook(Novel novel) throws IOException { | ||||
|     public synchronized void openBook(Novel novel) throws IOException, InterruptedException { | ||||
|         this.mNovel = novel; | ||||
|         //如果当前缓存不是要打开的书本就缓存书本同时删除缓存 | ||||
| 
 | ||||
|  | @ -118,8 +223,6 @@ public class BookUtil { | |||
|         boolean isOnShelf = isLocalImport || novel.isOnShelf(); | ||||
|         boolean isLoadChaptsFromRemote = !isLocalImport ;// && !novel.isFinished() ; //是否从目标网站下载目录 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         if(isLocalImport) { | ||||
| 
 | ||||
|             mChapters = LitePal.where("novelId=?", mNovel.getId() + "").find(Chapter.class); | ||||
|  | @ -129,7 +232,7 @@ public class BookUtil { | |||
|             } | ||||
| 
 | ||||
|             chaptCache = new HashMap<Integer, Cache>(); | ||||
|             if (mChapters.isEmpty()) {  //1. 首次打开 本地导入的书 2. 首次打开 未缓存的在线小说 | ||||
|             if (mChapters.isEmpty()) {  //1. 首次打开 本地导入的书 | ||||
| 
 | ||||
|                 if (bookPath == null || !bookPath.equals(mNovel.getNovelPath())) { | ||||
|                     cleanCacheFile(); | ||||
|  | @ -138,11 +241,136 @@ public class BookUtil { | |||
|                     cacheBook(); | ||||
|                 } | ||||
|             } | ||||
|         }else{ //读取目录列表 | ||||
|             MuluStatus m = mMuluStatus; | ||||
|             Log.d(TAG,String.format("mulu on Site %s download status %s",mSite.getDomain(),mMuluStatus)); | ||||
| 
 | ||||
|             while(mMuluStatus == MuluStatus.isDownloading){ | ||||
|                 Thread.sleep(50); | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|    // String getMuluUrl() { | ||||
|    //  return  "https://www.qu.la/book/390/"; | ||||
|   //  } | ||||
|    /* void readChapters(  String url){ | ||||
|         Request request = getTagRequest(url); | ||||
| 
 | ||||
|         ResponseBody body =null; | ||||
|         try { | ||||
| 
 | ||||
|             long startTime= new Date().getTime(); | ||||
|             Log.d(TAG,String.format("loadChaptContent----start download %s  目录 from %s",  mNovel.getName()  ,url )); | ||||
| 
 | ||||
| 
 | ||||
|             Response response = HttpMethods.getOkClient().newCall(request).execute(); | ||||
|             Log.d(TAG,String.format("loadChaptContent----end download %s  目录, 目录数量 %s, cost %s",  mNovel.getName()  , mChapters.size(),   new Date().getTime() -startTime )); | ||||
|             startTime= new Date().getTime(); | ||||
|             body = response.body(); | ||||
|             String bodyStr = body.string(); | ||||
|             Log.d(TAG, "onResponse: " +bodyStr); | ||||
| 
 | ||||
|             buildCharacters(bodyStr,url); | ||||
|             Log.d(TAG,String.format("loadChaptContent----end build %s  目录, 目录数量 %s, cost %s",  mNovel.getName()  , mChapters.size(),   new Date().getTime() -startTime )); | ||||
| 
 | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|         }finally { | ||||
|             if(body!=null){ | ||||
|                 body.close();; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     }*/ | ||||
| 
 | ||||
|     void readChaptersAsync( ) { | ||||
|         String url = mSite.getMuluUrl(); | ||||
|         Request request = getTagRequest(url); | ||||
|         mMuluStatus = MuluStatus.isDownloading; | ||||
|         long startTime= new Date().getTime(); | ||||
|         Log.d(TAG,String.format("loadChaptContent----start download %s  目录 from %s",  mNovel.getName()  ,url )); | ||||
| 
 | ||||
| 
 | ||||
|         HttpMethods.getOkClient().newCall(request).enqueue(new Callback() { | ||||
|             @Override | ||||
|             public void onFailure(Call call, IOException e) { | ||||
|                 Log.d(TAG, "onFailure: " + e.getMessage()); | ||||
|                 if( mNovelSites.getSites().length ==1){ | ||||
|                     mMuluStatus = MuluStatus.failed; | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 //try next site | ||||
|                for(Site st :  mNovelSites.getSites() ){ | ||||
|                    if(!st.getDomain().equals(mSite.getDomain())){ | ||||
|                        mSite =st; | ||||
|                        break; | ||||
|                    } | ||||
|                } | ||||
|               //  readChaptersAsync(); | ||||
|                 getSiteRule(); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onResponse(Call call, Response response){ | ||||
|                 ResponseBody body = response.body(); | ||||
|                 if (body != null) { | ||||
| 
 | ||||
|                     try { | ||||
|                         String bodyStr = body.string(); | ||||
|                         Log.d(TAG, "onResponse: " +bodyStr); | ||||
|                         Log.d(TAG,String.format("loadChaptContent----end download %s  目录, 目录数量 %s, cost %s",  mNovel.getName()  , mChapters.size(),   new Date().getTime() -startTime )); | ||||
|                         long startTime2= new Date().getTime(); | ||||
|                         buildCharacters(bodyStr,url); | ||||
|                         Log.d(TAG,String.format("loadChaptContent----end download %s  目录, 目录数量 %s, cost %s",  mNovel.getName()  , mChapters.size(),   new Date().getTime() -startTime2 )); | ||||
|                         mMuluStatus = MuluStatus.isDone; | ||||
| 
 | ||||
| 
 | ||||
|                     } catch (IOException e) { | ||||
|                         e.printStackTrace(); | ||||
|                     }finally { | ||||
|                         body.close(); | ||||
|                     } | ||||
| 
 | ||||
|                 } | ||||
| 
 | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|     void buildCharacters( String content ,String url){ | ||||
| 
 | ||||
|         try { | ||||
|             JSONObject siteJson = new JSONObject(); | ||||
| 
 | ||||
|             siteJson.put("chapterUrlPattern", mSiteRule.getChapterUrlPattern()); | ||||
|             siteJson.put("chapterUrlRegexOnMulu", mSiteRule.getChapterUrlRegexOnMulu());//示例接口表达式有问题 | ||||
|             siteJson.put("chapterUrlRegexOnMulu", "<dd> <a[^>]*href=\"(/book/[\\d]+/[\\d]+\\.html)\">([^<]+)</a></dd>"); | ||||
| 
 | ||||
|             mChapters = NovelParseUtil.getChapters(mSite.getDomain(),url, content, siteJson); | ||||
|             Log.d(TAG,String.format("mulu on Site %s download status %s",mSite.getDomain(),mMuluStatus)); | ||||
|         /*    if (mChapters != null) { | ||||
|                 int lastReadChapt = mNovel.getLastReadChapt(); | ||||
|                 //   int index =lastReadChapt*2-2; | ||||
| 
 | ||||
|                 lastReadChapt = lastReadChapt >=mChapters.size() ? mChapters.size() -1:lastReadChapt; | ||||
|                 lastReadChapt = lastReadChapt <=0 ? 1:lastReadChapt; | ||||
|                 mCurrentChapter =mChapters.get(lastReadChapt-1); | ||||
| 
 | ||||
|             }*/ | ||||
|         } catch (JSONException e) { | ||||
|             // } catch (JSONException | IOException e) { | ||||
|             Log.d(TAG,String.format("mulu on Site %s download status %s",mSite.getDomain(),mMuluStatus)); | ||||
|             e.printStackTrace(); | ||||
|         } finally { | ||||
|             //   result.close(); | ||||
|             //   if (result2 != null) result2.close(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     private void cleanCacheFile(){ | ||||
| 
 | ||||
| 
 | ||||
|  | @ -464,7 +692,7 @@ public class BookUtil { | |||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public List<Chapter> getDirectoryList(){ | ||||
|     public List<Chapter> getmChapters(){ | ||||
|         return mChapters; | ||||
|     } | ||||
| 
 | ||||
|  | @ -473,14 +701,21 @@ public class BookUtil { | |||
|     } | ||||
| 
 | ||||
|     protected String fileName(int index) { | ||||
|         return cachedPath + bookName + index ; | ||||
|         return cachedPath + mNovel.getName() + index ; | ||||
|     } | ||||
|     protected String fileChapterName(int chaptId ) { | ||||
|         if(mSite!=null){ | ||||
| 
 | ||||
|             return  getChapterPath() +mSite.getDomain()+"/"+ chaptId ; | ||||
|         } | ||||
|         return   getChapterPath() + chaptId ; | ||||
|     } | ||||
| 
 | ||||
|     String getChapterPath(){ | ||||
|          File file = new File(chapterPath +mNovel.getId()); | ||||
|          if(!file.exists()){ | ||||
|              file.mkdir(); | ||||
|          } | ||||
|         return  chapterPath +mNovel.getId()+"/"; | ||||
|     } | ||||
| 
 | ||||
|  | @ -517,6 +752,28 @@ public class BookUtil { | |||
|         return block; | ||||
|     } | ||||
| 
 | ||||
|     boolean isDownloadChapt =false; | ||||
| 
 | ||||
|     void setDownloadFlag(boolean flag){ | ||||
|         isDownloadChapt = flag; | ||||
|     } | ||||
| 
 | ||||
|     Handler handler = new Handler() { | ||||
|         @Override | ||||
|         public void handleMessage(Message msg) { | ||||
| 
 | ||||
|             int wt = msg.what; | ||||
| 
 | ||||
|             if (msg.what == 123) { | ||||
|                 isDownloadChapt =true; | ||||
|             }else if(msg.what==1){ | ||||
| 
 | ||||
|                 Toast.makeText(mContext,"网络错误",Toast.LENGTH_LONG).show(); | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     private Map<Integer,Cache> chaptCache = new HashMap<Integer,Cache>(); | ||||
| 
 | ||||
|     //获取chapter 缓存 | ||||
|  | @ -526,39 +783,37 @@ public class BookUtil { | |||
|             block = chaptCache .get(index).getData().get(); | ||||
|         } | ||||
|         if (block == null) { | ||||
|      //       cleanCacheFile(); //to remove | ||||
|             try { | ||||
|                 File file = new File(fileChapterName(index)); | ||||
| 
 | ||||
|                 if(!file.exists()) { | ||||
|                     /* 章节内容没有缓存在本地 | ||||
|                         1. 根据本地的章节网络地址信息,读取章节内容到本地,若读取失败则 | ||||
|                         2. 查询主服务器,若有地址更新则更新本地信息,并重复1,若没有更新地址,则地址无效,返回章节内容正待手打 | ||||
|                     */ | ||||
| 
 | ||||
|                     Chapter chapter = mChapters.get(index); | ||||
|                     String url = chapter.getChapterUrl(); | ||||
|                     Log.d(TAG,String.format("loadChaptContent----start %s"  ,new Date().toString() )); | ||||
| 
 | ||||
|                     JSONObject siteJson = new JSONObject(); | ||||
|                     siteJson.put("chapterContentRegex", "<div id=\"content\">([\\s\\S]+?)</div>"); | ||||
|                     siteJson.put("chapterContentDumpRegex", "<script>chaptererror();</script>"); | ||||
|                     Request request = new Request.Builder() | ||||
|                             .url(url) | ||||
|                             // .header("User-Agent", "OkHttp Example") | ||||
|                             .build(); | ||||
|                     Response response = HttpMethods.getOkClient().newCall(request).execute(); | ||||
|                     String content = NovelParseUtil.getChapterContent(response.body().string(), siteJson); | ||||
|                     loadChaptContent(index); | ||||
| 
 | ||||
|                     char[] buf = content.toCharArray(); | ||||
|                     try { | ||||
|                         file.createNewFile(); | ||||
| 
 | ||||
|                         final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(index)), "UTF-16LE"); // UTF-16LE 比 utf-8 文件小 | ||||
|                         writer.write(buf); | ||||
|                         writer.close(); | ||||
|                     } catch (IOException e) { | ||||
|                         throw new RuntimeException("Error during writing " + fileName(index)); | ||||
|                      showProgressDialog();//why not show | ||||
|                     int slepttime =0; | ||||
|                     while(!isDownloadChapt){ | ||||
|                         Thread.sleep(50); | ||||
|                         slepttime+=50; | ||||
|                     } | ||||
|                     dismissProgressDialog(); | ||||
|                     Log.d(TAG,String.format("loadChaptContent slept %s for downloading %s ",slepttime,  mChapters.get(index -1).getChapterName()   )); | ||||
|                 } | ||||
| 
 | ||||
|                 if(!file.exists()) { | ||||
|                      String error = "网络错误"; | ||||
|                      return  error.toCharArray(); | ||||
|                 } | ||||
|                 if(mChapters.size() > index ) { | ||||
| 
 | ||||
|                     File file2 = new File(fileChapterName(index+1)); | ||||
| 
 | ||||
|                     if(!file2.exists()) { | ||||
|                         loadChaptContent(index + 1); | ||||
|                     } | ||||
| 
 | ||||
|                 } | ||||
| 
 | ||||
|  | @ -583,6 +838,8 @@ public class BookUtil { | |||
|                 throw new RuntimeException("Error during reading " + fileChapterName(index)); | ||||
|             } catch (JSONException e) { | ||||
|                 e.printStackTrace(); | ||||
|             } catch (InterruptedException e) { | ||||
|                 e.printStackTrace(); | ||||
|             } | ||||
|             Cache cache = new Cache(); | ||||
|             cache.setSize(block.length); | ||||
|  | @ -592,7 +849,96 @@ public class BookUtil { | |||
|         } | ||||
|         return block; | ||||
|     } | ||||
| 
 | ||||
| private void loadChaptContent(int index) throws JSONException, InterruptedException { | ||||
|          /* 章节内容没有缓存在本地 | ||||
|                         1. 根据本地的章节网络地址信息,读取章节内容到本地,若读取失败则 | ||||
|                         2. 查询主服务器,若有地址更新则更新本地信息,并重复1,若没有更新地址,则地址无效,返回章节内容正待手打 | ||||
|                     */ | ||||
|     // | ||||
|     if(mChapters ==null || mChapters.size() ==0){ | ||||
|         return; | ||||
|     } | ||||
|     Chapter chapter = mChapters.get(index -1); | ||||
|     String url = chapter.getChapterUrl(); | ||||
|     if( TextUtils.isEmpty( url)){ | ||||
|         return ; | ||||
|     } | ||||
|     long startTime= new Date().getTime(); | ||||
|     Log.d(TAG,String.format("loadChaptContent----start download %s from %s",   chapter.getChapterName()  ,url )); | ||||
| 
 | ||||
|     setDownloadFlag(false); | ||||
| 
 | ||||
|     JSONObject siteJson = new JSONObject(); | ||||
|     siteJson.put("chapterContentRegex", mSiteRule.getChapterContentRegex()); | ||||
|     siteJson.put("chapterContentDumpRegex", mSiteRule.getChapterContentDumpRegex()); | ||||
|     Request request = getTagRequest(url); | ||||
|     HttpMethods.getOkClient().newCall(request).enqueue(new Callback() { | ||||
|         @Override | ||||
|         public void onFailure(Call call, IOException e) { | ||||
|             handler.sendEmptyMessage(123); | ||||
|             setDownloadFlag(true); | ||||
|             Log.d(TAG, "loadChaptContent---- onFailure: " + e.getMessage()); | ||||
|             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){ | ||||
| 
 | ||||
|                     setDownloadFlag(true); | ||||
|                    handler.sendEmptyMessage(1); | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 try { | ||||
|                     String bodyStr = body.string(); | ||||
|                     String title = chapter.getChapterName(); | ||||
|                     String chapterContent = title+ "\n" + NovelParseUtil.getChapterContent(bodyStr, siteJson); | ||||
|                     char[] buf = chapterContent.toCharArray(); | ||||
|                     File file = new File(fileChapterName(index)); | ||||
|                     file.createNewFile(); | ||||
| 
 | ||||
|                     final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(index)), charachterType);//"UTF-16LE"); // UTF-16LE 比 utf-8 文件小 | ||||
|                     writer.write(buf); | ||||
|                     writer.close(); | ||||
|                 } catch (IOException | JSONException e) { | ||||
|                     e.printStackTrace(); | ||||
|                     throw new RuntimeException("Error during writing " + fileChapterName( index)); | ||||
|                 } | ||||
|                 finally { | ||||
|                     body.close(); | ||||
| 
 | ||||
|                     handler.sendEmptyMessage(123); | ||||
|                     setDownloadFlag(true); | ||||
|                 } | ||||
|                 chapter.setNovelId(mNovel.getId()); | ||||
|                 chapter.setChapterPath(fileChapterName(index)); | ||||
|                 chapter.save(); | ||||
| 
 | ||||
|                Log.d(TAG,String.format("loadChaptContent---- finished download %s, cost time %s ,content path %s ",  chapter.getChapterName(),  new Date().getTime() -startTime ,chapter.getChapterPath()   )); | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|     private Request getTagRequest(String url) { | ||||
|         return new  Request.Builder() | ||||
|                 .tag(mNovel.getNovelId()) //标记 请求的tag,切换小说或离开小说界面(BookActivity) 时 取消未执行完毕的 此tag的所有请求 | ||||
|                 .url(url) | ||||
|                 // .header("User-Agent", "OkHttp Example") | ||||
|                 .build(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public boolean isChapterTitle(String line){ | ||||
|         return (line.length() <= 30 && (line.matches(".*第.{1,8}章.*") || line.matches(".*第.{1,8}节.*")))  ; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,30 @@ | |||
| package com.novelbook.android.utils; | ||||
| 
 | ||||
| import com.novelbook.android.db.Novel; | ||||
| 
 | ||||
| import org.json.JSONException; | ||||
| import org.json.JSONObject; | ||||
| 
 | ||||
| public class GsonUtil { | ||||
| 
 | ||||
|     public static Novel getNovel(String json){ | ||||
|         Novel nv = new Novel(); | ||||
|         try { | ||||
|             JSONObject jsonObject = new JSONObject(json); | ||||
|             nv.setNovelId(jsonObject.getString("novelId")); | ||||
|             nv.setLastUpateTime(jsonObject.getLong("lastUpateTime")); | ||||
|             nv.setAuthor(jsonObject.getString("author")); | ||||
|             nv.setName(jsonObject.getString("name")); | ||||
|             nv.setCover(jsonObject.getString("cover")); | ||||
|             nv.setNovelType(jsonObject.getString("novelType")); | ||||
|             nv.setNovelType2(jsonObject.getString("novelType2")); | ||||
|             nv.setLastestChapterName(jsonObject.getString("lastestChapterName")); | ||||
| 
 | ||||
|             return  nv; | ||||
| 
 | ||||
|         } catch (JSONException e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|         return  nv; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,22 @@ | |||
| package com.novelbook.android.utils; | ||||
| 
 | ||||
| import com.novelbook.android.bean.NovelSites; | ||||
| import com.novelbook.android.db.SiteRule; | ||||
| import com.novelbook.android.db.Chapter; | ||||
| import com.novelbook.android.db.Novel; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| public class NovelConstants { | ||||
|     public static Novel CURRENT_NOVEL; | ||||
|     public static NovelSites CURRENT_NOVEL_SITES; | ||||
|     public static List<Chapter> CURRENT_CHPATERS; | ||||
|     public static Map<String, SiteRule> SiteRules= new FIFOMap<String, SiteRule>(100);; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -1,16 +1,55 @@ | |||
| package com.novelbook.android.utils; | ||||
| 
 | ||||
| import com.novelbook.android.db.Chapter; | ||||
| 
 | ||||
| import org.json.JSONException; | ||||
| import org.json.JSONObject; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.LinkedHashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| public class NovelParseUtil { | ||||
| 
 | ||||
|     private static final String A_Regex = "<a[^>]+href[\\s]*=[\\s]*['\"]?([^'\"]+)['\"\\s]?[^>]*>([^<]+)<"; | ||||
|     public static String[] getChapters(String muluUrl, String html, JSONObject siteJson) throws JSONException { | ||||
|     public static String[] getChaptersArray(String muluUrl, String html, JSONObject siteJson) throws JSONException { | ||||
| 
 | ||||
|         Map<String, String> muluMap = getChaptersMap(muluUrl,   html,   siteJson); | ||||
| 
 | ||||
| 
 | ||||
|         String[] values = new String[muluMap.size() * 2]; | ||||
| 
 | ||||
|         Set<Map.Entry<String, String>> es = muluMap.entrySet(); | ||||
|         int pos = values.length - 2; | ||||
|         for (Map.Entry<String, String> e : es) { | ||||
|             values[pos] = e.getKey(); | ||||
|             values[pos + 1] = e.getValue(); | ||||
|             pos -= 2; | ||||
|         } | ||||
|         return values; | ||||
|     } | ||||
|     public static List<Chapter>  getChapters(String domain,String muluUrl, String html, JSONObject siteJson) throws JSONException { | ||||
| 
 | ||||
|         Map<String, String> muluMap = getChaptersMap(muluUrl,   html,   siteJson); | ||||
|         Chapter[] tmp = new Chapter[muluMap.size()]; | ||||
| 
 | ||||
| 
 | ||||
|         Set<Map.Entry<String, String>> es = muluMap.entrySet(); | ||||
|         int pos = tmp.length - 1; | ||||
|         for (Map.Entry<String, String> e : es) { | ||||
|             Chapter chapter = new Chapter(); | ||||
|             chapter.setChapterUrl( e.getKey()); | ||||
|             chapter.setChapterName( e.getValue()); | ||||
|             chapter.setDomain(domain); | ||||
|            tmp[pos--] =chapter; | ||||
|         } | ||||
|         List<Chapter> values = new ArrayList<Chapter>(Arrays.asList(tmp)); | ||||
|         return values; | ||||
|     } | ||||
|     public static Map<String, String> getChaptersMap(String muluUrl, String html, JSONObject siteJson) throws JSONException { | ||||
|         String chapterUrlRegexOnMulu = siteJson.getString("chapterUrlRegexOnMulu"); | ||||
|         String chapterUrlPattern = siteJson.getString("chapterUrlPattern"); | ||||
| 
 | ||||
|  | @ -34,16 +73,8 @@ public class NovelParseUtil { | |||
|             muluMap.put(href, name); | ||||
|         } | ||||
| 
 | ||||
|         String[] values = new String[muluMap.size() * 2]; | ||||
|         return  muluMap; | ||||
| 
 | ||||
|         Set<Map.Entry<String, String>> es = muluMap.entrySet(); | ||||
|         int pos = values.length - 2; | ||||
|         for (Map.Entry<String, String> e : es) { | ||||
|             values[pos] = e.getKey(); | ||||
|             values[pos + 1] = e.getValue(); | ||||
|             pos -= 2; | ||||
|         } | ||||
|         return values; | ||||
|     } | ||||
| 
 | ||||
|     public static String getChapterContent(String html, JSONObject siteJson) throws JSONException  { | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ import android.graphics.RectF; | |||
| import android.graphics.Region; | ||||
| import android.graphics.Typeface; | ||||
| import android.os.AsyncTask; | ||||
| import android.text.TextUtils; | ||||
| import android.util.DisplayMetrics; | ||||
| import android.util.Log; | ||||
| import android.view.WindowManager; | ||||
|  | @ -20,8 +21,10 @@ import android.widget.Toast; | |||
| 
 | ||||
| import com.novelbook.android.Config; | ||||
| import com.novelbook.android.R; | ||||
| import com.novelbook.android.bean.NovelSites; | ||||
| import com.novelbook.android.db.Chapter; | ||||
| import com.novelbook.android.db.Novel; | ||||
| import com.novelbook.android.netutils.NetUtil; | ||||
| import com.novelbook.android.view.PageWidget; | ||||
| 
 | ||||
| import org.litepal.LitePal; | ||||
|  | @ -139,8 +142,12 @@ public class PageFactory { | |||
|     private Novel mBook; | ||||
|     //书的目录列表 | ||||
|     private List<Chapter> mChapters; | ||||
|     //当前章节 | ||||
|    // private Chapter  mCurrentChapter; | ||||
|     //书本章节 | ||||
|     private int currentChapter = 0; | ||||
| 
 | ||||
| 
 | ||||
|     //当前电量 | ||||
|     private int level = 0; | ||||
|     private BookUtil mBookUtil; | ||||
|  | @ -218,7 +225,7 @@ public class PageFactory { | |||
|     } | ||||
| 
 | ||||
|     private PageFactory(Context context) { | ||||
|         mBookUtil = new BookUtil(); | ||||
|        // mBookUtil = new BookUtil(); | ||||
|         mContext = context.getApplicationContext(); | ||||
|         config = Config.getInstance(); | ||||
|         //获取屏幕宽高 | ||||
|  | @ -343,7 +350,7 @@ public class PageFactory { | |||
|     } | ||||
| 
 | ||||
|     public void onDraw(Bitmap bitmap,List<String> m_lines,Boolean updateChapter) { | ||||
|         if (getDirectoryList().size() > 0 && updateChapter) { | ||||
|         if (getChapters().size() > 0 && updateChapter) { | ||||
|             currentChapter = getCurrentCharter(); | ||||
|         } | ||||
|         //更新数据库进度 | ||||
|  | @ -352,11 +359,11 @@ public class PageFactory { | |||
|                 @Override | ||||
|                 public void run() { | ||||
|                     super.run(); | ||||
|                     values.put("begin",currentPage.getBegin()); | ||||
|                     values.put("biginChapt",currentChapter); | ||||
|                    Log.d(TAG,String.format("begin to update book %s chapter%s bigin %s ",mBook.getNovelName(),currentChapter, currentPage.getBegin() ) ); | ||||
|                     values.put("lastReadPos",currentPage.getBegin()); | ||||
|                     values.put("lastReadChapt",currentChapter); | ||||
|                    Log.d(TAG,String.format("begin to update book %s chapter%s bigin %s ",mBook.getName(),currentChapter, currentPage.getBegin() ) ); | ||||
|                   int rows =  LitePal.update(Novel.class,values,mBook.getId()); | ||||
|                    Log.d(TAG,String.format("update book %s chapter%s bigin %s, result %s",mBook.getNovelName(),currentChapter, currentPage.getBegin(),rows) ); | ||||
|                    Log.d(TAG,String.format("update book %s chapter%s bigin %s, result %s",mBook.getName(),currentChapter, currentPage.getBegin(),rows) ); | ||||
|         } | ||||
|     }.start(); | ||||
|         } | ||||
|  | @ -439,12 +446,17 @@ public class PageFactory { | |||
|         //画书名 | ||||
|         c.drawText(CommonUtil.subString(bookName,12), marginWidth ,statusMarginBottom + mBatterryFontSize, mBatterryPaint); | ||||
|         //画章 | ||||
|         if (getDirectoryList().size() > 0) { | ||||
|             String charterName = CommonUtil.subString(getDirectoryList().get(currentChapter-1).getChapterName(),16); | ||||
|             int nChaterWidth = (int) mBatterryPaint.measureText(charterName) + 1; | ||||
|             c.drawText(charterName, mWidth - marginWidth - nChaterWidth, statusMarginBottom  + mBatterryFontSize, mBatterryPaint); | ||||
|         } | ||||
|        /* String chapterName =""; | ||||
|         if(mCurrentChapter!=null){ | ||||
|             chapterName = mCurrentChapter.getChapterName(); | ||||
|         }else*/ | ||||
|        if (getChapters().size() > 0) | ||||
|         { | ||||
|             String  chapterName = CommonUtil.subString(getChapters().get(currentChapter-1).getChapterName(),16); | ||||
|             int nChaterWidth = (int) mBatterryPaint.measureText(chapterName) + 1; | ||||
|             c.drawText(chapterName, mWidth - marginWidth - nChaterWidth, statusMarginBottom  + mBatterryFontSize, mBatterryPaint); | ||||
| 
 | ||||
|         } | ||||
|                mBookPageWidget.postInvalidate(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -473,7 +485,7 @@ public class PageFactory { | |||
|         if (currentPage.getEnd() >= mBookUtil.getBookLen()) { | ||||
|            Log.d(TAG,"已经是本章最后一页了"); | ||||
| 
 | ||||
|             m_islastPage =currentChapter == mBookUtil.getDirectoryList().size(); | ||||
|             m_islastPage =currentChapter == mBookUtil.getChapters().size(); | ||||
|             if ( m_islastPage){ | ||||
|                 Toast.makeText(mContext, "已经是最后一页了", Toast.LENGTH_SHORT).show(); | ||||
|                 return; | ||||
|  | @ -496,29 +508,51 @@ public class PageFactory { | |||
|         currentPage = cancelPage; | ||||
|     } | ||||
| 
 | ||||
|     public void prepareBook(Novel book,NovelSites nvs,Context context){ | ||||
|         if(mBook!=null &&mBook.getNovelId() !=book.getNovelId()){ //取消未上本书完成的web请求,待验证效果 | ||||
|             NetUtil.cancelRequest(mBook.getNovelId()); | ||||
|         } | ||||
|         mBookUtil = new BookUtil(); | ||||
|         this.mBookUtil.setContext(context); | ||||
|         this.mBookUtil.setNovel(book); | ||||
|         this.mBookUtil.setNovelSites(nvs); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 打开书本 | ||||
|      * @throws IOException | ||||
|      */ | ||||
|     public void openBook(Novel book , List<Chapter> chapters ) throws IOException { | ||||
|     public void openBook(Novel book ,Context context) throws IOException { | ||||
|         if(null ==mBookUtil || !TextUtils.isEmpty(book.getNovelPath())  ){ //离线书籍重新初始化加载mBookUtil | ||||
|             mBookUtil = new BookUtil(); | ||||
|             mBookUtil.setContext(context); | ||||
|         } | ||||
|         //清空数据 | ||||
|         currentChapter = 0; | ||||
| //        m_mbBufLen = 0; | ||||
|         initBg(config.getDayOrNight()); | ||||
| 
 | ||||
|         if(mBook!=null &&mBook.getNovelId() !=book.getNovelId()){ //取消未上本书完成的web请求 | ||||
|            NetUtil.cancelRequest(mBook.getNovelId()); | ||||
|         } | ||||
| 
 | ||||
|         this.mBook = book ; | ||||
|         bookPath = mBook.getNovelPath(); | ||||
|         bookName =mBook.getNovelName();// FileUtils.getFileName(bookPath); | ||||
|         this.mChapters = chapters; | ||||
|         bookName =mBook.getName();// FileUtils.getFileName(bookPath); | ||||
|       //  this.mCurrentChapter = chapter; | ||||
|         mStatus = Status.OPENING; | ||||
|         drawStatus(mBookPageWidget.getCurPage()); | ||||
|         drawStatus(mBookPageWidget.getNextPage()); | ||||
|         if (bookTask != null && bookTask.getStatus() != AsyncTask.Status.FINISHED){ | ||||
|             bookTask.cancel(true); | ||||
|         } | ||||
| 
 | ||||
|         bookTask = new BookTask(); | ||||
| 
 | ||||
|         bookTask.execute(book.getLastReadChapt(),book .getLastReadPos()); | ||||
|         bookTask.execute((long)book.getLastReadChapt(),book .getLastReadPos()); | ||||
|     } | ||||
| 
 | ||||
|     private class BookTask extends AsyncTask<Long,Void,Boolean>{ | ||||
|  | @ -535,9 +569,6 @@ public class PageFactory { | |||
|                 PageFactory.mStatus = PageFactory.Status.FINISH; | ||||
| //                m_mbBufLen = mBookUtil.getBookLen(); | ||||
|                 mBookUtil.setChapterNo((int)chapter); | ||||
|                 if(mChapters!=null) { | ||||
|                     mBookUtil.setChapters(mChapters); | ||||
|                 } | ||||
|                 currentChaptPages = loadCurrentChapt((int)chapter); | ||||
|                 currentPage = getPageForBegin(begin) ;// currentChaptPages.get(0); | ||||
|               //  currentPage = getPageForBegin(begin); | ||||
|  | @ -805,7 +836,7 @@ public class PageFactory { | |||
| 
 | ||||
|     //上一章 | ||||
|     public void preChapter(){ | ||||
|         if (mBookUtil.getDirectoryList().size() > 0){ | ||||
|         if (mBookUtil.getChapters().size() > 0){ | ||||
|             int num = currentChapter; | ||||
|             if (num ==1){ | ||||
|                 num =getCurrentCharter(); | ||||
|  | @ -831,7 +862,7 @@ public class PageFactory { | |||
|             num =getCurrentCharter(); | ||||
|         } | ||||
|         num ++; | ||||
|         if (num <= getDirectoryList().size()){ | ||||
|         if (num <= getChapters().size()){ | ||||
| 
 | ||||
|             preChaptPages =currentChaptPages; | ||||
|             currentChapter = num; | ||||
|  | @ -1032,13 +1063,19 @@ public class PageFactory { | |||
|     } | ||||
| 
 | ||||
|     //获取书本的章 | ||||
|     public List<Chapter> getDirectoryList(){ | ||||
|         return mBookUtil.getDirectoryList(); | ||||
|     public List<Chapter> getChapters(){ | ||||
|         return mBookUtil.getChapters(); | ||||
|     } | ||||
| 
 | ||||
|     public String getBookPath(){ | ||||
|         return bookPath; | ||||
|     } | ||||
|     public String getBookName(){ | ||||
|         return mBook.getName(); | ||||
|     } | ||||
|     public Novel getNovle(){ | ||||
|         return mBook; | ||||
|     } | ||||
|     //是否是第一页 | ||||
|     public boolean isfirstPage() { | ||||
|         return m_isfirstPage; | ||||
|  |  | |||
|  | @ -152,6 +152,7 @@ | |||
|         > | ||||
| 
 | ||||
|         <Button | ||||
|             android:id="@+id/btnShelf" | ||||
|             android:text="加入书架" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|  |  | |||
|  | @ -87,6 +87,7 @@ | |||
|                     /> | ||||
| 
 | ||||
|                 <TextView | ||||
| 
 | ||||
|                     style="@style/TextViewTitle" | ||||
|                     android:layout_width="wrap_content" | ||||
|                     android:layout_height="wrap_content" | ||||
|  | @ -95,6 +96,7 @@ | |||
|             </LinearLayout> | ||||
| 
 | ||||
|             <TextView | ||||
|                 android:id="@+id/txtDesc2" | ||||
|                 style="@style/TextViewDesc" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|  | @ -164,6 +166,7 @@ | |||
|                     android:orientation="vertical"> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:id="@+id/txtLatestCate" | ||||
|                         style="@style/TextViewDesc" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="wrap_content" | ||||
|  | @ -171,16 +174,8 @@ | |||
| 
 | ||||
|                         /> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         style="@style/TextViewDesc" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:text="第一万两千八百章 天冷好个秋" /> | ||||
|                     <TextView | ||||
|                         style="@style/TextViewDesc" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:text="第一万两千八百零一章 天冷好个秋2" /> | ||||
| 
 | ||||
| 
 | ||||
|                 </LinearLayout> | ||||
| 
 | ||||
|                 <TextView | ||||
|  |  | |||
|  | @ -200,7 +200,7 @@ | |||
| 
 | ||||
|     <style name="TextViewHead.bold"> | ||||
|         <item name="android:textStyle">bold</item> | ||||
| 
 | ||||
|         <item name="android:textSize">18sp</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue