From 90af9bbce2ff88333cfd5d92686a88fb0c995321 Mon Sep 17 00:00:00 2001 From: mwang <8205347@qq.com> Date: Fri, 5 Apr 2019 23:59:31 +0800 Subject: [PATCH] try read book online --- zhuike/src/main/assets/litepal.xml | 8 +- .../com/novelbook/android/Activity_base.java | 2 +- .../android/Activity_createShudan.java | 4 +- .../com/novelbook/android/BookActivity.java | 366 +++++++-------- .../com/novelbook/android/FileActivity.java | 4 +- .../android/Fragments/BasicFragment.java | 6 +- .../android/Fragments/BookMarkFragment.java | 14 +- .../android/Fragments/CatalogFragment.java | 2 +- .../android/Fragments/Fragment_Shelf.java | 6 +- .../com/novelbook/android/MarkActivity.java | 4 +- .../com/novelbook/android/ReadActivity.java | 17 +- .../android/adapter/BookListAdapter.java | 2 +- .../android/adapter/MyPagerAdapter.java | 10 +- .../android/adapter/ShelfAdapter.java | 6 +- .../novelbook/android/bean/NovelSites.java | 22 + .../java/com/novelbook/android/bean/Site.java | 31 ++ .../com/novelbook/android/db/BookMarks.java | 10 +- .../com/novelbook/android/db/Chapter.java | 14 +- .../java/com/novelbook/android/db/Novel.java | 18 +- .../com/novelbook/android/db/SiteRule.java | 98 ++++ .../filechooser/DirectoryFragment.java | 15 +- .../com/novelbook/android/netapi/HttpApi.java | 13 +- .../android/netsubscribe/BookSubscribe.java | 9 +- .../android/netutils/HttpMethods.java | 2 +- .../novelbook/android/netutils/NetUtil.java | 14 + .../android/utils/BandanAdapter.java | 6 +- .../com/novelbook/android/utils/BookUtil.java | 424 ++++++++++++++++-- .../com/novelbook/android/utils/GsonUtil.java | 30 ++ .../android/utils/NovelConstants.java | 22 + .../android/utils/NovelParseUtil.java | 51 ++- .../novelbook/android/utils/PageFactory.java | 85 +++- zhuike/src/main/res/layout/activity_book.xml | 1 + zhuike/src/main/res/layout/content_book.xml | 15 +- zhuike/src/main/res/values/styles.xml | 2 +- 34 files changed, 961 insertions(+), 372 deletions(-) create mode 100644 zhuike/src/main/java/com/novelbook/android/bean/NovelSites.java create mode 100644 zhuike/src/main/java/com/novelbook/android/bean/Site.java create mode 100644 zhuike/src/main/java/com/novelbook/android/db/SiteRule.java create mode 100644 zhuike/src/main/java/com/novelbook/android/utils/GsonUtil.java create mode 100644 zhuike/src/main/java/com/novelbook/android/utils/NovelConstants.java diff --git a/zhuike/src/main/assets/litepal.xml b/zhuike/src/main/assets/litepal.xml index 46532e0..3e47a74 100644 --- a/zhuike/src/main/assets/litepal.xml +++ b/zhuike/src/main/assets/litepal.xml @@ -2,12 +2,12 @@ - + - - + + - + \ No newline at end of file diff --git a/zhuike/src/main/java/com/novelbook/android/Activity_base.java b/zhuike/src/main/java/com/novelbook/android/Activity_base.java index 3c246ca..3114c05 100644 --- a/zhuike/src/main/java/com/novelbook/android/Activity_base.java +++ b/zhuike/src/main/java/com/novelbook/android/Activity_base.java @@ -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); diff --git a/zhuike/src/main/java/com/novelbook/android/Activity_createShudan.java b/zhuike/src/main/java/com/novelbook/android/Activity_createShudan.java index 7e69b38..207e6f6 100644 --- a/zhuike/src/main/java/com/novelbook/android/Activity_createShudan.java +++ b/zhuike/src/main/java/com/novelbook/android/Activity_createShudan.java @@ -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()); diff --git a/zhuike/src/main/java/com/novelbook/android/BookActivity.java b/zhuike/src/main/java/com/novelbook/android/BookActivity.java index 15edf70..93a0167 100644 --- a/zhuike/src/main/java/com/novelbook/android/BookActivity.java +++ b/zhuike/src/main/java/com/novelbook/android/BookActivity.java @@ -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 mData;; - - private ArrayList mChapters = new ArrayList<>(); + private Gson gson = new Gson(); + private List 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() { - getBookInfo(); - // getMuluInfo(); + 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(); + } 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":"����","novelType2":"������½","name":"���Ʋ��","author":"�������","cover":"http:\/\/qidian.qpic.cn\/qdbimg\/349573\/1209977\/180","description":"","lastestChapterName":"�ڰ��� ��ʼ","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 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", "
]*href=\"(/book/[\\d]+/[\\d]+\\.html)\">([^<]+)
"); - 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", "
([\\s\\S]+?)
"); - siteJson.put("chapterContentDumpRegex", ""); - - - 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 mDatas = new ArrayList(); - private OnItemClickListener mOnItemClickListener; - private int listItemID; - public BookListAdapter(Context context,List 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 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); - - } - } - } - */ } diff --git a/zhuike/src/main/java/com/novelbook/android/FileActivity.java b/zhuike/src/main/java/com/novelbook/android/FileActivity.java index 8e769df..9a767dd 100644 --- a/zhuike/src/main/java/com/novelbook/android/FileActivity.java +++ b/zhuike/src/main/java/com/novelbook/android/FileActivity.java @@ -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; } diff --git a/zhuike/src/main/java/com/novelbook/android/Fragments/BasicFragment.java b/zhuike/src/main/java/com/novelbook/android/Fragments/BasicFragment.java index 6986d1c..d1a03bc 100644 --- a/zhuike/src/main/java/com/novelbook/android/Fragments/BasicFragment.java +++ b/zhuike/src/main/java/com/novelbook/android/Fragments/BasicFragment.java @@ -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){ diff --git a/zhuike/src/main/java/com/novelbook/android/Fragments/BookMarkFragment.java b/zhuike/src/main/java/com/novelbook/android/Fragments/BookMarkFragment.java index 7e7b16d..da97bba 100644 --- a/zhuike/src/main/java/com/novelbook/android/Fragments/BookMarkFragment.java +++ b/zhuike/src/main/java/com/novelbook/android/Fragments/BookMarkFragment.java @@ -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 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; diff --git a/zhuike/src/main/java/com/novelbook/android/Fragments/CatalogFragment.java b/zhuike/src/main/java/com/novelbook/android/Fragments/CatalogFragment.java index 5a388df..715e33a 100644 --- a/zhuike/src/main/java/com/novelbook/android/Fragments/CatalogFragment.java +++ b/zhuike/src/main/java/com/novelbook/android/Fragments/CatalogFragment.java @@ -39,7 +39,7 @@ public class CatalogFragment extends BasicFragment { @Override protected void initData() { pageFactory = PageFactory.getInstance(); - catalogueList.addAll(pageFactory.getDirectoryList()); + catalogueList.addAll(pageFactory.getChapters()); } diff --git a/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_Shelf.java b/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_Shelf.java index 2fbbef9..03dedce 100644 --- a/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_Shelf.java +++ b/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_Shelf.java @@ -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()); diff --git a/zhuike/src/main/java/com/novelbook/android/MarkActivity.java b/zhuike/src/main/java/com/novelbook/android/MarkActivity.java index a191636..cdc5869 100644 --- a/zhuike/src/main/java/com/novelbook/android/MarkActivity.java +++ b/zhuike/src/main/java/com/novelbook/android/MarkActivity.java @@ -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); } diff --git a/zhuike/src/main/java/com/novelbook/android/ReadActivity.java b/zhuike/src/main/java/com/novelbook/android/ReadActivity.java index 5c205c5..1fdf3c8 100644 --- a/zhuike/src/main/java/com/novelbook/android/ReadActivity.java +++ b/zhuike/src/main/java/com/novelbook/android/ReadActivity.java @@ -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 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) 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 bookMarksList = LitePal.where("bookpath = ? and begin = ?", pageFactory.getBookPath(),pageFactory.getCurrentPage().getBegin() + "").find(BookMarks.class); + List 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 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); diff --git a/zhuike/src/main/java/com/novelbook/android/adapter/BookListAdapter.java b/zhuike/src/main/java/com/novelbook/android/adapter/BookListAdapter.java index 1ce0b42..2f7a292 100644 --- a/zhuike/src/main/java/com/novelbook/android/adapter/BookListAdapter.java +++ b/zhuike/src/main/java/com/novelbook/android/adapter/BookListAdapter.java @@ -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()); diff --git a/zhuike/src/main/java/com/novelbook/android/adapter/MyPagerAdapter.java b/zhuike/src/main/java/com/novelbook/android/adapter/MyPagerAdapter.java index 6a60386..fa04a7a 100644 --- a/zhuike/src/main/java/com/novelbook/android/adapter/MyPagerAdapter.java +++ b/zhuike/src/main/java/com/novelbook/android/adapter/MyPagerAdapter.java @@ -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; } diff --git a/zhuike/src/main/java/com/novelbook/android/adapter/ShelfAdapter.java b/zhuike/src/main/java/com/novelbook/android/adapter/ShelfAdapter.java index 8631653..4b8e55e 100644 --- a/zhuike/src/main/java/com/novelbook/android/adapter/ShelfAdapter.java +++ b/zhuike/src/main/java/com/novelbook/android/adapter/ShelfAdapter.java @@ -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 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()); diff --git a/zhuike/src/main/java/com/novelbook/android/bean/NovelSites.java b/zhuike/src/main/java/com/novelbook/android/bean/NovelSites.java new file mode 100644 index 0000000..484ac37 --- /dev/null +++ b/zhuike/src/main/java/com/novelbook/android/bean/NovelSites.java @@ -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; + } +} diff --git a/zhuike/src/main/java/com/novelbook/android/bean/Site.java b/zhuike/src/main/java/com/novelbook/android/bean/Site.java new file mode 100644 index 0000000..b6e18f0 --- /dev/null +++ b/zhuike/src/main/java/com/novelbook/android/bean/Site.java @@ -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; + } +} diff --git a/zhuike/src/main/java/com/novelbook/android/db/BookMarks.java b/zhuike/src/main/java/com/novelbook/android/db/BookMarks.java index a78d8ca..058aa79 100644 --- a/zhuike/src/main/java/com/novelbook/android/db/BookMarks.java +++ b/zhuike/src/main/java/com/novelbook/android/db/BookMarks.java @@ -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; } } diff --git a/zhuike/src/main/java/com/novelbook/android/db/Chapter.java b/zhuike/src/main/java/com/novelbook/android/db/Chapter.java index 065a6a7..e27913d 100644 --- a/zhuike/src/main/java/com/novelbook/android/db/Chapter.java +++ b/zhuike/src/main/java/com/novelbook/android/db/Chapter.java @@ -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; diff --git a/zhuike/src/main/java/com/novelbook/android/db/Novel.java b/zhuike/src/main/java/com/novelbook/android/db/Novel.java index 2bc01e1..e5b930f 100644 --- a/zhuike/src/main/java/com/novelbook/android/db/Novel.java +++ b/zhuike/src/main/java/com/novelbook/android/db/Novel.java @@ -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; } diff --git a/zhuike/src/main/java/com/novelbook/android/db/SiteRule.java b/zhuike/src/main/java/com/novelbook/android/db/SiteRule.java new file mode 100644 index 0000000..7fc68c7 --- /dev/null +++ b/zhuike/src/main/java/com/novelbook/android/db/SiteRule.java @@ -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; + } +} diff --git a/zhuike/src/main/java/com/novelbook/android/filechooser/DirectoryFragment.java b/zhuike/src/main/java/com/novelbook/android/filechooser/DirectoryFragment.java index 58d1eb5..aa8dfbf 100644 --- a/zhuike/src/main/java/com/novelbook/android/filechooser/DirectoryFragment.java +++ b/zhuike/src/main/java/com/novelbook/android/filechooser/DirectoryFragment.java @@ -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... params) { List bookLists = params[0]; for (Novel bookList : bookLists){ - List books = LitePal.where("bookpath = ?", bookList.getNovelPath()).find(Novel.class); + List 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(); } diff --git a/zhuike/src/main/java/com/novelbook/android/netapi/HttpApi.java b/zhuike/src/main/java/com/novelbook/android/netapi/HttpApi.java index 3a1ab4e..05a3f78 100644 --- a/zhuike/src/main/java/com/novelbook/android/netapi/HttpApi.java +++ b/zhuike/src/main/java/com/novelbook/android/netapi/HttpApi.java @@ -34,13 +34,18 @@ public interface HttpApi { @Streaming Call downloadFile(@Url String fileUrl); - +//http://xiaoshuofenxiang.com/api/g/ + @GET("g") + Observable getMasterDomain(); + //http://xiaoshuofenxiang.com/api/n/f2619820112625133c14dcb170f5e092.json @GET("n/{id}.json") Observable getNovel(@Path("id") String novelId); + //http://xiaoshuofenxiang.com/api/n/f2619820112625133c14dcb170f5e092.mulu-urls.json @GET("n/{id}.mulu-urls.json") - Observable getNovelMulu(@Path("id") String novelId); + Observable getNovelSites(@Path("id") String novelId); - @GET("s/{siteName}.json") - Observable getNovelRegex(@Path("siteName") String siteName); + //http://xiaoshuofenxiang.com/api/s/www.qu.la.json + @GET("s/{siteDomain}.json") + Observable getNovelRule(@Path("siteDomain") String siteDomain); } diff --git a/zhuike/src/main/java/com/novelbook/android/netsubscribe/BookSubscribe.java b/zhuike/src/main/java/com/novelbook/android/netsubscribe/BookSubscribe.java index e0bc225..f354adc 100644 --- a/zhuike/src/main/java/com/novelbook/android/netsubscribe/BookSubscribe.java +++ b/zhuike/src/main/java/com/novelbook/android/netsubscribe/BookSubscribe.java @@ -22,9 +22,12 @@ public class BookSubscribe { Observable observable = HttpMethods.getInstance().getHttpApi().getNovel(novelId); HttpMethods.getInstance().toSubscribe(observable, subscriber); } - public static void getNovelMulu(String novelId,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getNovelMulu(novelId); + public static void getNovelSites(String novelId,DisposableObserver subscriber){ + Observable observable = HttpMethods.getInstance().getHttpApi().getNovelSites(novelId); + HttpMethods.getInstance().toSubscribe(observable, subscriber); + } + public static void getSiteRule(String domain,DisposableObserver subscriber){ + Observable observable = HttpMethods.getInstance().getHttpApi().getNovelRule(domain); HttpMethods.getInstance().toSubscribe(observable, subscriber); } - } diff --git a/zhuike/src/main/java/com/novelbook/android/netutils/HttpMethods.java b/zhuike/src/main/java/com/novelbook/android/netutils/HttpMethods.java index 0c5d770..16a1df6 100644 --- a/zhuike/src/main/java/com/novelbook/android/netutils/HttpMethods.java +++ b/zhuike/src/main/java/com/novelbook/android/netutils/HttpMethods.java @@ -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; diff --git a/zhuike/src/main/java/com/novelbook/android/netutils/NetUtil.java b/zhuike/src/main/java/com/novelbook/android/netutils/NetUtil.java index 93cdac2..7982ac5 100644 --- a/zhuike/src/main/java/com/novelbook/android/netutils/NetUtil.java +++ b/zhuike/src/main/java/com/novelbook/android/netutils/NetUtil.java @@ -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 = { diff --git a/zhuike/src/main/java/com/novelbook/android/utils/BandanAdapter.java b/zhuike/src/main/java/com/novelbook/android/utils/BandanAdapter.java index 4163dcb..3866a5b 100644 --- a/zhuike/src/main/java/com/novelbook/android/utils/BandanAdapter.java +++ b/zhuike/src/main/java/com/novelbook/android/utils/BandanAdapter.java @@ -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()); diff --git a/zhuike/src/main/java/com/novelbook/android/utils/BookUtil.java b/zhuike/src/main/java/com/novelbook/android/utils/BookUtil.java index 14be86b..550f16b 100644 --- a/zhuike/src/main/java/com/novelbook/android/utils/BookUtil.java +++ b/zhuike/src/main/java/com/novelbook/android/utils/BookUtil.java @@ -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> myArray = new ArrayList<>(); @@ -47,6 +73,9 @@ public class BookUtil { protected final ArrayList myArray = new ArrayList<>(); //目录 private List mChapters = new ArrayList<>(); + //当前章节 + // private Chapter mCurrentChapter; + public List 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 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; //如果当前缓存不是要打开的书本就缓存书本同时删除缓存 @@ -117,8 +222,6 @@ public class BookUtil { boolean isLocalImport = TextUtils.isEmpty( novel.getNovelId()); boolean isOnShelf = isLocalImport || novel.isOnShelf(); boolean isLoadChaptsFromRemote = !isLocalImport ;// && !novel.isFinished() ; //是否从目标网站下载目录 - - if(isLocalImport) { @@ -129,7 +232,7 @@ public class BookUtil { } chaptCache = new HashMap(); - 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", "
]*href=\"(/book/[\\d]+/[\\d]+\\.html)\">([^<]+)
"); + + 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 getDirectoryList(){ + public List 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 chaptCache = new HashMap(); //获取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", "
([\\s\\S]+?)
"); - siteJson.put("chapterContentDumpRegex", ""); - 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}节.*"))) ; } + + } diff --git a/zhuike/src/main/java/com/novelbook/android/utils/GsonUtil.java b/zhuike/src/main/java/com/novelbook/android/utils/GsonUtil.java new file mode 100644 index 0000000..773dbf2 --- /dev/null +++ b/zhuike/src/main/java/com/novelbook/android/utils/GsonUtil.java @@ -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; + } +} diff --git a/zhuike/src/main/java/com/novelbook/android/utils/NovelConstants.java b/zhuike/src/main/java/com/novelbook/android/utils/NovelConstants.java new file mode 100644 index 0000000..23ad27d --- /dev/null +++ b/zhuike/src/main/java/com/novelbook/android/utils/NovelConstants.java @@ -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 CURRENT_CHPATERS; + public static Map SiteRules= new FIFOMap(100);; + + + + + + +} diff --git a/zhuike/src/main/java/com/novelbook/android/utils/NovelParseUtil.java b/zhuike/src/main/java/com/novelbook/android/utils/NovelParseUtil.java index 7501f16..17aedef 100644 --- a/zhuike/src/main/java/com/novelbook/android/utils/NovelParseUtil.java +++ b/zhuike/src/main/java/com/novelbook/android/utils/NovelParseUtil.java @@ -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 = "]+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 muluMap = getChaptersMap(muluUrl, html, siteJson); + + + String[] values = new String[muluMap.size() * 2]; + + Set> es = muluMap.entrySet(); + int pos = values.length - 2; + for (Map.Entry e : es) { + values[pos] = e.getKey(); + values[pos + 1] = e.getValue(); + pos -= 2; + } + return values; + } + public static List getChapters(String domain,String muluUrl, String html, JSONObject siteJson) throws JSONException { + + Map muluMap = getChaptersMap(muluUrl, html, siteJson); + Chapter[] tmp = new Chapter[muluMap.size()]; + + + Set> es = muluMap.entrySet(); + int pos = tmp.length - 1; + for (Map.Entry e : es) { + Chapter chapter = new Chapter(); + chapter.setChapterUrl( e.getKey()); + chapter.setChapterName( e.getValue()); + chapter.setDomain(domain); + tmp[pos--] =chapter; + } + List values = new ArrayList(Arrays.asList(tmp)); + return values; + } + public static Map 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> es = muluMap.entrySet(); - int pos = values.length - 2; - for (Map.Entry 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 { diff --git a/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java b/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java index 99a7f53..482458d 100644 --- a/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java +++ b/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java @@ -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 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 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,13 +446,18 @@ 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(); + } + 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 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{ @@ -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 getDirectoryList(){ - return mBookUtil.getDirectoryList(); + public List 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; diff --git a/zhuike/src/main/res/layout/activity_book.xml b/zhuike/src/main/res/layout/activity_book.xml index 7793095..019b034 100644 --- a/zhuike/src/main/res/layout/activity_book.xml +++ b/zhuike/src/main/res/layout/activity_book.xml @@ -152,6 +152,7 @@ >