diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index c3dfe1e..c297635 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/misc.xml b/.idea/misc.xml index 5da0664..74c8e4b 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,10 +5,10 @@ diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml index fb48575..8bc84c2 100644 --- a/.idea/sqldialects.xml +++ b/.idea/sqldialects.xml @@ -1,7 +1,7 @@ - + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index dbc9ca2..637f1a4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -127,10 +127,13 @@ dependencies { implementation 'net.ricecode:string-similarity:1.0.0' implementation 'com.jayway.jsonpath:json-path:2.4.0' + //RxAndroid + implementation 'io.reactivex.rxjava2:rxjava:2.2.19' + implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' } greendao { - schemaVersion 14 + schemaVersion 16 daoPackage 'xyz.fycz.myreader.greendao.gen' // targetGenDir 'src/main/java' } diff --git a/app/libs/adapter-rxjava2-2.7.2.jar b/app/libs/adapter-rxjava2-2.7.2.jar deleted file mode 100644 index 0f5e9a8..0000000 Binary files a/app/libs/adapter-rxjava2-2.7.2.jar and /dev/null differ diff --git a/app/libs/classes.jar b/app/libs/classes.jar deleted file mode 100644 index 331c692..0000000 Binary files a/app/libs/classes.jar and /dev/null differ diff --git a/app/libs/rxjava-2.2.19.jar b/app/libs/rxjava-2.2.19.jar deleted file mode 100644 index 0f760be..0000000 Binary files a/app/libs/rxjava-2.2.19.jar and /dev/null differ diff --git a/app/src/main/assets/updatelog.fy b/app/src/main/assets/updatelog.fy index 70b2f9b..3963096 100644 --- a/app/src/main/assets/updatelog.fy +++ b/app/src/main/assets/updatelog.fy @@ -1,3 +1,19 @@ +2020.10.01 +风月读书v1.20.100123 +1、新增书源: +(1)网络小说书源:米趣小说、九桃小说、云中书库 +(2)实体书书源:超星图书·实体、作品集·实体、99藏书·实体、100本·实体 +2、优化书籍搜索显示,提升显示速度 +3、优化换源对话框 +4、阅读界面新增换源按钮,可在阅读界面直接换源 +5、新增搜索线程设置 +6、修复已知bug + +2020.09.27 +风月读书v1.20.092718 +1、修复搜索书籍后书籍详情页点击更多闪退的问题 +2、新增批量从分组移除书籍(不会删除书籍) + 2020.09.26 风月读书v1.20.092617 1、新增书架自定义分组功能(点击编辑书架即可选择书籍加入指定分组[需要自行添加分组]) diff --git a/app/src/main/java/xyz/fycz/myreader/application/MyApplication.java b/app/src/main/java/xyz/fycz/myreader/application/MyApplication.java index 07ff6d9..4deef83 100644 --- a/app/src/main/java/xyz/fycz/myreader/application/MyApplication.java +++ b/app/src/main/java/xyz/fycz/myreader/application/MyApplication.java @@ -22,6 +22,8 @@ import android.util.Log; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatDelegate; +import io.reactivex.internal.functions.Functions; +import io.reactivex.plugins.RxJavaPlugins; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; @@ -41,8 +43,8 @@ import javax.net.ssl.X509TrustManager; import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.common.URLCONST; -import xyz.fycz.myreader.creator.APPDownloadTip; -import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.ui.dialog.APPDownloadTip; +import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.entity.UpdateInfo; import xyz.fycz.myreader.ui.activity.MainActivity; @@ -63,16 +65,19 @@ public class MyApplication extends Application { super.onCreate(); application = this; HttpUtil.trustAllHosts();//信任所有证书 + RxJavaPlugins.setErrorHandler(Functions.emptyConsumer()); // handleSSLHandshake(); if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { createNotificationChannel(); } mFixedThreadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());//初始化线程池 - BaseActivity.setCloseAntiHijacking(true); initNightTheme(); + } + + public void initNightTheme() { if (isNightFS()){ AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); diff --git a/app/src/main/java/xyz/fycz/myreader/application/SysManager.java b/app/src/main/java/xyz/fycz/myreader/application/SysManager.java index 05e8b87..097a025 100644 --- a/app/src/main/java/xyz/fycz/myreader/application/SysManager.java +++ b/app/src/main/java/xyz/fycz/myreader/application/SysManager.java @@ -8,6 +8,7 @@ import xyz.fycz.myreader.enums.ReadStyle; import xyz.fycz.myreader.util.CacheHelper; import xyz.fycz.myreader.R; import xyz.fycz.myreader.entity.Setting; +import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; import xyz.fycz.myreader.widget.page.PageMode; import static xyz.fycz.myreader.application.MyApplication.getVersionCode; @@ -78,11 +79,12 @@ public class SysManager { public static void resetSetting(){ Setting setting = getSetting(); - setting.setVolumeTurnPage(true); + /*setting.setVolumeTurnPage(true); setting.setMatchChapter(true); setting.setRefreshWhenStart(true); setting.setOpenBookStore(true); - setting.setResetScreen(3); + setting.setResetScreen(3);*/ + ReadCrawlerUtil.resetReaderCrawlers(); setting.setSettingVersion(APPCONST.SETTING_VERSION); saveSetting(setting); } diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter/BaseListAdapter.java b/app/src/main/java/xyz/fycz/myreader/base/adapter/BaseListAdapter.java index 79b982a..ac32ec0 100644 --- a/app/src/main/java/xyz/fycz/myreader/base/adapter/BaseListAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/base/adapter/BaseListAdapter.java @@ -18,7 +18,7 @@ public abstract class BaseListAdapter extends RecyclerView.Adapter mList = new ArrayList<>(); + protected List mList = new ArrayList<>(); protected OnItemClickListener mClickListener; protected OnItemLongClickListener mLongClickListener; diff --git a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java index 031a6fa..c893364 100644 --- a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java +++ b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java @@ -27,6 +27,8 @@ public class APPCONST { //BookCachePath (因为getCachePath引用了Context,所以必须是静态变量,不能够是静态常量) public static String BOOK_CACHE_PATH = FileUtils.getCachePath() + File.separator + "book_cache"+ File.separator ; + public static String HTML_CACHE_PATH = FileUtils.getCachePath() + File.separator + + "html_cache"+ File.separator ; public static final String LOADING_ERROR = "\t\t \t\t\t\t\n\n  章节内容转码失败!\n\n\t\t \t\t\t\n\n"; public static long exitTime; @@ -38,6 +40,7 @@ public class APPCONST { public static final String CHAPTER_PAGE = "chapter_page"; public static final String SETTING = "setting"; public static final String SEARCH_BOOK_BEAN = "SearchBookBean"; + public static final String SOURCE_INDEX = "sourceIndex"; public static final String FONT = "font"; public static final String RESULT_RESET_SCREEN = "result_reset_screen"; public static final String RESULT_IS_COLLECTED = "result_is_collected"; @@ -76,7 +79,7 @@ public class APPCONST { public static final int PERMISSIONS_REQUEST_STORAGE = 10001; //设置版本号 - public static final int SETTING_VERSION = 3; + public static final int SETTING_VERSION = 5; public static final String FORMAT_FILE_DATE = "yyyy-MM-dd"; diff --git a/app/src/main/java/xyz/fycz/myreader/controller/SyncChaptersController.java b/app/src/main/java/xyz/fycz/myreader/controller/SyncChaptersController.java deleted file mode 100644 index fd5d851..0000000 --- a/app/src/main/java/xyz/fycz/myreader/controller/SyncChaptersController.java +++ /dev/null @@ -1,63 +0,0 @@ -package xyz.fycz.myreader.controller; - -import xyz.fycz.myreader.greendao.entity.Book; -import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.greendao.service.ChapterService; - -import java.util.ArrayList; - - - -public class SyncChaptersController { - - private ArrayList mLocalChapters;//本地章节 - private ArrayList mNetChapters;//网络章节 - private Book mBook;//书 - private ChapterService mChapterService; - - public SyncChaptersController(ArrayList localChapters,ArrayList netChapters,Book book){ - mLocalChapters = localChapters; - mNetChapters = netChapters; - mBook = book; - mChapterService = ChapterService.getInstance(); - } - - /** - * 开始同步 - */ - public void sync(){ - - } - - /** - * 更新所有章节 - * - * @param newChapters - */ - private void updateAllOldChapterData(ArrayList newChapters) { - int i; - for (i = 0; i < mLocalChapters.size() && i < newChapters.size(); i++) { - Chapter oldChapter = mLocalChapters.get(i); - Chapter newChapter = newChapters.get(i); - if (!oldChapter.getTitle().equals(newChapter.getTitle())) { - oldChapter.setTitle(newChapter.getTitle()); - oldChapter.setUrl(newChapter.getUrl()); - oldChapter.setContent(null); - mChapterService.updateEntity(oldChapter); - } - } - if (mLocalChapters.size() < newChapters.size()) { - for (int j = mLocalChapters.size(); j < newChapters.size(); j++) { - - mLocalChapters.add(newChapters.get(j)); - mChapterService.addChapter(newChapters.get(j), null); - } - } else if (mLocalChapters.size() > newChapters.size()) { - for (int j = newChapters.size(); j < mLocalChapters.size(); j++) { - mChapterService.deleteEntity(mLocalChapters.get(j)); - } - mLocalChapters.subList(0, newChapters.size()); - } - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/creator/ListenerInterface.java b/app/src/main/java/xyz/fycz/myreader/creator/ListenerInterface.java deleted file mode 100644 index 0cb3767..0000000 --- a/app/src/main/java/xyz/fycz/myreader/creator/ListenerInterface.java +++ /dev/null @@ -1,12 +0,0 @@ -package xyz.fycz.myreader.creator; - -/** - * @author fengyue - * @date 2020/7/15 8:02 - */ -public class ListenerInterface { - public interface OnRefreshFinishListener{ - void onRefresh(); - void onFinish(); - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/enums/BookSource.java b/app/src/main/java/xyz/fycz/myreader/enums/BookSource.java index 4c7fe71..447f8bb 100644 --- a/app/src/main/java/xyz/fycz/myreader/enums/BookSource.java +++ b/app/src/main/java/xyz/fycz/myreader/enums/BookSource.java @@ -2,7 +2,6 @@ package xyz.fycz.myreader.enums; /** * 小说源 - * Created by zhao on 2020/04/13. */ public enum BookSource { @@ -13,6 +12,16 @@ public enum BookSource { pinshu("品书网"), biquge("笔趣阁"), qb5("全本小说"), + miqu("米趣小说"), + jiutao("九桃小说"), + yunzhong("云中书库"), + sonovel("搜小说网"), + quannovel("全小说网"), + qiqi("奇奇小说"), + chaoxing("超星图书·实体"), + zuopin("作品集·实体"), + cangshu99("99藏书·实体"), + ben100("100本·实体"), local("本地书籍"); public String text; diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java index 50c510f..ec02228 100644 --- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java +++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java @@ -26,6 +26,7 @@ public class Book implements Serializable { private String name;//书名 private String chapterUrl;//书目Url(本地书籍为:本地书籍地址) + private String infoUrl;//书目详情Url private String imgUrl;//封面图片url private String desc;//简介 private String author;//作者 @@ -64,10 +65,10 @@ public class Book implements Serializable { private int groupSort;//分组排序 - @Generated(hash = 1308680987) - public Book(String id, String name, String chapterUrl, String imgUrl, - String desc, String author, String type, String updateDate, - String newestChapterId, String newestChapterTitle, + @Generated(hash = 170911086) + public Book(String id, String name, String chapterUrl, String infoUrl, + String imgUrl, String desc, String author, String type, + String updateDate, String newestChapterId, String newestChapterTitle, String newestChapterUrl, String historyChapterId, int histtoryChapterNum, int sortCode, int noReadNum, int chapterTotalNum, int lastReadPosition, String source, @@ -76,6 +77,7 @@ public class Book implements Serializable { this.id = id; this.name = name; this.chapterUrl = chapterUrl; + this.infoUrl = infoUrl; this.imgUrl = imgUrl; this.desc = desc; this.author = author; @@ -101,6 +103,7 @@ public class Book implements Serializable { this.id = book.id; this.name = book.name; this.chapterUrl = book.chapterUrl; + this.infoUrl = book.infoUrl; this.imgUrl = book.imgUrl; this.desc = book.desc; this.author = book.author; @@ -119,6 +122,7 @@ public class Book implements Serializable { this.isCloseUpdate = book.isCloseUpdate; this.isDownLoadAll = book.isDownLoadAll; this.groupId = book.groupId; + this.groupSort = book.groupSort; } @Generated(hash = 1839243756) @@ -311,6 +315,14 @@ public class Book implements Serializable { this.groupSort = groupSort; } + public String getInfoUrl() { + return this.infoUrl; + } + + public void setInfoUrl(String infoUrl) { + this.infoUrl = infoUrl; + } + diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookMarkService.java b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookMarkService.java index 5d8d66e..e6d02ae 100644 --- a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookMarkService.java +++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookMarkService.java @@ -59,6 +59,9 @@ public class BookMarkService extends BaseService { * @return */ public List findBookAllBookMarkByBookId(String bookId) { + if (bookId == null) { + return new ArrayList<>(); + } return GreenDaoManager.getInstance().getSession().getBookMarkDao() .queryBuilder() .where(BookMarkDao.Properties.BookId.eq(bookId)) diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookService.java b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookService.java index ba4346d..d725ba1 100644 --- a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookService.java +++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookService.java @@ -101,6 +101,7 @@ public class BookService extends BaseService { book.setSortCode(0); book.setGroupSort(0); + book.setGroupId(SharedPreUtils.getInstance().getString("curBookGroupId", "")); if (StringHelper.isEmpty(book.getId())) { book.setId(StringHelper.getStringRandom(25)); } diff --git a/app/src/main/java/xyz/fycz/myreader/model/SearchEngine.java b/app/src/main/java/xyz/fycz/myreader/model/SearchEngine.java new file mode 100644 index 0000000..c6d040a --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/model/SearchEngine.java @@ -0,0 +1,253 @@ +package xyz.fycz.myreader.model; + + +import androidx.annotation.NonNull; +import io.reactivex.Observer; +import io.reactivex.Scheduler; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.util.SharedPreUtils; +import xyz.fycz.myreader.util.ToastUtils; +import xyz.fycz.myreader.webapi.CommonApi; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + + +public class SearchEngine { + + private static final String TAG = "SearchEngine"; + + //线程池 + private ExecutorService executorService; + + private Scheduler scheduler; + private CompositeDisposable compositeDisposable; + + private List mSourceList = new ArrayList<>(); + + private int threadsNum; + private int searchSiteIndex; + private int searchSuccessNum; + private int searchFinishNum; + + private OnSearchListener searchListener; + + public SearchEngine() { + threadsNum = SharedPreUtils.getInstance().getInt("threadNum", 8); + } + + public void setOnSearchListener(OnSearchListener searchListener) { + this.searchListener = searchListener; + } + + /** + * 搜索引擎初始化 + */ + public void initSearchEngine(@NonNull List sourceList) { + mSourceList.addAll(sourceList); + executorService = Executors.newFixedThreadPool(threadsNum); + scheduler = Schedulers.from(executorService); + compositeDisposable = new CompositeDisposable(); + } + + public void stopSearch() { + if (compositeDisposable != null) compositeDisposable.dispose(); + compositeDisposable = new CompositeDisposable(); + searchListener.loadMoreFinish(true); + } + + /** + * 刷新引擎 + * + * @param sourceList + */ + public void refreshSearchEngine(@NonNull List sourceList) { + mSourceList.clear(); + mSourceList.addAll(sourceList); + } + + + /** + * 关闭引擎 + */ + public void closeSearchEngine() { + executorService.shutdown(); + if (!compositeDisposable.isDisposed()) + compositeDisposable.dispose(); + compositeDisposable = null; + } + + /** + * 搜索关键字 + * + * @param keyword + */ + public void search(String keyword) { + if (mSourceList.size() == 0) { + ToastUtils.showWarring("当前书源已全部禁用,无法搜索!"); + searchListener.loadMoreFinish(true); + return; + } + searchSuccessNum = 0; + searchSiteIndex = -1; + searchFinishNum = 0; + for (int i = 0; i < threadsNum; i++) { + searchOnEngine(keyword); + } + } + + /** + * 根据书名和作者搜索书籍 + * + * @param title + * @param author + */ + public void search(String title, String author) { + if (mSourceList.size() == 0) { + ToastUtils.showWarring("当前书源已全部禁用,无法搜索!"); + searchListener.loadMoreFinish(true); + return; + } + searchSuccessNum = 0; + searchSiteIndex = -1; + searchFinishNum = 0; + for (int i = 0; i < threadsNum; i++) { + searchOnEngine(title, author); + } + } + + private synchronized void searchOnEngine(String keyword) { + searchSiteIndex++; + if (searchSiteIndex < mSourceList.size()) { + ReadCrawler crawler = mSourceList.get(searchSiteIndex); + String searchKey = keyword; + if (crawler.getSearchCharset().toLowerCase().equals("gbk")) { + try { + searchKey = URLEncoder.encode(keyword, crawler.getSearchCharset()); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + CommonApi.search(searchKey, crawler) + .subscribeOn(scheduler) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer>() { + @Override + public void onSubscribe(Disposable d) { + compositeDisposable.add(d); + } + + @Override + public void onNext(ConcurrentMultiValueMap bookSearchBeans) { + searchFinishNum++; + if (bookSearchBeans != null) { + searchSuccessNum++; + searchListener.loadMoreSearchBook(bookSearchBeans); + } + searchOnEngine(keyword); + } + + @Override + public void onError(Throwable e) { + searchFinishNum++; + searchOnEngine(keyword); + } + + @Override + public void onComplete() { + + } + }); + } else { + if (searchFinishNum >= mSourceList.size()) { + if (searchSuccessNum == 0) { + searchListener.searchBookError(new Throwable("未搜索到内容")); + } + searchListener.loadMoreFinish(true); + } + } + + } + + private synchronized void searchOnEngine(final String title, final String author) { + searchSiteIndex++; + if (searchSiteIndex < mSourceList.size()) { + ReadCrawler crawler = mSourceList.get(searchSiteIndex); + String searchKey = title; + if (crawler.getSearchCharset().toLowerCase().equals("gbk")) { + try { + searchKey = URLEncoder.encode(title, crawler.getSearchCharset()); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + CommonApi.search(searchKey, crawler) + .subscribeOn(scheduler) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer>() { + @Override + public void onSubscribe(Disposable d) { + compositeDisposable.add(d); + } + + @Override + public void onNext(ConcurrentMultiValueMap bookSearchBeans) { + searchFinishNum++; + if (bookSearchBeans != null) { + List books = bookSearchBeans.getValues(new SearchBookBean(title, author)); + if (books != null) { + searchSuccessNum++; + searchListener.loadMoreSearchBook(books); + } + } + searchOnEngine(title, author); + } + + @Override + public void onError(Throwable e) { + searchFinishNum++; + searchOnEngine(title, author); + } + + @Override + public void onComplete() { + + } + }); + } else { + if (searchFinishNum >= mSourceList.size()) { + if (searchSuccessNum == 0) { + searchListener.searchBookError(new Throwable("未搜索到内容")); + } + searchListener.loadMoreFinish(true); + + } + } + + } + + + /************************************************************************/ + public interface OnSearchListener { + + void loadMoreFinish(Boolean isAll); + + void loadMoreSearchBook(ConcurrentMultiValueMap items); + + void loadMoreSearchBook(List items); + + void searchBookError(Throwable throwable); + + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/backup/BackupAndRestore.java b/app/src/main/java/xyz/fycz/myreader/model/backup/BackupAndRestore.java similarity index 95% rename from app/src/main/java/xyz/fycz/myreader/backup/BackupAndRestore.java rename to app/src/main/java/xyz/fycz/myreader/model/backup/BackupAndRestore.java index f22dbde..4e4ecb9 100644 --- a/app/src/main/java/xyz/fycz/myreader/backup/BackupAndRestore.java +++ b/app/src/main/java/xyz/fycz/myreader/model/backup/BackupAndRestore.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.backup; +package xyz.fycz.myreader.model.backup; import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.common.APPCONST; @@ -84,6 +84,7 @@ public class BackupAndRestore { boolean isCloseUpdate = false; boolean isDownloadAll = true; String group = "allBook"; + String infoUrl = ""; if(!sBookFields[2].contains("novel.fycz.xyz")){ source = sBookFields[17]; } @@ -99,7 +100,10 @@ public class BackupAndRestore { if (sBookFields.length >= 21){ group = sBookFields[20]; } - Book book = new Book(sBookFields[0], sBookFields[1], sBookFields[2], sBookFields[3], sBookFields[4], + if (sBookFields.length >= 22){ + infoUrl = sBookFields[21]; + } + Book book = new Book(sBookFields[0], sBookFields[1], sBookFields[2], infoUrl, sBookFields[3], sBookFields[4], sBookFields[5], sBookFields[6], sBookFields[7], sBookFields[8], sBookFields[9], sBookFields[10], sBookFields[11], Integer.parseInt(sBookFields[12]), Integer.parseInt(sBookFields[13]), Integer.parseInt(sBookFields[14]), Integer.parseInt(sBookFields[15]), Integer.parseInt(sBookFields[16]) diff --git a/app/src/main/java/xyz/fycz/myreader/backup/UserService.java b/app/src/main/java/xyz/fycz/myreader/model/backup/UserService.java similarity index 99% rename from app/src/main/java/xyz/fycz/myreader/backup/UserService.java rename to app/src/main/java/xyz/fycz/myreader/model/backup/UserService.java index 74f2383..c7aa256 100644 --- a/app/src/main/java/xyz/fycz/myreader/backup/UserService.java +++ b/app/src/main/java/xyz/fycz/myreader/model/backup/UserService.java @@ -1,7 +1,7 @@ -package xyz.fycz.myreader.backup; +package xyz.fycz.myreader.model.backup; import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.common.URLCONST; import xyz.fycz.myreader.util.*; diff --git a/app/src/main/java/xyz/fycz/myreader/mulvalmap/ConcurrentMultiValueMap.java b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/ConcurrentMultiValueMap.java similarity index 84% rename from app/src/main/java/xyz/fycz/myreader/mulvalmap/ConcurrentMultiValueMap.java rename to app/src/main/java/xyz/fycz/myreader/model/mulvalmap/ConcurrentMultiValueMap.java index e0ff783..e42625e 100644 --- a/app/src/main/java/xyz/fycz/myreader/mulvalmap/ConcurrentMultiValueMap.java +++ b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/ConcurrentMultiValueMap.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.mulvalmap; +package xyz.fycz.myreader.model.mulvalmap; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -10,7 +10,7 @@ import java.util.concurrent.ConcurrentHashMap; public class ConcurrentMultiValueMap implements MultiValueSetMap { - protected Map> mSource = new ConcurrentHashMap<>(); + protected Map> mSource = new ConcurrentHashMap<>(); public ConcurrentMultiValueMap() { } @@ -20,13 +20,13 @@ public class ConcurrentMultiValueMap implements MultiValueSetMap { if (key != null) { // 如果有这个Key就继续添加Value,没有就创建一个List并添加Value if (!mSource.containsKey(key)) - mSource.put(key, new HashSet(2)); + mSource.put(key, new LinkedHashSet(2)); mSource.get(key).add(value); } } @Override - public void add(K key, HashSet values) { + public void add(K key, LinkedHashSet values) { // 便利添加进来的List的Value,调用上面的add(K, V)方法添加 for (V value : values) { add(key, value); @@ -36,7 +36,7 @@ public class ConcurrentMultiValueMap implements MultiValueSetMap { @Override public void addAll(MultiValueSetMap mvm) { for(K k : mvm.keySet()){ - add(k, new HashSet(mvm.getValues(k))); + add(k, new LinkedHashSet(mvm.getValues(k))); } } @@ -48,21 +48,21 @@ public class ConcurrentMultiValueMap implements MultiValueSetMap { } @Override - public void set(K key, HashSet values) { + public void set(K key, LinkedHashSet values) { // 移除Key,添加List mSource.remove(key); add(key, values); } @Override - public void set(Map> map) { + public void set(Map> map) { // 移除所有值,便利Map里的所有值添加进来 mSource.clear(); mSource.putAll(map); } @Override - public HashSet remove(K key) { + public LinkedHashSet remove(K key) { return mSource.remove(key); } diff --git a/app/src/main/java/xyz/fycz/myreader/mulvalmap/LinkedMultiValueMap.java b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/LinkedMultiValueMap.java similarity index 98% rename from app/src/main/java/xyz/fycz/myreader/mulvalmap/LinkedMultiValueMap.java rename to app/src/main/java/xyz/fycz/myreader/model/mulvalmap/LinkedMultiValueMap.java index de05337..6ae3ce3 100644 --- a/app/src/main/java/xyz/fycz/myreader/mulvalmap/LinkedMultiValueMap.java +++ b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/LinkedMultiValueMap.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.mulvalmap; +package xyz.fycz.myreader.model.mulvalmap; import java.util.ArrayList; import java.util.LinkedHashMap; diff --git a/app/src/main/java/xyz/fycz/myreader/mulvalmap/MultiValueMap.java b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueMap.java similarity index 98% rename from app/src/main/java/xyz/fycz/myreader/mulvalmap/MultiValueMap.java rename to app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueMap.java index cce193b..928dae6 100644 --- a/app/src/main/java/xyz/fycz/myreader/mulvalmap/MultiValueMap.java +++ b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueMap.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.mulvalmap; +package xyz.fycz.myreader.model.mulvalmap; import java.util.List; import java.util.Map; diff --git a/app/src/main/java/xyz/fycz/myreader/mulvalmap/MultiValueSetMap.java b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueSetMap.java similarity index 88% rename from app/src/main/java/xyz/fycz/myreader/mulvalmap/MultiValueSetMap.java rename to app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueSetMap.java index f5b818c..18bdaa6 100644 --- a/app/src/main/java/xyz/fycz/myreader/mulvalmap/MultiValueSetMap.java +++ b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueSetMap.java @@ -1,9 +1,6 @@ -package xyz.fycz.myreader.mulvalmap; +package xyz.fycz.myreader.model.mulvalmap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** *

Can save multiple the value of the map.

@@ -29,7 +26,7 @@ public interface MultiValueSetMap { * @param key key. * @param values values. */ - void add(K key, HashSet values); + void add(K key, LinkedHashSet values); /** * 添加全部Key-List。 @@ -51,14 +48,14 @@ public interface MultiValueSetMap { * @param values values. * @see #set(Object, Object) */ - void set(K key, HashSet values); + void set(K key, LinkedHashSet values); /** * 替换所有的Key-HashSet。 * * @param values values. */ - void set(Map> values); + void set(Map> values); /** * 移除某一个Key,对应的所有值也将被移除。 @@ -66,7 +63,7 @@ public interface MultiValueSetMap { * @param key key. * @return value. */ - HashSet remove(K key); + LinkedHashSet remove(K key); /** * 移除所有的值。 diff --git a/app/src/main/java/xyz/fycz/myreader/source/HttpDataSource.java b/app/src/main/java/xyz/fycz/myreader/source/HttpDataSource.java index 8c00efa..cba8af7 100644 --- a/app/src/main/java/xyz/fycz/myreader/source/HttpDataSource.java +++ b/app/src/main/java/xyz/fycz/myreader/source/HttpDataSource.java @@ -5,7 +5,7 @@ import android.graphics.BitmapFactory; import android.util.Base64; import android.util.Log; -import xyz.fycz.myreader.callback.JsonCallback; +import xyz.fycz.myreader.webapi.callback.JsonCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.common.URLCONST; import xyz.fycz.myreader.entity.JsonModel; @@ -13,8 +13,8 @@ import xyz.fycz.myreader.util.HttpUtil; import xyz.fycz.myreader.util.RSAUtilV2; import xyz.fycz.myreader.util.StringHelper; import com.google.gson.Gson; -import xyz.fycz.myreader.callback.HttpCallback; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.HttpCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import java.io.BufferedReader; import java.io.File; @@ -34,9 +34,9 @@ public class HttpDataSource { * @param url * @param callback */ - public static void httpGet_html(String url, final String charsetName, final ResultCallback callback){ + public static void httpGet_html(String url, final String charsetName, boolean isRefresh, final ResultCallback callback){ Log.d("HttpGet URl", url); - HttpUtil.sendGetRequest_okHttp(url, new HttpCallback() { + HttpUtil.sendGetRequest_okHttp(url, isRefresh, new HttpCallback() { @Override public void onFinish(Bitmap bm) { @@ -63,7 +63,8 @@ public class HttpDataSource { @Override public void onFinish(String response) { - + Log.d("Local", "read finish:" + response); + callback.onFinish(response, 0); } @Override diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java index b1efd92..68c4ea4 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java @@ -5,7 +5,6 @@ import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.net.Uri; -import android.os.Bundle; import android.widget.TextView; import androidx.appcompat.widget.Toolbar; import androidx.cardview.widget.CardView; @@ -13,7 +12,7 @@ import butterknife.BindView; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.base.BaseActivity2; -import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.util.ShareUtils; import xyz.fycz.myreader.util.SharedPreUtils; import xyz.fycz.myreader.util.ToastUtils; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java index f83a396..33f4eb8 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java @@ -10,9 +10,7 @@ import android.os.Message; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.view.WindowManager; import android.widget.*; -import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -21,22 +19,20 @@ import butterknife.OnClick; import com.bumptech.glide.Glide; import com.bumptech.glide.RequestBuilder; import com.bumptech.glide.load.resource.bitmap.RoundedCorners; -import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; import com.bumptech.glide.request.RequestOptions; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.base.BaseActivity2; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.MyAlertDialog; +import xyz.fycz.myreader.ui.dialog.SourceExchangeDialog; import xyz.fycz.myreader.util.ToastUtils; import xyz.fycz.myreader.util.utils.BlurTransformation; -import xyz.fycz.myreader.webapi.crawler.BookInfoCrawler; -import xyz.fycz.myreader.webapi.crawler.ReadCrawler; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; -import xyz.fycz.myreader.creator.ChangeSourceDialog; -import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Chapter; @@ -93,6 +89,8 @@ public class BookDetailedActivity extends BaseActivity2 { private ArrayList mChapters = new ArrayList<>(); private ArrayList mNewestChapters = new ArrayList<>(); private boolean isCollected; + private SourceExchangeDialog mSourceDialog; + private int sourceIndex; @SuppressLint("HandlerLeak") private Handler mHandler = new Handler() { @@ -134,8 +132,9 @@ public class BookDetailedActivity extends BaseActivity2 { mBookService = BookService.getInstance(); mChapterService = ChapterService.getInstance(); aBooks = (ArrayList) getIntent().getSerializableExtra(APPCONST.SEARCH_BOOK_BEAN); + sourceIndex = getIntent().getIntExtra(APPCONST.SOURCE_INDEX, 0); if (aBooks != null) { - mBook = aBooks.get(0); + mBook = aBooks.get(sourceIndex); } else { mBook = (Book) getIntent().getSerializableExtra(APPCONST.BOOK); } @@ -177,6 +176,24 @@ public class BookDetailedActivity extends BaseActivity2 { bookDetailTvOpen.setText("继续阅读"); } + //Dialog + mSourceDialog = new SourceExchangeDialog(this, mBook); + if (aBooks != null && aBooks.size() > 0) { + if (isCollected) { + for (int i = 0; i < aBooks.size(); i++) { + Book book = aBooks.get(i); + if (book.getSource().equals(mBook.getSource())) { + book.setNewestChapterId("true"); + sourceIndex = i; + break; + } + } + }else { + aBooks.get(sourceIndex).setNewestChapterId("true"); + } + } + mSourceDialog.setABooks(aBooks); + mSourceDialog.setSourceIndex(sourceIndex); } @Override @@ -208,6 +225,35 @@ public class BookDetailedActivity extends BaseActivity2 { }); flOpenBook.setOnClickListener(view -> goReadActivity()); + //换源对话框 + mSourceDialog.setOnSourceChangeListener((bean, pos) -> { + Book bookTem = new Book(mBook); + bookTem.setChapterUrl(bean.getChapterUrl()); + if (!StringHelper.isEmpty(bean.getImgUrl())) { + bookTem.setImgUrl(bean.getImgUrl()); + } + if (!StringHelper.isEmpty(bean.getType())) { + bookTem.setType(bean.getType()); + } + if (!StringHelper.isEmpty(bean.getDesc())){ + bookTem.setDesc(bean.getDesc()); + } + bookTem.setSource(bean.getSource()); + if (isCollected) { + mBookService.updateBook(mBook, bookTem); + } + mBook = bookTem; + mHandler.sendMessage(mHandler.obtainMessage(1)); + if (isCollected) { + String tip = null; + if (SysManager.getSetting().isMatchChapter()) { + tip = getString(R.string.change_source_tip1); + } else { + tip = getString(R.string.change_source_tip2); + } + DialogCreator.createTipDialog(this, tip); + } + }); } @Override @@ -308,7 +354,7 @@ public class BookDetailedActivity extends BaseActivity2 { mHandler.sendMessage(mHandler.obtainMessage(3)); return; } - pbLoading.setVisibility(View.GONE); + /*pbLoading.setVisibility(View.GONE); CharSequence[] sources = new CharSequence[aBooks.size()]; int checkedItem = 0; for (int i = 0; i < sources.length; i++) { @@ -351,7 +397,8 @@ public class BookDetailedActivity extends BaseActivity2 { } dialog1.dismiss(); }).create(); - dialog.show(); + dialog.show();*/ + } /** @@ -363,14 +410,14 @@ public class BookDetailedActivity extends BaseActivity2 { if (isCollected) { mChapters = (ArrayList) mChapterService.findBookAllChapterByBookId(mBook.getId()); } - CommonApi.getBookChapters(mBook.getChapterUrl(), mReadCrawler, new ResultCallback() { + CommonApi.getBookChapters(mBook.getChapterUrl(), mReadCrawler, isChangeSource, new ResultCallback() { @Override public void onFinish(Object o, int code) { ArrayList chapters = (ArrayList) o; + mBook.setNewestChapterTitle(chapters.get(chapters.size() - 1).getTitle()); if (isCollected) { int noReadNum = chapters.size() - mBook.getChapterTotalNum(); mBook.setNoReadNum(Math.max(noReadNum, 0)); - mBook.setNewestChapterTitle(chapters.get(chapters.size() - 1).getTitle()); mChapterService.updateAllOldChapterData(mChapters, chapters, mBook.getId()); mBookService.updateEntity(mBook); if (isChangeSource && SysManager.getSetting().isMatchChapter()) { @@ -435,11 +482,14 @@ public class BookDetailedActivity extends BaseActivity2 { @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem isUpdate = menu.findItem(R.id.action_is_update); + MenuItem groupSetting = menu.findItem(R.id.action_group_setting); if (isCollected) { isUpdate.setVisible(true); + //groupSetting.setVisible(true); isUpdate.setChecked(!mBook.getIsCloseUpdate()); } else { isUpdate.setVisible(false); + groupSetting.setVisible(false); } return super.onPrepareOptionsMenu(menu); } @@ -458,7 +508,7 @@ public class BookDetailedActivity extends BaseActivity2 { ToastUtils.showWarring("无网络连接!"); return true; } - pbLoading.setVisibility(View.VISIBLE); + /*pbLoading.setVisibility(View.VISIBLE); if (aBooks == null) { ChangeSourceDialog csd = new ChangeSourceDialog(this, mBook); csd.init(new ResultCallback() { @@ -475,13 +525,11 @@ public class BookDetailedActivity extends BaseActivity2 { }); } else { createChangeSourceDia(); - } + }*/ + mSourceDialog.show(); break; case R.id.action_reload: //重新加载 - mChapters.clear(); - mNewestChapters.clear(); - initWidget(); - processLogic(); + mHandler.sendEmptyMessage(1); break; case R.id.action_is_update://是否更新 mBook.setIsCloseUpdate(!mBook.getIsCloseUpdate()); @@ -492,6 +540,8 @@ public class BookDetailedActivity extends BaseActivity2 { Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent); break; + case R.id.action_group_setting: + break; default: break; } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java index 926757c..092dc91 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java @@ -17,10 +17,10 @@ import com.scwang.smartrefresh.layout.SmartRefreshLayout; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.base.BaseActivity2; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.ChangeSourceDialog; -import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.ui.dialog.DialogCreator; +import xyz.fycz.myreader.ui.dialog.SourceExchangeDialog; import xyz.fycz.myreader.entity.bookstore.BookType; import xyz.fycz.myreader.entity.bookstore.QDBook; import xyz.fycz.myreader.entity.bookstore.RankBook; @@ -32,8 +32,8 @@ import xyz.fycz.myreader.ui.adapter.BookStoreBookTypeAdapter; import xyz.fycz.myreader.util.SharedPreUtils; import xyz.fycz.myreader.util.ToastUtils; import xyz.fycz.myreader.webapi.BookStoreApi; -import xyz.fycz.myreader.webapi.crawler.FindCrawler; -import xyz.fycz.myreader.webapi.crawler.find.ABC; +import xyz.fycz.myreader.webapi.crawler.base.FindCrawler; +import xyz.fycz.myreader.webapi.crawler.find.QiDianMobileRank; import xyz.fycz.myreader.widget.RefreshLayout; import java.util.ArrayList; @@ -62,6 +62,7 @@ public class BookstoreActivity extends BaseActivity2 { private BookStoreBookAdapter mBookStoreBookAdapter; private List bookList = new ArrayList<>(); + private SourceExchangeDialog mSourceDia; private BookType curType; @@ -166,7 +167,16 @@ public class BookstoreActivity extends BaseActivity2 { goToBookDetail(book); return; } - mHandler.sendMessage(mHandler.obtainMessage(3)); + mSourceDia = new SourceExchangeDialog(this, book); + mSourceDia.setOnSourceChangeListener((bean, pos1) -> { + Intent intent = new Intent(this, BookDetailedActivity.class); + intent.putExtra(APPCONST.SEARCH_BOOK_BEAN, (ArrayList) mSourceDia.getaBooks()); + intent.putExtra(APPCONST.SOURCE_INDEX, pos1); + BookstoreActivity.this.startActivity(intent); + mSourceDia.dismiss(); + }); + mSourceDia.show(); + /*mHandler.sendMessage(mHandler.obtainMessage(3)); ChangeSourceDialog csd = new ChangeSourceDialog(this, book); csd.initOneBook(new ResultCallback() { @Override @@ -183,7 +193,7 @@ public class BookstoreActivity extends BaseActivity2 { DialogCreator.createTipDialog(BookstoreActivity.this, "未搜索到该书籍,无法进入书籍详情!"); mHandler.sendMessage(mHandler.obtainMessage(4)); } - }); + });*/ } }); } @@ -207,14 +217,14 @@ public class BookstoreActivity extends BaseActivity2 { * 获取页面数据 */ private void getData() { - if (findCrawler instanceof ABC) { + if (findCrawler instanceof QiDianMobileRank) { SharedPreUtils spu = SharedPreUtils.getInstance(); if (spu.getString("qdCookie", "").equals("")) { - ((ABC) findCrawler).initCookie(this, new ResultCallback() { + ((QiDianMobileRank) findCrawler).initCookie(this, new ResultCallback() { @Override public void onFinish(Object o, int code) { spu.putString("qdCookie", (String) o); - mBookTypes = ((ABC) findCrawler).getRankTypes(); + mBookTypes = ((QiDianMobileRank) findCrawler).getRankTypes(); curType = mBookTypes.get(0); mHandler.sendMessage(mHandler.obtainMessage(1)); page = 1; @@ -228,7 +238,7 @@ public class BookstoreActivity extends BaseActivity2 { } }); } else { - mBookTypes = ((ABC) findCrawler).getRankTypes(); + mBookTypes = ((QiDianMobileRank) findCrawler).getRankTypes(); curType = mBookTypes.get(0); mHandler.sendMessage(mHandler.obtainMessage(1)); page = 1; @@ -265,8 +275,8 @@ public class BookstoreActivity extends BaseActivity2 { } mHandler.sendEmptyMessage(3); - if (findCrawler instanceof ABC) { - ((ABC) findCrawler).getRankBooks(curType, new ResultCallback() { + if (findCrawler instanceof QiDianMobileRank) { + ((QiDianMobileRank) findCrawler).getRankBooks(curType, new ResultCallback() { @Override public void onFinish(Object o, int code) { List books = new ArrayList<>(); diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/FileSystemActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/FileSystemActivity.java index bd4b330..a526a9e 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/FileSystemActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/FileSystemActivity.java @@ -9,7 +9,7 @@ import androidx.viewpager.widget.ViewPager; import butterknife.BindView; import xyz.fycz.myreader.R; import xyz.fycz.myreader.base.BaseTabActivity; -import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.service.BookService; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/LoginActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/LoginActivity.java index 8f5d88e..a01af55 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/LoginActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/LoginActivity.java @@ -20,11 +20,11 @@ import androidx.appcompat.widget.Toolbar; import butterknife.BindView; import com.google.android.material.textfield.TextInputLayout; import xyz.fycz.myreader.R; -import xyz.fycz.myreader.backup.UserService; +import xyz.fycz.myreader.model.backup.UserService; import xyz.fycz.myreader.base.BaseActivity2; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.util.CodeUtil; import xyz.fycz.myreader.util.CyptoUtils; import xyz.fycz.myreader.util.ToastUtils; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java index 21ef4f2..c879720 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java @@ -6,13 +6,11 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.Settings; -import android.util.Log; import android.view.Menu; import android.view.MenuItem; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.widget.Toolbar; import androidx.core.content.FileProvider; import androidx.fragment.app.Fragment; @@ -25,12 +23,10 @@ import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.base.BaseActivity2; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.ui.fragment.BookStoreFragment; +import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.ui.fragment.BookcaseFragment; import xyz.fycz.myreader.ui.fragment.FindFragment; import xyz.fycz.myreader.ui.fragment.MineFragment; -import xyz.fycz.myreader.ui.presenter.BookcasePresenter; import xyz.fycz.myreader.util.SharedPreUtils; import xyz.fycz.myreader.util.ToastUtils; @@ -39,7 +35,6 @@ import java.util.ArrayList; import java.util.List; import static androidx.fragment.app.FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT; -import static xyz.fycz.myreader.application.MyApplication.checkVersionByServer; /** * @author fengyue @@ -237,12 +232,14 @@ public class MainActivity extends BaseActivity2 { mBookcaseFragment.getmBookcasePresenter().cancelEdit(); invalidateOptionsMenu(); return true; - case R.id.action_change_group: - mBookcaseFragment.getmBookcasePresenter() - .showBookGroupMenu(findViewById(R.id.action_change_group), () -> { - groupName = SharedPreUtils.getInstance().getString("curBookGroupName", "所有书籍"); - getSupportActionBar().setSubtitle(groupName); - }); + case R.id.action_change_group: case R.id.action_group_man: + if (!mBookcaseFragment.getmBookcasePresenter().hasOnGroupChangeListener()) { + mBookcaseFragment.getmBookcasePresenter().addOnGroupChangeListener(() -> { + groupName = SharedPreUtils.getInstance().getString("curBookGroupName", "所有书籍"); + getSupportActionBar().setSubtitle(groupName); + }); + } + break; case R.id.action_edit: invalidateOptionsMenu(); break; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/MoreSettingActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/MoreSettingActivity.java index abb8179..3e30e14 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/MoreSettingActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/MoreSettingActivity.java @@ -3,6 +3,7 @@ package xyz.fycz.myreader.ui.activity; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; +import android.view.LayoutInflater; import android.view.View; import android.widget.*; import androidx.appcompat.app.AlertDialog; @@ -15,8 +16,9 @@ import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.base.BaseActivity2; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.creator.MultiChoiceDialog; +import xyz.fycz.myreader.ui.dialog.DialogCreator; +import xyz.fycz.myreader.ui.dialog.MultiChoiceDialog; +import xyz.fycz.myreader.ui.dialog.MyAlertDialog; import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; @@ -55,6 +57,10 @@ public class MoreSettingActivity extends BaseActivity2 { LinearLayout mLlCloseRefresh; @BindView(R.id.more_setting_ll_disable_source) LinearLayout mLlDisableSource; + @BindView(R.id.more_setting_ll_thread_num) + LinearLayout mLlThreadNum; + @BindView(R.id.more_setting_tv_thread_num) + TextView mTvThreadNum; @BindView(R.id.more_setting_iv_match_chapter_tip) ImageView mIvMatchChapterTip; @BindView(R.id.more_setting_rl_match_chapter) @@ -89,16 +95,20 @@ public class MoreSettingActivity extends BaseActivity2 { private ArrayList mBooks; int booksCount; CharSequence[] mBooksName; + int threadNum; //选择禁用更新书籍对话框 private AlertDialog mCloseRefreshDia; //选择禁用更新书源对话框 private AlertDialog mDisableSourceDia; + //线程选择 + private AlertDialog mThreadSelectDia; //选择一键缓存书籍对话框 private AlertDialog mDownloadAllDia; //选择清除缓存对话框 private AlertDialog mDeleteCatheDia; + @Override protected int getContentId() { return R.layout.activity_more_setting; @@ -115,6 +125,7 @@ public class MoreSettingActivity extends BaseActivity2 { catheCap = mSetting.getCatheGap(); autoRefresh = mSetting.isRefreshWhenStart(); openBookStore = mSetting.isOpenBookStore(); + threadNum = SharedPreUtils.getInstance().getInt("threadNum", 8); } @Override @@ -133,6 +144,7 @@ public class MoreSettingActivity extends BaseActivity2 { } else { mRlMatchChapterSuitability.setVisibility(View.GONE); } + mTvThreadNum.setText(getString(R.string.cur_thread_num, threadNum)); } private void initSwitchStatus() { @@ -261,6 +273,26 @@ public class MoreSettingActivity extends BaseActivity2 { }); }); + mLlThreadNum.setOnClickListener(v -> { + View view = LayoutInflater.from(this).inflate(R.layout.dialog_number_picker, null); + NumberPicker threadPick = view.findViewById(R.id.number_picker); + threadPick.setMaxValue(1024); + threadPick.setMinValue(1); + threadPick.setValue(threadNum); + threadPick.setOnScrollListener((view1, scrollState) -> { + + }); + mThreadSelectDia = MyAlertDialog.build(this) + .setTitle("搜索线程数") + .setView(view) + .setPositiveButton("确定", (dialog, which) -> { + threadNum = threadPick.getValue(); + SharedPreUtils.getInstance().putInt("threadNum", threadNum); + mTvThreadNum.setText(getString(R.string.cur_thread_num, threadNum)); + }).setNegativeButton("取消", null) + .show(); + }); + mRlMatchChapter.setOnClickListener( (v) -> { if (isMatchChapter) { @@ -363,20 +395,6 @@ public class MoreSettingActivity extends BaseActivity2 { }); }); - - /*mRlBookstore.setOnClickListener( - (v) -> { - if (openBookStore) { - openBookStore = false; - } else { - openBookStore = true; - } - mScBookstore.setChecked(openBookStore); - mSetting.setOpenBookStore(openBookStore); - SysManager.saveSetting(mSetting); - ToastUtils.showInfo("重启后生效!"); - } - );*/ } @Override @@ -388,8 +406,8 @@ public class MoreSettingActivity extends BaseActivity2 { private void initSpinner() { // initSwitchStatus() be called earlier than onCreate(), so setSelection() won't work ArrayAdapter resetScreenAdapter = ArrayAdapter.createFromResource(this, - R.array.reset_screen_time, R.layout.spinner); - resetScreenAdapter.setDropDownViewResource(R.layout.spinner_item); + R.array.reset_screen_time, android.R.layout.simple_spinner_item); + resetScreenAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mScResetScreen.setAdapter(resetScreenAdapter); int resetScreenSelection = 0; @@ -439,8 +457,8 @@ public class MoreSettingActivity extends BaseActivity2 { ArrayAdapter matchSuiAdapter = ArrayAdapter.createFromResource(this, - R.array.match_chapter_suitability, R.layout.spinner); - matchSuiAdapter.setDropDownViewResource(R.layout.spinner_item); + R.array.match_chapter_suitability, android.R.layout.simple_spinner_item); + matchSuiAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mScMatchChapterSuitability.setAdapter(matchSuiAdapter); if (matchChapterSuitability == 0.0) { @@ -467,8 +485,8 @@ public class MoreSettingActivity extends BaseActivity2 { ArrayAdapter catheGapAdapter = ArrayAdapter.createFromResource(this, - R.array.cathe_chapter_gap, R.layout.spinner); - catheGapAdapter.setDropDownViewResource(R.layout.spinner_item); + R.array.cathe_chapter_gap, android.R.layout.simple_spinner_item); + catheGapAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mScCatheGap.setAdapter(catheGapAdapter); if (catheCap == 0) { diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java index 616f9f1..c2c42dc 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java @@ -20,7 +20,7 @@ import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.ui.presenter.ReadPresenter; import xyz.fycz.myreader.widget.page.PageView; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/RegisterActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/RegisterActivity.java index daa38ff..9d2965b 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/RegisterActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/RegisterActivity.java @@ -3,7 +3,6 @@ package xyz.fycz.myreader.ui.activity; import android.annotation.SuppressLint; import android.app.ProgressDialog; import android.graphics.Bitmap; -import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.Editable; @@ -18,10 +17,10 @@ import androidx.appcompat.widget.Toolbar; import butterknife.BindView; import com.google.android.material.textfield.TextInputLayout; import xyz.fycz.myreader.R; -import xyz.fycz.myreader.backup.UserService; +import xyz.fycz.myreader.model.backup.UserService; import xyz.fycz.myreader.base.BaseActivity2; -import xyz.fycz.myreader.callback.ResultCallback; -import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.webapi.callback.ResultCallback; +import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.util.CodeUtil; import xyz.fycz.myreader.util.ToastUtils; import xyz.fycz.myreader.util.utils.StringUtils; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java index 514ca85..3580cf0 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java @@ -3,7 +3,6 @@ package xyz.fycz.myreader.ui.activity; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -15,33 +14,38 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.*; import androidx.appcompat.widget.Toolbar; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import butterknife.BindView; +import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.scwang.smartrefresh.layout.SmartRefreshLayout; import me.gujun.android.taggroup.TagGroup; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.base.BaseActivity2; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.custom.DragSortGridView; +import xyz.fycz.myreader.model.SearchEngine; import xyz.fycz.myreader.entity.SearchBookBean; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.SearchHistory; import xyz.fycz.myreader.greendao.service.SearchHistoryService; -import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; import xyz.fycz.myreader.ui.adapter.SearchBookAdapter; import xyz.fycz.myreader.ui.adapter.SearchHistoryAdapter; import xyz.fycz.myreader.util.StringHelper; import xyz.fycz.myreader.util.ToastUtils; import xyz.fycz.myreader.webapi.CommonApi; -import xyz.fycz.myreader.webapi.crawler.ReadCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; +import xyz.fycz.myreader.widget.RefreshProgressBar; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.List; /** * @author fengyue @@ -54,12 +58,12 @@ public class SearchBookActivity extends BaseActivity2 { TextView tvSearchConform; @BindView(R.id.ll_refresh_suggest_books) LinearLayout llRefreshSuggestBooks; - @BindView(R.id.gv_search_books_list) - DragSortGridView gvSearchBooksList; + @BindView(R.id.rv_search_books_list) + RecyclerView rvSearchBooksList; @BindView(R.id.ll_suggest_books_view) LinearLayout llSuggestBooksView; - @BindView(R.id.pb_loading) - ProgressBar pbLoading; + @BindView(R.id.rpb) + RefreshProgressBar rpb; @BindView(R.id.lv_history_list) ListView lvHistoryList; @BindView(R.id.ll_clear_history) @@ -74,13 +78,14 @@ public class SearchBookActivity extends BaseActivity2 { TextView renewByText; @BindView(R.id.srl_search_book_list) SmartRefreshLayout srlSearchBookList; + @BindView(R.id.fabSearchStop) + FloatingActionButton fabSearchStop; private SearchBookAdapter mSearchBookAdapter; private String searchKey;//搜索关键字 private ArrayList mBooksBean = new ArrayList<>(); private ConcurrentMultiValueMap mBooks = new ConcurrentMultiValueMap<>(); - private ArrayList mAdapterBooks = new ArrayList<>(); private ArrayList mSearchHistories = new ArrayList<>(); private ArrayList mSuggestions = new ArrayList<>(); @@ -97,6 +102,8 @@ public class SearchBookActivity extends BaseActivity2 { private int inputConfirm = 0;//搜索输入确认 private int confirmTime = 1000;//搜索输入确认时间(毫秒) + private SearchEngine searchEngine; + private static String[] suggestion = {"第一序列", "大道朝天", "伏天氏", "终极斗罗", "我师兄实在太稳健了", "烂柯棋缘", "诡秘之主"}; private static String[] suggestion2 = {"不朽凡人", "圣墟", "我是至尊", "龙王传说", "太古神王", "一念永恒", "雪鹰领主", "大主宰"}; @@ -109,18 +116,21 @@ public class SearchBookActivity extends BaseActivity2 { search(); break; case 2: - if (curThreadCount == 0 && !isStopSearch) { - initSearchList(); + if (srlSearchBookList != null) { srlSearchBookList.finishRefresh(); - pbLoading.setVisibility(View.GONE); - }/*else { - notifyDataSetChanged(); - mSearchBookActivity.getSrlSearchBookList().finishRefresh(); - }*/ + } + if (curThreadCount == 0 && !isStopSearch) { + rpb.setIsAutoLoading(false); + } + break; + case 3: + fabSearchStop.setVisibility(View.GONE); break; } } }; + + @Override protected int getContentId() { return R.layout.activity_search_book; @@ -140,6 +150,36 @@ public class SearchBookActivity extends BaseActivity2 { for (int i = 0; i < suggestion.length; i++) { mSuggestions.add(suggestion[i]); } + + searchEngine = new SearchEngine(); + searchEngine.setOnSearchListener(new SearchEngine.OnSearchListener() { + @Override + public void loadMoreFinish(Boolean isAll) { + if (rpb != null) { + rpb.setIsAutoLoading(false); + } + mHandler.sendEmptyMessage(3); + } + + @Override + public void loadMoreSearchBook(ConcurrentMultiValueMap items) { + mBooks.addAll(items); + curThreadCount--; + mSearchBookAdapter.addAll(new ArrayList<>(items.keySet()), searchKey); + mHandler.sendMessage(mHandler.obtainMessage(2)); + } + + @Override + public void loadMoreSearchBook(List items) { + + } + + @Override + public void searchBookError(Throwable throwable) { + curThreadCount = 0; + mHandler.sendMessage(mHandler.obtainMessage(2)); + } + }); } @Override @@ -177,11 +217,13 @@ public class SearchBookActivity extends BaseActivity2 { } }); + rvSearchBooksList.setLayoutManager(new LinearLayoutManager(this)); + //上拉刷新 - srlSearchBookList.setOnRefreshListener(refreshLayout -> mHandler.sendMessage(mHandler.obtainMessage(1))); - srlSearchBookList.setEnableRefresh(false); - gvSearchBooksList.setNumColumns(1); - gvSearchBooksList.setDragModel(-1); + srlSearchBookList.setOnRefreshListener(refreshLayout -> { + stopSearch(); + mHandler.sendMessage(mHandler.obtainMessage(1)); + }); initSuggestionBook(); initHistoryList(); } @@ -194,12 +236,7 @@ public class SearchBookActivity extends BaseActivity2 { renewByImage.setOnClickListener(new RenewSuggestionBook()); //换一批点击事件 renewByText.setOnClickListener(new RenewSuggestionBook()); - //进入书籍详情页 - gvSearchBooksList.setOnItemClickListener((adapterView, view, i, l) -> { - Intent intent = new Intent(this, BookDetailedActivity.class); - intent.putExtra(APPCONST.SEARCH_BOOK_BEAN, new ArrayList<>(mBooks.getValues(mBooksBean.get(i)))); - startActivity(intent); - }); + //搜索按钮点击事件 tvSearchConform.setOnClickListener(view -> mHandler.sendMessage(mHandler.obtainMessage(1))); //suggestion搜索事件 @@ -227,6 +264,10 @@ public class SearchBookActivity extends BaseActivity2 { } return true; }); + + fabSearchStop.setOnClickListener(v -> { + stopSearch(); + }); } @@ -244,7 +285,7 @@ public class SearchBookActivity extends BaseActivity2 { if (Arrays.equals(s, suggestion)) { tgSuggestBook.setTags(suggestion2); } else { - tgSuggestBook.setTags(suggestion); + tgSuggestBook.setTags(suggestion); } } } @@ -267,105 +308,69 @@ public class SearchBookActivity extends BaseActivity2 { * 初始化搜索列表 */ private void initSearchList() { - initmBooksBean(); - mSearchBookAdapter = new SearchBookAdapter(this, - R.layout.listview_search_book_item, mBooksBean, mBooks); - gvSearchBooksList.setAdapter(mSearchBookAdapter); - gvSearchBooksList.setVisibility(View.VISIBLE); + //initmBooksBean(); + rvSearchBooksList.setVisibility(View.VISIBLE); llSuggestBooksView.setVisibility(View.GONE); llSuggestBooksView.setVisibility(View.GONE); } - /** - * 更新搜索列表 - */ - private void notifyDataSetChanged() { - if (curThreadCount == 0) { - pbLoading.setVisibility(View.GONE); - } - initmBooksBean(); - } - /** - * 初始化mBooksBean - */ - private void initmBooksBean() { - synchronized (this) { - mBooksBean.clear(); - mBooksBean.addAll(mBooks.keySet()); - //排序,基于最符合关键字的搜书结果应该是最短的 - //TODO ;这里只做了简单的比较排序,还需要继续完善 - Collections.sort(mBooksBean, (o1, o2) -> { - if (searchKey.equals(o1.getName())) - return -1; - if (searchKey.equals(o2.getName())) - return 1; - if (searchKey.equals(o1.getAuthor())) - return -1; - if (searchKey.equals(o2.getAuthor())) - return 1; - if (o1.getName().length() < o2.getName().length()) - return -1; - if (o1.getName().length() == o2.getName().length()) - return 0; - return 1; - }); - /*MyApplication.runOnUiThread(new Runnable() { - @Override - public void run() { - mSearchBookAdapter.notifyDataSetChanged(); - } - });*/ - } - } + /** * 获取搜索数据 */ private void getData() { + initSearchList(); mBooksBean.clear(); mBooks.clear(); ArrayList readCrawlers = ReadCrawlerUtil.getReadCrawlers(); allThreadCount = readCrawlers.size(); - if (allThreadCount == 0){ + if (allThreadCount == 0) { ToastUtils.showWarring("当前书源已全部禁用,无法搜索!"); - pbLoading.setVisibility(View.GONE); + rpb.setIsAutoLoading(false); return; } curThreadCount = allThreadCount; - for (ReadCrawler readCrawler : readCrawlers){ + /*for (ReadCrawler readCrawler : readCrawlers) { searchBookByCrawler(readCrawler, readCrawler.getSearchCharset()); - } + }*/ + searchEngine.initSearchEngine(ReadCrawlerUtil.getReadCrawlers()); + searchEngine.search(searchKey); } /** * 搜索 */ private void search() { - pbLoading.setVisibility(View.VISIBLE); + rpb.setIsAutoLoading(true); + fabSearchStop.setVisibility(View.VISIBLE); if (StringHelper.isEmpty(searchKey)) { isStopSearch = true; - pbLoading.setVisibility(View.GONE); - gvSearchBooksList.setVisibility(View.GONE); + stopSearch(); + rpb.setIsAutoLoading(false); + rvSearchBooksList.setVisibility(View.GONE); llSuggestBooksView.setVisibility(View.VISIBLE); initHistoryList(); - gvSearchBooksList.setAdapter(null); + rvSearchBooksList.setAdapter(null); srlSearchBookList.setEnableRefresh(false); } else { isStopSearch = false; - gvSearchBooksList.setVisibility(View.VISIBLE); + + mSearchBookAdapter = new SearchBookAdapter(mBooks); + + rvSearchBooksList.setAdapter(mSearchBookAdapter); + //进入书籍详情页 + mSearchBookAdapter.setOnItemClickListener((view, pos) -> { + Intent intent = new Intent(this, BookDetailedActivity.class); + intent.putExtra(APPCONST.SEARCH_BOOK_BEAN, new ArrayList<>(mBooks.getValues(mSearchBookAdapter.getItem(pos)))); + startActivity(intent); + }); + srlSearchBookList.setEnableRefresh(true); + rvSearchBooksList.setVisibility(View.VISIBLE); llSuggestBooksView.setVisibility(View.GONE); llHistoryView.setVisibility(View.GONE); getData(); - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (gvSearchBooksList.getmScrollView().getScrollY() == 0){ - srlSearchBookList.setEnableRefresh(true); - } - //滑动监听器 - gvSearchBooksList.getmScrollView().setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { - srlSearchBookList.setEnableRefresh(scrollY == 0); - }); - } mSearchHistoryService.addOrUpadteHistory(searchKey); //收起软键盘 InputMethodManager imm = (InputMethodManager) MyApplication.getmContext().getSystemService(Context.INPUT_METHOD_SERVICE); @@ -374,6 +379,11 @@ public class SearchBookActivity extends BaseActivity2 { } } + private void stopSearch() { + searchEngine.stopSearch(); + mHandler.sendEmptyMessage(3); + } + @Override public void onBackPressed() { if (StringHelper.isEmpty(searchKey)) { @@ -413,7 +423,11 @@ public class SearchBookActivity extends BaseActivity2 { @Override protected void onDestroy() { - super.onDestroy(); isStopSearch = true; + stopSearch(); + for (int i = 0; i < 9; i++) { + mHandler.removeMessages(i + 1); + } + super.onDestroy(); } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookStoreBookAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookStoreBookAdapter.java index c91050f..b34722d 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookStoreBookAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookStoreBookAdapter.java @@ -1,40 +1,10 @@ package xyz.fycz.myreader.ui.adapter; import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Handler; -import android.os.Message; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.recyclerview.widget.RecyclerView; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.resource.bitmap.RoundedCorners; -import com.bumptech.glide.request.RequestOptions; -import xyz.fycz.myreader.R; import xyz.fycz.myreader.base.adapter.BaseListAdapter; import xyz.fycz.myreader.base.adapter.IViewHolder; -import xyz.fycz.myreader.callback.ResultCallback; -import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.custom.DragAdapter; -import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.ui.activity.BookDetailedActivity; -import xyz.fycz.myreader.ui.adapter.holder.BookStoreBookHolder; -import xyz.fycz.myreader.webapi.crawler.BiQuGeReadCrawler; -import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; -import xyz.fycz.myreader.util.StringHelper; -import xyz.fycz.myreader.webapi.CommonApi; - - -import java.util.List; +import xyz.fycz.myreader.ui.adapter.holder.BookStoreBookHolder; public class BookStoreBookAdapter extends BaseListAdapter { diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java index e3a5087..0e1c52b 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java @@ -4,8 +4,6 @@ import android.content.Context; import android.content.DialogInterface; import android.widget.*; -import androidx.appcompat.app.AlertDialog; - import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; @@ -17,9 +15,9 @@ import java.util.*; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.creator.MyAlertDialog; -import xyz.fycz.myreader.custom.DragAdapter; +import xyz.fycz.myreader.ui.dialog.DialogCreator; +import xyz.fycz.myreader.ui.dialog.MyAlertDialog; +import xyz.fycz.myreader.widget.custom.DragAdapter; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Chapter; import xyz.fycz.myreader.greendao.service.BookService; @@ -122,7 +120,7 @@ public abstract class BookcaseAdapter extends DragAdapter { }, null); }else { DialogCreator.createCommonDialog(mContext, "删除/移除书籍", "您是希望删除《" + book.getName() + "》及其所有缓存还是从分组中移除该书籍(不会删除书籍)呢?", - true, "删除书籍", "从分组中移除书籍",(dialogInterface, i) -> { + true, "删除书籍", "从分组中移除",(dialogInterface, i) -> { remove(book); ToastUtils.showSuccess("书籍删除成功!"); mBookcasePresenter.init(); diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java index f1b2ecf..64d1df5 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java @@ -5,7 +5,6 @@ import android.content.Intent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; import android.widget.LinearLayout; import android.widget.TextView; @@ -21,8 +20,8 @@ import java.util.ArrayList; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.creator.MyAlertDialog; +import xyz.fycz.myreader.ui.dialog.DialogCreator; +import xyz.fycz.myreader.ui.dialog.MyAlertDialog; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.ui.activity.BookDetailedActivity; import xyz.fycz.myreader.ui.activity.ReadActivity; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java index 48a9c99..017ece3 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java @@ -1,12 +1,10 @@ package xyz.fycz.myreader.ui.adapter; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; import androidx.appcompat.app.AlertDialog; @@ -20,8 +18,8 @@ import java.util.ArrayList; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.creator.MyAlertDialog; +import xyz.fycz.myreader.ui.dialog.DialogCreator; +import xyz.fycz.myreader.ui.dialog.MyAlertDialog; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.ui.activity.BookDetailedActivity; import xyz.fycz.myreader.ui.activity.ReadActivity; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/FontsAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/FontsAdapter.java index 5601a6c..a21d8f8 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/FontsAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/FontsAdapter.java @@ -27,7 +27,7 @@ import java.util.ArrayList; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.SysManager; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.common.URLCONST; import xyz.fycz.myreader.entity.Setting; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/SearchBookAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/SearchBookAdapter.java index 4458f75..b70c0a1 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/SearchBookAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/SearchBookAdapter.java @@ -1,191 +1,81 @@ package xyz.fycz.myreader.ui.adapter; import android.app.Activity; -import android.content.Context; -import android.os.Handler; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.resource.bitmap.RoundedCorners; -import com.bumptech.glide.request.RequestOptions; -import xyz.fycz.myreader.R; +import android.text.TextUtils; import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.callback.ResultCallback; -import xyz.fycz.myreader.webapi.crawler.BookInfoCrawler; -import xyz.fycz.myreader.webapi.crawler.ReadCrawler; -import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; -import xyz.fycz.myreader.custom.DragAdapter; +import xyz.fycz.myreader.base.adapter.BaseListAdapter; +import xyz.fycz.myreader.base.adapter.IViewHolder; import xyz.fycz.myreader.entity.SearchBookBean; -import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; -import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; -import xyz.fycz.myreader.util.StringHelper; -import xyz.fycz.myreader.webapi.CommonApi; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.ui.adapter.holder.SearchBookHolder; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; - /** - * Created by zhao on 2017/7/26. + * @author fengyue + * @date 2020/10/2 10:08 */ - -public class SearchBookAdapter extends DragAdapter { - - private int mResourceId; - - private Context mContext; - +public class SearchBookAdapter extends BaseListAdapter { private ConcurrentMultiValueMap mBooks; - private ArrayList mSearchBookBeans; - - private ArrayList mTempSearchBookBeans = new ArrayList<>(); - - private HashMap mTempBooks = new HashMap<>(); - - private Handler mHandle = new Handler(message -> { - - switch (message.what) { - case 1: - ViewHolder holder = (ViewHolder) message.obj; - int pos = message.arg1; - SearchBookAdapter.this.initOtherInfo(pos, holder); - break; - } - return false; - }); - - public SearchBookAdapter(Context context, int resourceId, ArrayList datas, - ConcurrentMultiValueMap mBooks){ - mContext = context; - mSearchBookBeans = datas; - mResourceId = resourceId; + public SearchBookAdapter(ConcurrentMultiValueMap mBooks) { this.mBooks = mBooks; } @Override - public int getCount() { - return mSearchBookBeans.size(); - } - - @Override - public SearchBookBean getItem(int position) { - return mSearchBookBeans.get(position); - } - - @Override - public long getItemId(int position) { - return 0; - } - - @NonNull - @Override - public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { - ViewHolder viewHolder = null; - if (convertView == null){ - viewHolder = new ViewHolder(); - convertView = LayoutInflater.from(mContext).inflate(mResourceId,null); - viewHolder.ivBookImg = convertView.findViewById(R.id.iv_book_img); - viewHolder.tvBookName = convertView.findViewById(R.id.tv_book_name); - viewHolder.tvAuthor = convertView.findViewById(R.id.tv_book_author); - viewHolder.tvDesc = convertView.findViewById(R.id.tv_book_desc); - viewHolder.tvType = convertView.findViewById(R.id.tv_book_type); - viewHolder.tvSource = convertView.findViewById(R.id.tv_book_source); - viewHolder.tvNewestChapter = convertView.findViewById(R.id.tv_book_newest_chapter); - //viewHolder.tvNewestChapter = convertView.findViewById(R.id.tv_book_newest_chapter); - convertView.setTag(viewHolder); - }else { - viewHolder = (ViewHolder) convertView.getTag(); - } - initView(position,viewHolder); - return convertView; + protected IViewHolder createViewHolder(int viewType) { + return new SearchBookHolder(mBooks); } - private void initView(final int position, final ViewHolder viewHolder){ - List aBooks = mBooks.getValues(getItem(position)); - int bookCount = aBooks.size(); - Book book = aBooks.get(0); - SearchBookBean ssb = new SearchBookBean(book.getName(), book.getAuthor()); - - //判断是否已经加载,防止多次加载 - /*for (SearchBookBean temp : mTempSearchBookBeans){//已加载 - if (ssb.equals(temp)){ - book = mTempBooks.get(ssb); - } - }*/ - - if (StringHelper.isEmpty(book.getImgUrl())){ - book.setImgUrl(""); - } - viewHolder.tvBookName.setText(book.getName()); - viewHolder.tvNewestChapter.setText("最新章节:" + book.getNewestChapterTitle()); - viewHolder.tvAuthor.setText(book.getAuthor()); - viewHolder.tvSource.setText("书源:" + BookSource.fromString(book.getSource()).text - + " 共" + bookCount + "个源"); - viewHolder.tvDesc.setText(""); - viewHolder.tvType.setText(""); - ReadCrawler rc = ReadCrawlerUtil.getReadCrawler(book.getSource()); - if (rc instanceof BookInfoCrawler && StringHelper.isEmpty(book.getImgUrl())){ - BookInfoCrawler bic = (BookInfoCrawler) rc; - CommonApi.getBookInfo(book, bic, new ResultCallback() { - @Override - public void onFinish(Object o, int code) { - mHandle.sendMessage(mHandle.obtainMessage(1, position,0,viewHolder)); + public synchronized void addAll(List newDataS, String keyWord) { + List copyDataS = mList; + if (newDataS != null && newDataS.size() > 0) { + List searchBookBeansAdd = new ArrayList<>(); + if (copyDataS.size() == 0) { + copyDataS.addAll(newDataS); + } else { + //存在 + for (SearchBookBean temp : newDataS) { + boolean hasSame = false; + for (int i = 0, size = copyDataS.size(); i < size; i++) { + SearchBookBean searchBook = copyDataS.get(i); + if (TextUtils.equals(temp.getName(), searchBook.getName()) + && TextUtils.equals(temp.getAuthor(), searchBook.getAuthor())) { + hasSame = true; + break; + } + } + + if (!hasSame) { + searchBookBeansAdd.add(temp); + } } - - @Override - public void onError(Exception e) { - + //添加 + for (SearchBookBean temp : searchBookBeansAdd) { + if (TextUtils.equals(keyWord, temp.getName())) { + for (int i = 0; i < copyDataS.size(); i++) { + SearchBookBean searchBook = copyDataS.get(i); + if (!TextUtils.equals(keyWord, searchBook.getName())) { + copyDataS.add(i, temp); + break; + } + } + } else if (TextUtils.equals(keyWord, temp.getAuthor())) { + for (int i = 0; i < copyDataS.size(); i++) { + SearchBookBean searchBook = copyDataS.get(i); + if (!TextUtils.equals(keyWord, searchBook.getName()) && !TextUtils.equals(keyWord, searchBook.getAuthor())) { + copyDataS.add(i, temp); + break; + } + } + } else { + copyDataS.add(temp); + } } - }); - }else { - initOtherInfo(position, viewHolder); - } - //viewHolder.tvNewestChapter.setText(book.getNewestChapterTitle()); - //添加已经加载的书籍 - /*mTempSearchBookBeans.add(ssb); - mTempBooks.put(ssb, book);*/ - } - private void initOtherInfo(final int position, final ViewHolder holder){ - Book book = mBooks.getValue(getItem(position), 0); - //图片 - if (!MyApplication.isDestroy((Activity) mContext)) { - Glide.with(mContext) - .load(book.getImgUrl()) -// .override(DipPxUtil.dip2px(getContext(), 80), DipPxUtil.dip2px(getContext(), 150)) - .error(R.mipmap.no_image) - .placeholder(R.mipmap.no_image) - //设置圆角 - .apply(RequestOptions.bitmapTransform(new RoundedCorners(8))) - .into(holder.ivBookImg); + } + MyApplication.runOnUiThread(this::notifyDataSetChanged); } - //简介 - holder.tvDesc.setText("简介:" + book.getDesc()); - holder.tvType.setText(book.getType()); } - - @Override - public void onDataModelMove(int from, int to) { - - } - - class ViewHolder{ - ImageView ivBookImg; - TextView tvBookName; - TextView tvDesc; - TextView tvAuthor; - TextView tvType; - TextView tvSource; - TextView tvNewestChapter; - //TextView tvNewestChapter; - } - } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/SourceExchangeAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/SourceExchangeAdapter.java new file mode 100644 index 0000000..df73b74 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/SourceExchangeAdapter.java @@ -0,0 +1,19 @@ +package xyz.fycz.myreader.ui.adapter; + +import xyz.fycz.myreader.base.adapter.BaseListAdapter; +import xyz.fycz.myreader.base.adapter.IViewHolder; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.ui.adapter.holder.SourceExchangeHolder; + +import java.util.List; + +/** + * @author fengyue + * @date 2020/9/30 18:42 + */ +public class SourceExchangeAdapter extends BaseListAdapter { + @Override + protected IViewHolder createViewHolder(int viewType) { + return new SourceExchangeHolder(); + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/SearchBookHolder.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/SearchBookHolder.java new file mode 100644 index 0000000..796712d --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/SearchBookHolder.java @@ -0,0 +1,134 @@ +package xyz.fycz.myreader.ui.adapter.holder; + +import android.app.Activity; +import android.os.Handler; +import android.util.Log; +import android.widget.ImageView; +import android.widget.TextView; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.bumptech.glide.request.RequestOptions; +import xyz.fycz.myreader.R; +import xyz.fycz.myreader.application.MyApplication; +import xyz.fycz.myreader.base.adapter.ViewHolderImpl; +import xyz.fycz.myreader.webapi.callback.ResultCallback; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.util.StringHelper; +import xyz.fycz.myreader.webapi.CommonApi; +import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + +import java.util.List; + +/** + * @author fengyue + * @date 2020/10/2 10:10 + */ +public class SearchBookHolder extends ViewHolderImpl { + private ConcurrentMultiValueMap mBooks; + private Handler mHandle = new Handler(message -> { + + switch (message.what) { + case 1: + Book book = (Book) message.obj; + initOtherInfo(book); + break; + } + return false; + }); + + public SearchBookHolder(ConcurrentMultiValueMap mBooks) { + this.mBooks = mBooks; + } + + ImageView ivBookImg; + TextView tvBookName; + TextView tvDesc; + TextView tvAuthor; + TextView tvType; + TextView tvSource; + TextView tvNewestChapter; + @Override + protected int getItemLayoutId() { + return R.layout.listview_search_book_item; + } + + @Override + public void initView() { + ivBookImg = findById(R.id.iv_book_img); + tvBookName = findById(R.id.tv_book_name); + tvAuthor = findById(R.id.tv_book_author); + tvDesc = findById(R.id.tv_book_desc); + tvType = findById(R.id.tv_book_type); + tvSource = findById(R.id.tv_book_source); + tvNewestChapter = findById(R.id.tv_book_newest_chapter); + } + + + @Override + public void onBind(SearchBookBean data, int pos) { + List aBooks = mBooks.getValues(data); + int bookCount = aBooks.size(); + Book book = aBooks.get(0); + if (StringHelper.isEmpty(book.getImgUrl())){ + book.setImgUrl(""); + } + tvBookName.setText(book.getName()); + tvNewestChapter.setText(getContext().getString(R.string.newest_chapter, book.getNewestChapterTitle())); + tvAuthor.setText(book.getAuthor()); + tvSource.setText(getContext().getString(R.string.source_title_num, BookSource.fromString(book.getSource()).text, bookCount)); + tvDesc.setText(""); + tvType.setText(""); + ReadCrawler rc = ReadCrawlerUtil.getReadCrawler(book.getSource()); + if (rc instanceof BookInfoCrawler){ + if (tvBookName.getTag() == null || !(Boolean) tvBookName.getTag()) { + tvBookName.setTag(true); + } else { + initOtherInfo(book); + return; + } + Log.i(book.getName(), "initOtherInfo"); + BookInfoCrawler bic = (BookInfoCrawler) rc; + CommonApi.getBookInfo(book, bic, new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + mHandle.sendMessage(mHandle.obtainMessage(1, pos, 0, book)); + } + + @Override + public void onError(Exception e) { + tvBookName.setTag(false); + } + }); + }else { + initOtherInfo(book); + } + } + + private void initOtherInfo(Book book){ + //图片 + if (!MyApplication.isDestroy((Activity) getContext())) { + Glide.with(getContext()) + .load(book.getImgUrl()) +// .override(DipPxUtil.dip2px(getContext(), 80), DipPxUtil.dip2px(getContext(), 150)) + .error(R.mipmap.no_image) + .placeholder(R.mipmap.no_image) + //设置圆角 + .apply(RequestOptions.bitmapTransform(new RoundedCorners(8))) + .into(ivBookImg); + } + //简介 + if (book.getDesc() == null) { + tvDesc.setText(""); + }else { + tvDesc.setText("简介:" + book.getDesc()); + } + tvType.setText(book.getType()); + tvNewestChapter.setText("最新章节:" + book.getNewestChapterTitle()); + tvAuthor.setText(book.getAuthor()); + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/SourceExchangeHolder.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/SourceExchangeHolder.java new file mode 100644 index 0000000..b82931c --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/SourceExchangeHolder.java @@ -0,0 +1,40 @@ +package xyz.fycz.myreader.ui.adapter.holder; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; +import xyz.fycz.myreader.R; +import xyz.fycz.myreader.base.adapter.ViewHolderImpl; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; + +/** + * @author fengyue + * @date 2020/9/30 18:43 + */ +public class SourceExchangeHolder extends ViewHolderImpl { + TextView sourceTvTitle; + TextView sourceTvChapter; + ImageView sourceIv; + @Override + protected int getItemLayoutId() { + return R.layout.item_change_source; + } + + @Override + public void initView() { + sourceTvTitle = findById(R.id.tv_source_name); + sourceTvChapter = findById(R.id.tv_lastChapter); + sourceIv = findById(R.id.iv_checked); + } + + @Override + public void onBind(Book data, int pos) { + sourceTvTitle.setText(BookSource.fromString(data.getSource()).text); + sourceTvChapter.setText(data.getNewestChapterTitle()); + if (Boolean.parseBoolean(data.getNewestChapterId())) + sourceIv.setVisibility(View.VISIBLE); + else + sourceIv.setVisibility(View.GONE); + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/creator/APPDownloadTip.java b/app/src/main/java/xyz/fycz/myreader/ui/dialog/APPDownloadTip.java similarity index 98% rename from app/src/main/java/xyz/fycz/myreader/creator/APPDownloadTip.java rename to app/src/main/java/xyz/fycz/myreader/ui/dialog/APPDownloadTip.java index e589529..89a647c 100644 --- a/app/src/main/java/xyz/fycz/myreader/creator/APPDownloadTip.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/dialog/APPDownloadTip.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.creator; +package xyz.fycz.myreader.ui.dialog; import android.annotation.SuppressLint; @@ -9,7 +9,7 @@ import android.os.Message; import android.view.View; import androidx.appcompat.app.AppCompatActivity; import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.ui.activity.MainActivity; import xyz.fycz.myreader.ui.fragment.BookcaseFragment; diff --git a/app/src/main/java/xyz/fycz/myreader/creator/ChangeSourceDialog.java b/app/src/main/java/xyz/fycz/myreader/ui/dialog/ChangeSourceDialog.java similarity index 95% rename from app/src/main/java/xyz/fycz/myreader/creator/ChangeSourceDialog.java rename to app/src/main/java/xyz/fycz/myreader/ui/dialog/ChangeSourceDialog.java index 8715384..a490538 100644 --- a/app/src/main/java/xyz/fycz/myreader/creator/ChangeSourceDialog.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/dialog/ChangeSourceDialog.java @@ -1,17 +1,19 @@ -package xyz.fycz.myreader.creator; +package xyz.fycz.myreader.ui.dialog; import android.annotation.SuppressLint; import android.content.Context; import android.os.Handler; import android.os.Message; import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.util.ToastUtils; import xyz.fycz.myreader.webapi.crawler.*; import xyz.fycz.myreader.entity.SearchBookBean; import xyz.fycz.myreader.greendao.entity.Book; -import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; import xyz.fycz.myreader.webapi.CommonApi; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; diff --git a/app/src/main/java/xyz/fycz/myreader/creator/DialogCreator.java b/app/src/main/java/xyz/fycz/myreader/ui/dialog/DialogCreator.java similarity index 99% rename from app/src/main/java/xyz/fycz/myreader/creator/DialogCreator.java rename to app/src/main/java/xyz/fycz/myreader/ui/dialog/DialogCreator.java index e09f6b4..efab472 100644 --- a/app/src/main/java/xyz/fycz/myreader/creator/DialogCreator.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/dialog/DialogCreator.java @@ -1,6 +1,5 @@ -package xyz.fycz.myreader.creator; +package xyz.fycz.myreader.ui.dialog; -import android.app.Activity; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; @@ -18,7 +17,6 @@ import android.widget.*; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.AppCompatImageView; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.SysManager; @@ -28,7 +26,6 @@ import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.enums.ReadStyle; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.greendao.service.BookService; import xyz.fycz.myreader.util.BrightUtil; import xyz.fycz.myreader.util.IOUtils; import xyz.fycz.myreader.util.StringHelper; @@ -384,6 +381,9 @@ public class DialogCreator { intent.putExtra(APPCONST.BOOK, mBook); context.startActivity(intent);*/ }); + if ("本地书籍".equals(mBook.getType())){ + ivChangeSource.setVisibility(View.GONE); + } //换源 ivChangeSource.setOnClickListener(changeSourceListener); diff --git a/app/src/main/java/xyz/fycz/myreader/creator/MultiChoiceDialog.java b/app/src/main/java/xyz/fycz/myreader/ui/dialog/MultiChoiceDialog.java similarity index 96% rename from app/src/main/java/xyz/fycz/myreader/creator/MultiChoiceDialog.java rename to app/src/main/java/xyz/fycz/myreader/ui/dialog/MultiChoiceDialog.java index 1f42589..140334b 100644 --- a/app/src/main/java/xyz/fycz/myreader/creator/MultiChoiceDialog.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/dialog/MultiChoiceDialog.java @@ -1,11 +1,10 @@ -package xyz.fycz.myreader.creator; +package xyz.fycz.myreader.ui.dialog; import android.content.Context; import android.content.DialogInterface; import android.widget.Button; import android.widget.ListView; import androidx.appcompat.app.AlertDialog; -import xyz.fycz.myreader.R; /** * @author fengyue @@ -25,7 +24,6 @@ public class MultiChoiceDialog { int itemsCount = checkedItems.length; AlertDialog multiChoiceDialog = MyAlertDialog.build(context) .setTitle(title) - .setCancelable(false) .setMultiChoiceItems(items, checkedItems, (dialog, which, isChecked) -> { if (onMultiDialogListener != null) { onMultiDialogListener.onItemClick(dialog, which, isChecked); diff --git a/app/src/main/java/xyz/fycz/myreader/creator/MyAlertDialog.java b/app/src/main/java/xyz/fycz/myreader/ui/dialog/MyAlertDialog.java similarity index 89% rename from app/src/main/java/xyz/fycz/myreader/creator/MyAlertDialog.java rename to app/src/main/java/xyz/fycz/myreader/ui/dialog/MyAlertDialog.java index b8f748c..ad9e444 100644 --- a/app/src/main/java/xyz/fycz/myreader/creator/MyAlertDialog.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/dialog/MyAlertDialog.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.creator; +package xyz.fycz.myreader.ui.dialog; import android.content.Context; import androidx.appcompat.app.AlertDialog; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/dialog/SourceExchangeDialog.java b/app/src/main/java/xyz/fycz/myreader/ui/dialog/SourceExchangeDialog.java new file mode 100644 index 0000000..c31332c --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/ui/dialog/SourceExchangeDialog.java @@ -0,0 +1,222 @@ +package xyz.fycz.myreader.ui.dialog; + +import android.app.Activity; +import android.app.Dialog; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.AppCompatImageView; +import androidx.appcompat.widget.Toolbar; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import butterknife.BindView; +import butterknife.ButterKnife; +import xyz.fycz.myreader.R; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.model.SearchEngine; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.ui.adapter.SourceExchangeAdapter; +import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; +import xyz.fycz.myreader.widget.RefreshProgressBar; + + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Zhouas666 on 2019-04-11 + * Github: https://github.com/zas023 + *

+ * 换源dialog + */ + +public class SourceExchangeDialog extends Dialog { + + private static final String TAG = "SourceExchangeDialog"; + /*@BindView(R.id.dialog_tv_title) + TextView dialogTvTitle;*/ + @BindView(R.id.toolbar) + Toolbar toolbar; + @BindView(R.id.iv_refresh_search) + AppCompatImageView ivRefreshSearch; + @BindView(R.id.iv_stop_search) + AppCompatImageView ivStopSearch; + @BindView(R.id.rpb) + RefreshProgressBar rpb; + @BindView(R.id.dialog_rv_content) + RecyclerView dialogRvContent; + + private SearchEngine searchEngine; + private SourceExchangeAdapter mAdapter; + + private OnSourceChangeListener listener; + + private Activity mActivity; + private Book mShelfBook; + private List aBooks; + + private AlertDialog mErrorDia; + + private int sourceIndex = -1; + + /***************************************************************************/ + public SourceExchangeDialog(@NonNull Activity activity, Book bookBean) { + super(activity); + mActivity = activity; + mShelfBook = bookBean; + } + + public void setShelfBook(Book mShelfBook) { + this.mShelfBook = mShelfBook; + } + + public void setABooks(List aBooks){ + this.aBooks = aBooks; + } + + public void setSourceIndex(int sourceIndex){ + this.sourceIndex = sourceIndex; + } + + public void setOnSourceChangeListener(OnSourceChangeListener listener) { + this.listener = listener; + } + + public List getaBooks(){return aBooks;} + /*****************************Initialization********************************/ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_book_source); + ButterKnife.bind(this); + setUpWindow(); + initData(); + initClick(); + } + + @Override + protected void onStart() { + super.onStart(); + //执行业务逻辑 + if (aBooks.size() == 0) { + searchEngine.search(mShelfBook.getName(), mShelfBook.getAuthor()); + ivStopSearch.setVisibility(View.VISIBLE); + rpb.setIsAutoLoading(true); + }else { + if (mAdapter.getItemCount() == 0) { + mAdapter.addItems(aBooks); + } + } + } + + /** + * 设置Dialog显示的位置 + */ + private void setUpWindow() { + Window window = getWindow(); + WindowManager.LayoutParams lp = window.getAttributes(); + lp.width = WindowManager.LayoutParams.MATCH_PARENT; + lp.height = WindowManager.LayoutParams.WRAP_CONTENT; + lp.gravity = Gravity.CENTER; + window.setAttributes(lp); + } + + /** + * 初始化数据 + */ + private void initData() { + toolbar.setTitle(mShelfBook.getName()); + toolbar.setSubtitle(mShelfBook.getAuthor()); + //dialogTvTitle.setText(mShelfBook.getName() + "(" + mShelfBook.getAuthor() + ")"); + + if (aBooks == null) { + aBooks = new ArrayList<>(); + } + + mAdapter = new SourceExchangeAdapter(); + dialogRvContent.setLayoutManager(new LinearLayoutManager(mActivity)); + dialogRvContent.setAdapter(mAdapter); + + searchEngine = new SearchEngine(); + searchEngine.initSearchEngine(ReadCrawlerUtil.getReadCrawlers()); + } + + private void initClick() { + searchEngine.setOnSearchListener(new SearchEngine.OnSearchListener() { + @Override + public void loadMoreFinish(Boolean isAll) { + synchronized (RefreshProgressBar.class) { + rpb.setIsAutoLoading(false); + ivStopSearch.setVisibility(View.GONE); + } + } + + @Override + public void loadMoreSearchBook(ConcurrentMultiValueMap items) { + + } + + @Override + public void loadMoreSearchBook(List items) { + //确保只有一个结果 + if (items != null && items.size() != 0) { + Book bean = items.get(0); + if (bean.getSource().equals(mShelfBook.getSource())) { + bean.setNewestChapterId("true"); + sourceIndex = mAdapter.getItemSize(); + } + mAdapter.addItem(items.get(0)); + aBooks.add(bean); + } + } + + @Override + public void searchBookError(Throwable throwable) { + dismiss(); + DialogCreator.createTipDialog(mActivity, "未搜索到该书籍,书源加载失败!"); + } + }); + + mAdapter.setOnItemClickListener((view, pos) -> { + if (listener == null) return; + Book newBook = mAdapter.getItem(pos); + if (mShelfBook.getSource() == null) { + listener.onSourceChanged(newBook, pos); + searchEngine.stopSearch(); + return; + } + if (mShelfBook.getSource().equals(newBook.getSource())) return; + mShelfBook = newBook; + listener.onSourceChanged(newBook, pos); + mAdapter.getItem(pos).setNewestChapterId("true"); + if (sourceIndex > -1) + mAdapter.getItem(sourceIndex).setNewestChapterId("false"); + sourceIndex = pos; + mAdapter.notifyDataSetChanged(); + dismiss(); + }); + + ivStopSearch.setOnClickListener(v -> searchEngine.stopSearch()); + ivRefreshSearch.setOnClickListener(v -> { + searchEngine.stopSearch(); + ivStopSearch.setVisibility(View.VISIBLE); + mAdapter.clear(); + aBooks.clear(); + mAdapter.notifyDataSetChanged(); + searchEngine.search(mShelfBook.getName(), mShelfBook.getAuthor()); + }); + } + + + /**************************Interface**********************************/ + public interface OnSourceChangeListener { + void onSourceChanged(Book bean, int pos); + } + +} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookStoreFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookStoreFragment.java index bf1fb1c..6797dd3 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookStoreFragment.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookStoreFragment.java @@ -2,13 +2,9 @@ package xyz.fycz.myreader.ui.fragment; import android.os.Bundle; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.webkit.CookieManager; -import android.webkit.WebView; -import android.webkit.WebViewClient; import android.widget.ProgressBar; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.RecyclerView; @@ -17,10 +13,7 @@ import butterknife.ButterKnife; import butterknife.Unbinder; import com.scwang.smartrefresh.layout.SmartRefreshLayout; import xyz.fycz.myreader.R; -import xyz.fycz.myreader.custom.DragSortGridView; import xyz.fycz.myreader.ui.presenter.BookStorePresenter; -import xyz.fycz.myreader.util.SharedPreUtils; -import xyz.fycz.myreader.util.StringHelper; import xyz.fycz.myreader.widget.RefreshLayout; /** diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookcaseFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookcaseFragment.java index 4ec8508..320cad3 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookcaseFragment.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/BookcaseFragment.java @@ -3,7 +3,6 @@ package xyz.fycz.myreader.ui.fragment; import android.os.Build; import android.os.Bundle; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -12,8 +11,7 @@ import android.widget.*; import androidx.fragment.app.Fragment; import com.scwang.smartrefresh.layout.SmartRefreshLayout; import xyz.fycz.myreader.R; -import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.custom.DragSortGridView; +import xyz.fycz.myreader.widget.custom.DragSortGridView; import butterknife.ButterKnife; import butterknife.BindView; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindFragment.java index 5e23e2a..5f591e6 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindFragment.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindFragment.java @@ -7,9 +7,9 @@ import xyz.fycz.myreader.R; import xyz.fycz.myreader.base.BaseFragment; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.ui.activity.BookstoreActivity; -import xyz.fycz.myreader.webapi.crawler.FindCrawler; -import xyz.fycz.myreader.webapi.crawler.QB5ReadCrawler; -import xyz.fycz.myreader.webapi.crawler.find.ABC; +import xyz.fycz.myreader.webapi.crawler.base.FindCrawler; +import xyz.fycz.myreader.webapi.crawler.read.QB5ReadCrawler; +import xyz.fycz.myreader.webapi.crawler.find.QiDianMobileRank; /** * @author fengyue @@ -37,10 +37,10 @@ public class FindFragment extends BaseFragment { @Override protected void initClick() { super.initClick(); - mRlQiDianTop.setOnClickListener(v -> comeToBookstore(new ABC(false))); - mRlQiDianNSTop.setOnClickListener(v -> comeToBookstore(new ABC(true))); - mRlQiDianSort.setOnClickListener(v -> comeToBookstore(new ABC(false, true))); - mRlQiDianNSSort.setOnClickListener(v -> comeToBookstore(new ABC(true, true))); + mRlQiDianTop.setOnClickListener(v -> comeToBookstore(new QiDianMobileRank(false))); + mRlQiDianNSTop.setOnClickListener(v -> comeToBookstore(new QiDianMobileRank(true))); + mRlQiDianSort.setOnClickListener(v -> comeToBookstore(new QiDianMobileRank(false, true))); + mRlQiDianNSSort.setOnClickListener(v -> comeToBookstore(new QiDianMobileRank(true, true))); mRlQB5Store.setOnClickListener(v -> comeToBookstore(new QB5ReadCrawler())); } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java index da741f4..364afe9 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java @@ -5,7 +5,6 @@ import android.content.*; import android.os.Bundle; import android.os.Handler; import android.os.Message; -import android.widget.ArrayAdapter; import android.widget.RelativeLayout; import android.widget.TextView; import androidx.annotation.NonNull; @@ -15,12 +14,12 @@ import butterknife.BindView; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.SysManager; -import xyz.fycz.myreader.backup.BackupAndRestore; -import xyz.fycz.myreader.backup.UserService; +import xyz.fycz.myreader.model.backup.BackupAndRestore; +import xyz.fycz.myreader.model.backup.UserService; import xyz.fycz.myreader.base.BaseFragment; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.creator.MyAlertDialog; +import xyz.fycz.myreader.ui.dialog.DialogCreator; +import xyz.fycz.myreader.ui.dialog.MyAlertDialog; import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.service.BookService; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookStorePresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookStorePresenter.java index 11aa653..65f6c25 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookStorePresenter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookStorePresenter.java @@ -7,10 +7,10 @@ import android.os.Message; import android.view.View; import androidx.recyclerview.widget.LinearLayoutManager; import xyz.fycz.myreader.base.BasePresenter; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.ChangeSourceDialog; -import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.ui.dialog.ChangeSourceDialog; +import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.entity.bookstore.BookType; import xyz.fycz.myreader.entity.bookstore.RankBook; import xyz.fycz.myreader.greendao.entity.Book; @@ -20,7 +20,7 @@ import xyz.fycz.myreader.ui.adapter.BookStoreBookAdapter; import xyz.fycz.myreader.ui.adapter.BookStoreBookTypeAdapter; import xyz.fycz.myreader.ui.fragment.BookStoreFragment; import xyz.fycz.myreader.util.ToastUtils; -import xyz.fycz.myreader.webapi.crawler.find.ABC; +import xyz.fycz.myreader.webapi.crawler.find.QiDianMobileRank; import java.util.ArrayList; @@ -42,7 +42,7 @@ public class BookStorePresenter implements BasePresenter { private List bookList = new ArrayList<>(); private BookType curType; - private ABC findCrawler; + private QiDianMobileRank findCrawler; private int page = 1; @@ -86,7 +86,7 @@ public class BookStorePresenter implements BasePresenter { public void start() { mBookStoreFragment.getSrlBookList().setEnableRefresh(false); mBookStoreFragment.getSrlBookList().setEnableLoadMore(false); - findCrawler = new ABC(true); + findCrawler = new QiDianMobileRank(true); //小说列表下拉加载更多事件 mBookStoreFragment.getSrlBookList().setOnLoadMoreListener(refreshLayout -> { page++; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java index fc78970..687daac 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java @@ -22,9 +22,7 @@ import android.widget.EditText; import android.widget.PopupMenu; import androidx.appcompat.app.AlertDialog; import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; -import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -32,25 +30,24 @@ import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputLayout; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.SysManager; -import xyz.fycz.myreader.backup.BackupAndRestore; -import xyz.fycz.myreader.backup.UserService; import xyz.fycz.myreader.base.BasePresenter; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.MultiChoiceDialog; -import xyz.fycz.myreader.creator.MyAlertDialog; +import xyz.fycz.myreader.ui.dialog.MultiChoiceDialog; +import xyz.fycz.myreader.ui.dialog.MyAlertDialog; import xyz.fycz.myreader.greendao.entity.BookGroup; import xyz.fycz.myreader.greendao.service.BookGroupService; +import xyz.fycz.myreader.model.backup.BackupAndRestore; +import xyz.fycz.myreader.model.backup.UserService; import xyz.fycz.myreader.ui.activity.*; -import xyz.fycz.myreader.webapi.crawler.ReadCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; -import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.custom.DragSortGridView; +import xyz.fycz.myreader.ui.dialog.DialogCreator; +import xyz.fycz.myreader.widget.custom.DragSortGridView; import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.enums.BookcaseStyle; @@ -109,6 +106,7 @@ public class BookcasePresenter implements BasePresenter { private Runnable sendDownloadNotification;//发送通知的线程 private boolean isFirstRefresh = true;//是否首次进入刷新 private boolean isGroup; + private MainActivity.OnGroupChangeListener ogcl; public static final String CANCEL_ACTION = "cancelAction"; @@ -236,14 +234,33 @@ public class BookcasePresenter implements BasePresenter { //删除监听器 mBookcaseFragment.getmBtnDelete().setOnClickListener(v -> { - DialogCreator.createCommonDialog(mMainActivity, "批量删除书籍", - "确定要删除这些书籍吗?", true, (dialog, which) -> { - for (Book book : mBookcaseAdapter.getSelectBooks()) { - mBookService.deleteBook(book); - } - ToastUtils.showSuccess("书籍删除成功!"); - init(); - }, null); + if (!isGroup) { + DialogCreator.createCommonDialog(mMainActivity, "批量删除书籍", + "确定要删除这些书籍吗?", true, (dialog, which) -> { + for (Book book : mBookcaseAdapter.getSelectBooks()) { + mBookService.deleteBook(book); + } + ToastUtils.showSuccess("书籍删除成功!"); + init(); + }, null); + }else { + DialogCreator.createCommonDialog(mMainActivity, "批量删除/移除书籍", + "您是希望是要删除这些书籍及其所有缓存还是从分组中移除(不会删除书籍)呢?", true, + "删除书籍", "从分组中移除" ,(dialog, which) -> { + for (Book book : mBookcaseAdapter.getSelectBooks()) { + mBookService.deleteBook(book); + } + ToastUtils.showSuccess("书籍删除成功!"); + init(); + }, (dialog, which) -> { + for (Book book : mBookcaseAdapter.getSelectBooks()) { + book.setGroupId(""); + mBookService.updateEntity(book); + } + ToastUtils.showSuccess("书籍已从分组中移除!"); + init(); + }); + } }); //加入分组监听器 @@ -254,7 +271,10 @@ public class BookcasePresenter implements BasePresenter { BookGroup bookGroup = mBookGroups.get(which); ArrayList mSelectBooks = (ArrayList) mBookcaseAdapter.getSelectBooks(); for (Book book : mSelectBooks) { - book.setGroupId(bookGroup.getId()); + if (!bookGroup.getId().equals(book.getGroupId())) { + book.setGroupId(bookGroup.getId()); + book.setGroupSort(0); + } } mBookService.updateBooks(mSelectBooks); ToastUtils.showSuccess("成功将《" + mSelectBooks.get(0).getName() + "》" @@ -262,7 +282,7 @@ public class BookcasePresenter implements BasePresenter { + "加入[" + bookGroup.getName() + "]分组"); init(); } else if (which == mBookGroups.size()) { - showAddOrRenameGroupDia(false, 0); + showAddOrRenameGroupDia(false, true, 0); } }); }); @@ -272,9 +292,8 @@ public class BookcasePresenter implements BasePresenter { //获取数据 public void getData() { init(); - initBookGroups(true); if (mSetting.isRefreshWhenStart() || android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - initNoReadNum(); + mHandler.postDelayed(this::initNoReadNum, 500); } } @@ -343,7 +362,8 @@ public class BookcasePresenter implements BasePresenter { mGroupNames = new CharSequence[isAdd ? mBookGroups.size() + 1 : mBookGroups.size()]; for (int i = 0; i < mBookGroups.size(); i++) { String groupName = mBookGroups.get(i).getName(); - mGroupNames[i] = groupName.getBytes().length > 20 ? groupName.substring(0, 8) + "···" : groupName; +// mGroupNames[i] = groupName.getBytes().length > 20 ? groupName.substring(0, 8) + "···" : groupName; + mGroupNames[i] = groupName; } if (isAdd) { mGroupNames[mBookGroups.size()] = "添加分组"; @@ -369,7 +389,7 @@ public class BookcasePresenter implements BasePresenter { Thread update = new Thread(() -> { final ArrayList mChapters = (ArrayList) mChapterService.findBookAllChapterByBookId(book.getId()); final ReadCrawler mReadCrawler = ReadCrawlerUtil.getReadCrawler(book.getSource()); - CommonApi.getBookChapters(book.getChapterUrl(), mReadCrawler, new ResultCallback() { + CommonApi.getBookChapters(book.getChapterUrl(), mReadCrawler, true, new ResultCallback() { @Override public void onFinish(Object o, int code) { ArrayList chapters = (ArrayList) o; @@ -421,6 +441,10 @@ public class BookcasePresenter implements BasePresenter { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.action_change_group: + mBookcaseFragment.getmBookcasePresenter() + .showBookGroupMenu(mMainActivity.findViewById(R.id.action_change_group)); + return true; case R.id.action_edit: editBookcase(true); return true; @@ -473,8 +497,11 @@ public class BookcasePresenter implements BasePresenter { return false; } - //显示书籍分组菜单 - public void showBookGroupMenu(View view, MainActivity.OnGroupChangeListener ogcl) { + /** + * 显示书籍分组菜单 + * + */ + public void showBookGroupMenu(View view) { initBookGroups(false); PopupMenu popupMenu = new PopupMenu(mMainActivity, view, Gravity.END); popupMenu.getMenu().add(0, 0, 0, "所有书籍"); @@ -539,11 +566,11 @@ public class BookcasePresenter implements BasePresenter { initBookGroups(false); switch (which){ case 0: - showAddOrRenameGroupDia(false, 0); + showAddOrRenameGroupDia(false, false,0); break; case 1: showSelectGroupDia((dialog1, which1) -> { - showAddOrRenameGroupDia(true, which1); + showAddOrRenameGroupDia(true,false, which1); }); break; case 2: @@ -557,7 +584,7 @@ public class BookcasePresenter implements BasePresenter { /** * 添加/重命名分组对话框 */ - private void showAddOrRenameGroupDia(boolean isRename, int groupNum){ + private void showAddOrRenameGroupDia(boolean isRename, boolean isAddGroup, int groupNum){ View view = LayoutInflater.from(mMainActivity).inflate(R.layout.edit_dialog, null); TextInputLayout textInputLayout = view.findViewById(R.id.text_input_lay); EditText editText = textInputLayout.getEditText(); @@ -568,9 +595,8 @@ public class BookcasePresenter implements BasePresenter { editText.setText(oldName); } editText.requestFocus(); + InputMethodManager imm = (InputMethodManager) mMainActivity.getSystemService(Context.INPUT_METHOD_SERVICE); mHandler.postDelayed(() ->{ - InputMethodManager imm = (InputMethodManager) mMainActivity - .getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED); }, 220); AlertDialog newGroupDia = MyAlertDialog.build(mMainActivity) @@ -583,16 +609,32 @@ public class BookcasePresenter implements BasePresenter { Button posBtn = newGroupDia.getButton(AlertDialog.BUTTON_POSITIVE); posBtn.setEnabled(false); posBtn.setOnClickListener(v1 -> { - bookGroup.setName(editText.getText().toString()); + CharSequence newGroupName = editText.getText().toString(); + for (CharSequence oldGroupName : mGroupNames){ + if (oldGroupName.equals(newGroupName)){ + ToastUtils.showWarring("分组[" + newGroupName + "]已存在,无法" + (!isRename ? "添加!" : "重命名!")); + return; + } + } + bookGroup.setName(newGroupName.toString()); if (!isRename) { mBookGroupService.addBookGroup(bookGroup); }else { mBookGroupService.updateEntity(bookGroup); + SharedPreUtils spu = SharedPreUtils.getInstance(); + if (spu.getString("curBookGroupName", "").equals(oldName)){ + spu.putString("curBookGroupName", newGroupName.toString()); + ogcl.onChange(); + } } ToastUtils.showSuccess("成功" + (!isRename ? "添加分组[" : "成功将[" + oldName + "]重命名为[") + bookGroup.getName() + "]"); + imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED); newGroupDia.dismiss(); + if (isAddGroup){ + mBookcaseFragment.getmBtnAddGroup().performClick(); + } }); editText.addTextChangedListener(new TextWatcher() { @Override @@ -634,6 +676,13 @@ public class BookcasePresenter implements BasePresenter { if (sb.length() > 0){ sb.deleteCharAt(sb.lastIndexOf("、")); } + SharedPreUtils spu = SharedPreUtils.getInstance(); + if (mBookGroupService.getGroupById(spu.getString("curBookGroupId", "")) == null){ + spu.putString("curBookGroupId", ""); + spu.putString("curBookGroupName", ""); + ogcl.onChange(); + init(); + } ToastUtils.showSuccess("分组[" + sb.toString() + "]删除成功!"); }, null, null); } @@ -648,6 +697,16 @@ public class BookcasePresenter implements BasePresenter { .show(); } + //分组切换监听器 + public void addOnGroupChangeListener(MainActivity.OnGroupChangeListener ogcl){ + this.ogcl = ogcl; + } + + //是否有分组切换监听器 + public boolean hasOnGroupChangeListener(){ + return this.ogcl != null; + } + /**********************************************缓存书籍***************************************************************/ /** * 缓存所有书籍 @@ -889,6 +948,7 @@ public class BookcasePresenter implements BasePresenter { } return; } + ArrayList mBooks = (ArrayList) BookService.getInstance().getAllBooks(); if (mBooks.size() == 0) { if (!isAutoSyn) { ToastUtils.showWarring("当前书架无任何书籍,无法同步!"); diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/CatalogPresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/CatalogPresenter.java index 752a95b..912078e 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/CatalogPresenter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/presenter/CatalogPresenter.java @@ -5,9 +5,8 @@ import android.content.Intent; import android.view.View; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.base.BasePresenter; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.ui.activity.CatalogActivity; import xyz.fycz.myreader.util.ToastUtils; @@ -63,7 +62,7 @@ public class CatalogPresenter implements BasePresenter { return; } mCatalogFragment.getPbLoading().setVisibility(View.VISIBLE); - CommonApi.getBookChapters(mBook.getChapterUrl(), ReadCrawlerUtil.getReadCrawler(mBook.getSource()), + CommonApi.getBookChapters(mBook.getChapterUrl(), ReadCrawlerUtil.getReadCrawler(mBook.getSource()),false, new ResultCallback() { @Override public void onFinish(Object o, int code) { diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/ReadPresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/ReadPresenter.java index 34e696e..42ef7d5 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/ReadPresenter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/presenter/ReadPresenter.java @@ -25,16 +25,17 @@ import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.base.BasePresenter; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.common.URLCONST; -import xyz.fycz.myreader.creator.MyAlertDialog; +import xyz.fycz.myreader.ui.dialog.MyAlertDialog; +import xyz.fycz.myreader.ui.dialog.SourceExchangeDialog; import xyz.fycz.myreader.ui.activity.*; import xyz.fycz.myreader.util.*; import xyz.fycz.myreader.util.utils.ColorUtil; -import xyz.fycz.myreader.webapi.crawler.ReadCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; -import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.enums.Font; @@ -116,6 +117,10 @@ public class ReadPresenter implements BasePresenter { "覆盖", "仿真", "滑动", "滚动", "无动画" }; + private SourceExchangeDialog mSourceDialog; + + private boolean hasChangeSource; + @SuppressLint("HandlerLeak") private Handler mHandler = new Handler() { @Override @@ -214,6 +219,7 @@ public class ReadPresenter implements BasePresenter { if (SharedPreUtils.getInstance().getBoolean("isNightFS", false)) { mSetting.setDayStyle(!ColorUtil.isColorLight(mReadActivity.getColor(R.color.textPrimary))); } + //息屏时间 screenTimeOut = mSetting.getResetScreen() * 60; @@ -225,6 +231,7 @@ public class ReadPresenter implements BasePresenter { upHpbNextPage = this::upHpbNextPage; sendDownloadNotification = this::sendNotification; + notificationUtil = NotificationUtil.getInstance(); //注册广播 @@ -237,19 +244,22 @@ public class ReadPresenter implements BasePresenter { BrightUtil.setBrightness(mReadActivity, BrightUtil.progressToBright(mSetting.getBrightProgress())); } - if (!loadBook()){ + if (!loadBook()) { mReadActivity.finish(); return; } isCollected = mReadActivity.getIntent().getBooleanExtra("isCollected", true); + hasChangeSource = mReadActivity.getIntent().getBooleanExtra("hasChangeSource", false); + //当书籍Collected且书籍id不为空的时候保存上次阅读信息 if (isCollected && !StringHelper.isEmpty(mBook.getId())) { //保存上次阅读信息 SharedPreUtils.getInstance().putString("lastRead", mBook.getId()); } + mReadCrawler = ReadCrawlerUtil.getReadCrawler(mBook.getSource()); mPageLoader = mReadActivity.getSrlContent().getPageLoader(mBook, mReadCrawler, mSetting); @@ -257,14 +267,45 @@ public class ReadPresenter implements BasePresenter { mReadActivity.getPbLoading().setVisibility(View.VISIBLE); initListener(); - + //Dialog + mSourceDialog = new SourceExchangeDialog(mReadActivity, mBook); + + mSourceDialog.setOnSourceChangeListener((bean, pos) -> { + Book bookTem = new Book(mBook); + bookTem.setChapterUrl(bean.getChapterUrl()); + bookTem.setSource(bean.getSource()); + if (!StringHelper.isEmpty(bean.getImgUrl())) { + bookTem.setImgUrl(bean.getImgUrl()); + } + if (!StringHelper.isEmpty(bean.getType())) { + bookTem.setType(bean.getType()); + } + if (!StringHelper.isEmpty(bean.getDesc())){ + bookTem.setDesc(bean.getDesc()); + } + if (isCollected) { + mBookService.updateBook(mBook, bookTem); + } + mBook = bookTem; + mSettingDialog.dismiss(); + Intent intent = new Intent(mReadActivity, ReadActivity.class) + .putExtra(APPCONST.BOOK, mBook) + .putExtra("hasChangeSource", true); + if (!isCollected){ + intent.putExtra("isCollected", false); + } + mReadActivity.finish(); + mReadActivity.startActivity(intent); + }); getData(); } + /** * 进入阅读书籍有三种方式: - * 1、直接从书架进入,这种方式书籍一定Collected - * 2、从外部打开txt文件,这种方式会添加进书架 - * 3、从快捷图标打开上次阅读书籍 + * 1、直接从书架进入,这种方式书籍一定Collected + * 2、从外部打开txt文件,这种方式会添加进书架 + * 3、从快捷图标打开上次阅读书籍 + * * @return 是否加载成功 */ private boolean loadBook() { @@ -283,15 +324,15 @@ public class ReadPresenter implements BasePresenter { //路径为空,说明不是直接打开txt文件 mBook = (Book) mReadActivity.getIntent().getSerializableExtra(APPCONST.BOOK); //mBook为空,说明是从快捷方式启动 - if (mBook == null){ + if (mBook == null) { String bookId = SharedPreUtils.getInstance().getString("lastRead", ""); - if ("".equals(bookId)){//没有上次阅读信息 + if ("".equals(bookId)) {//没有上次阅读信息 ToastUtils.showWarring("当前没有阅读任何书籍,无法加载上次阅读书籍!"); mReadActivity.finish(); return false; - }else {//有信息 + } else {//有信息 mBook = mBookService.getBookById(bookId); - if (mBook == null){//上次阅读的书籍不存在 + if (mBook == null) {//上次阅读的书籍不存在 ToastUtils.showWarring("上次阅读书籍已不存在/移除书架,无法加载!"); mReadActivity.finish(); return false; @@ -324,6 +365,7 @@ public class ReadPresenter implements BasePresenter { mSettingDialog.dismiss(); mReadActivity.onBackPressed(); }, v -> {//换源 + mSourceDialog.show(); }, v -> {//刷新 isPrev = false; if (!"本地书籍".equals(mBook.getType())) { @@ -718,7 +760,7 @@ public class ReadPresenter implements BasePresenter { } }); } else { - CommonApi.getBookChapters(mBook.getChapterUrl(), mReadCrawler, new ResultCallback() { + CommonApi.getBookChapters(mBook.getChapterUrl(), mReadCrawler,false, new ResultCallback() { @Override public void onFinish(Object o, int code) { ArrayList chapters = (ArrayList) o; @@ -762,6 +804,9 @@ public class ReadPresenter implements BasePresenter { mHandler.sendMessage(mHandler.obtainMessage(1)); return; } + if (hasChangeSource){ + mBookService.matchHistoryChapterPos(mBook, mChapters); + } getChapterContent(mChapters.get(mBook.getHisttoryChapterNum()), new ResultCallback() { @Override public void onFinish(Object o, int code) { @@ -840,7 +885,7 @@ public class ReadPresenter implements BasePresenter { e.printStackTrace(); } }*/ - if (SysManager.getSetting().getCatheGap() != 0){ + if (SysManager.getSetting().getCatheGap() != 0) { downloadInterval = SysManager.getSetting().getCatheGap(); } //计算断点章节 diff --git a/app/src/main/java/xyz/fycz/myreader/util/DownloadMangerUtils.java b/app/src/main/java/xyz/fycz/myreader/util/DownloadMangerUtils.java index aa1d108..f8f65f1 100644 --- a/app/src/main/java/xyz/fycz/myreader/util/DownloadMangerUtils.java +++ b/app/src/main/java/xyz/fycz/myreader/util/DownloadMangerUtils.java @@ -21,7 +21,7 @@ import java.util.HashMap; import java.util.Map; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.DialogCreator; +import xyz.fycz.myreader.ui.dialog.DialogCreator; import static android.app.DownloadManager.Request.VISIBILITY_HIDDEN; diff --git a/app/src/main/java/xyz/fycz/myreader/util/EmailUtils.java b/app/src/main/java/xyz/fycz/myreader/util/EmailUtils.java deleted file mode 100644 index 826a8a7..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/EmailUtils.java +++ /dev/null @@ -1,20 +0,0 @@ -package xyz.fycz.myreader.util; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - - - -public class EmailUtils { - /** - * 检验邮箱格式 - * @param email - * @return - */ - public static boolean isMatched(String email){ - String check = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"; - Pattern regex = Pattern.compile(check); - Matcher matcher = regex.matcher(email); - return matcher.matches(); - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/FormatDateUtils.java b/app/src/main/java/xyz/fycz/myreader/util/FormatDateUtils.java deleted file mode 100644 index 9f6eaff..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/FormatDateUtils.java +++ /dev/null @@ -1,58 +0,0 @@ -package xyz.fycz.myreader.util; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.GregorianCalendar; - - - -public class FormatDateUtils { - private static Date date; - private static SimpleDateFormat format; - - private static SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); - - public static String formatDateTime(long time) { - if (0 == time) { - return ""; - } - return mDateFormat.format(new Date(time)); - } - - public static String long2date(String str, String formater){ - return formateLongTime(long2String(str),formater); - } - - public static String long2date(long times, String formater){ - return formateLongTime(times,formater); - } - - - private static String formateLongTime(long times, String formater){ - date=new Date(times); - GregorianCalendar gc = new GregorianCalendar(); - gc.setTime(date); - format = new SimpleDateFormat(formater); - String sb=format.format(gc.getTime()); - return sb; - } - - - - public static long long2String(String str){ - long time = 0; - try { - time = mDateFormat.parse(str).getTime(); - } catch (ParseException e) { - e.printStackTrace(); - } - return time; - } - - public static long day2long(long times){ - long day = times / (1000*60*60*24); - return day; - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/HttpUtil.java b/app/src/main/java/xyz/fycz/myreader/util/HttpUtil.java index 486a8c2..fdb169f 100644 --- a/app/src/main/java/xyz/fycz/myreader/util/HttpUtil.java +++ b/app/src/main/java/xyz/fycz/myreader/util/HttpUtil.java @@ -8,9 +8,9 @@ import com.google.gson.Gson; import okhttp3.*; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.TrustAllCerts; -import xyz.fycz.myreader.callback.HttpCallback; -import xyz.fycz.myreader.callback.JsonCallback; -import xyz.fycz.myreader.callback.URLConnectionCallback; +import xyz.fycz.myreader.webapi.callback.HttpCallback; +import xyz.fycz.myreader.webapi.callback.JsonCallback; +import xyz.fycz.myreader.webapi.callback.URLConnectionCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.common.URLCONST; import xyz.fycz.myreader.entity.JsonModel; @@ -43,7 +43,6 @@ public class HttpUtil { private static SSLSocketFactory createSSLSocketFactory() { SSLSocketFactory ssfFactory = null; - try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom()); @@ -54,10 +53,12 @@ public class HttpUtil { return ssfFactory; } - private static synchronized OkHttpClient getOkHttpClient() { + public static synchronized OkHttpClient getOkHttpClient() { if (mClient == null) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); - builder.connectTimeout(30, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS); + builder.connectTimeout(5, TimeUnit.SECONDS) + .readTimeout(15, TimeUnit.SECONDS) + .writeTimeout(15, TimeUnit.SECONDS); builder.sslSocketFactory(createSSLSocketFactory()); builder.hostnameVerifier((hostname, session) -> true); mClient = builder @@ -206,7 +207,7 @@ public class HttpUtil { }).start(); } - public static void sendGetRequest_okHttp(final String address, final HttpCallback callback) { + public static void sendGetRequest_okHttp(final String address, boolean isRefresh, final HttpCallback callback) { MyApplication.getApplication().newThread(() -> { /* HttpURLConnection connection = null; try { diff --git a/app/src/main/java/xyz/fycz/myreader/util/ImageUtil.java b/app/src/main/java/xyz/fycz/myreader/util/ImageUtil.java deleted file mode 100644 index 89b22c3..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/ImageUtil.java +++ /dev/null @@ -1,272 +0,0 @@ -package xyz.fycz.myreader.util; - -import android.content.Context; -import android.graphics.*; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import xyz.fycz.myreader.R; -import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.callback.ResultCallback; - -import static xyz.fycz.myreader.util.DipPxUtil.dp2px; - -/** - * @author fengyue - * @date 2020/8/13 7:56 - */ -public class ImageUtil { - /** - * 设置水印图片在左上角 - * @param context - * @param src - * @param watermark - * @param paddingLeft - * @param paddingTop - * @return - */ - public static Bitmap createWaterMaskLeftTop( - Context context, Bitmap src, Bitmap watermark, - int paddingLeft, int paddingTop) { - return createWaterMaskBitmap(src, watermark, - dp2px(context, paddingLeft), dp2px(context, paddingTop)); - } - - private static Bitmap createWaterMaskBitmap(Bitmap src, Bitmap watermark, - int paddingLeft, int paddingTop) { - if (src == null) { - return null; - } - int width = src.getWidth(); - int height = src.getHeight(); - //创建一个bitmap - Bitmap newb = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图 - //将该图片作为画布 - Canvas canvas = new Canvas(newb); - //在画布 0,0坐标上开始绘制原始图片 - canvas.drawBitmap(src, 0, 0, null); - //在画布上绘制水印图片 - canvas.drawBitmap(watermark, paddingLeft, paddingTop, null); - // 保存 - canvas.save(); - // 存储 - canvas.restore(); - return newb; - } - - /** - * 设置水印图片在右下角 - * @param context - * @param src - * @param watermark - * @param paddingRight - * @param paddingBottom - * @return - */ - public static Bitmap createWaterMaskRightBottom( - Context context, Bitmap src, Bitmap watermark, - int paddingRight, int paddingBottom) { - return createWaterMaskBitmap(src, watermark, - src.getWidth() - watermark.getWidth() - dp2px(context, paddingRight), - src.getHeight() - watermark.getHeight() - dp2px(context, paddingBottom)); - } - - /** - * 设置水印图片到右上角 - * @param context - * @param src - * @param watermark - * @param paddingRight - * @param paddingTop - * @return - */ - public static Bitmap createWaterMaskRightTop( - Context context, Bitmap src, Bitmap watermark, - int paddingRight, int paddingTop) { - return createWaterMaskBitmap( src, watermark, - src.getWidth() - watermark.getWidth() - dp2px(context, paddingRight), - dp2px(context, paddingTop)); - } - - /** - * 设置水印图片到左下角 - * @param context - * @param src - * @param watermark - * @param paddingLeft - * @param paddingBottom - * @return - */ - public static Bitmap createWaterMaskLeftBottom( - Context context, Bitmap src, Bitmap watermark, - int paddingLeft, int paddingBottom) { - return createWaterMaskBitmap(src, watermark, dp2px(context, paddingLeft), - src.getHeight() - watermark.getHeight() - dp2px(context, paddingBottom)); - } - - /** - * 设置水印图片到中间 - * @param src - * @param src - * @param watermark - * @return - */ - public static Bitmap createWaterMaskCenter(Bitmap src, Bitmap watermark) { - return createWaterMaskBitmap(src, watermark, - (src.getWidth() - watermark.getWidth()) / 2, - (src.getHeight() - watermark.getHeight()) / 2); - } - - /** - * 给图片添加文字到左上角 - * @param context - * @param bitmap - * @param text - * @return - */ - public static Bitmap drawTextToLeftTop(Context context, Bitmap bitmap, String text, - int size, int color, int paddingLeft, int paddingTop) { - Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - paint.setColor(color); - paint.setTextSize(dp2px(context, size)); - Rect bounds = new Rect(); - paint.getTextBounds(text, 0, text.length(), bounds); - return drawTextToBitmap(context, bitmap, text, paint, bounds, - dp2px(context, paddingLeft), - dp2px(context, paddingTop) + bounds.height()); - } - - /** - * 绘制文字到右下角 - * @param context - * @param bitmap - * @param text - * @param size - * @param color - * @param paddingRight - * @param paddingBottom - * @return - */ - public static Bitmap drawTextToRightBottom(Context context, Bitmap bitmap, String text, - int size, int color, int paddingRight, int paddingBottom) { - Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - paint.setColor(color); - paint.setTextSize(dp2px(context, size)); - Rect bounds = new Rect(); - paint.getTextBounds(text, 0, text.length(), bounds); - return drawTextToBitmap(context, bitmap, text, paint, bounds, - bitmap.getWidth() - bounds.width() - dp2px(context, paddingRight), - bitmap.getHeight() - dp2px(context, paddingBottom)); - } - - /** - * 绘制文字到右上方 - * @param context - * @param bitmap - * @param text - * @param size - * @param color - * @param paddingRight - * @param paddingTop - * @return - */ - public static Bitmap drawTextToRightTop(Context context, Bitmap bitmap, String text, - int size, int color, int paddingRight, int paddingTop) { - Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - paint.setColor(color); - paint.setTextSize(dp2px(context, size)); - Rect bounds = new Rect(); - paint.getTextBounds(text, 0, text.length(), bounds); - return drawTextToBitmap(context, bitmap, text, paint, bounds, - bitmap.getWidth() - bounds.width() - dp2px(context, paddingRight), - dp2px(context, paddingTop) + bounds.height()); - } - - /** - * 绘制文字到左下方 - * @param context - * @param bitmap - * @param text - * @param size - * @param color - * @param paddingLeft - * @param paddingBottom - * @return - */ - public static Bitmap drawTextToLeftBottom(Context context, Bitmap bitmap, String text, - int size, int color, int paddingLeft, int paddingBottom) { - Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - paint.setColor(color); - paint.setTextSize(dp2px(context, size)); - Rect bounds = new Rect(); - paint.getTextBounds(text, 0, text.length(), bounds); - return drawTextToBitmap(context, bitmap, text, paint, bounds, - dp2px(context, paddingLeft), - bitmap.getHeight() - dp2px(context, paddingBottom)); - } - - /** - * 绘制文字到中间 - * @param context - * @param bitmap - * @param text - * @param size - * @param color - * @return - */ - public static Bitmap drawTextToCenter(Context context, Bitmap bitmap, String text, - int size, int color) { - Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - paint.setColor(color); - paint.setTextSize(dp2px(context, size)); - Rect bounds = new Rect(); - paint.getTextBounds(text, 0, text.length(), bounds); - return drawTextToBitmap(context, bitmap, text, paint, bounds, - (bitmap.getWidth() - bounds.width()) / 2, - (bitmap.getHeight() + bounds.height()) / 2); - } - - //图片上绘制文字 - private static Bitmap drawTextToBitmap(Context context, Bitmap bitmap, String text, - Paint paint, Rect bounds, int paddingLeft, int paddingTop) { - android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig(); - - paint.setDither(true); // 获取跟清晰的图像采样 - paint.setFilterBitmap(true);// 过滤一些 -// paint.setFakeBoldText(true); //加粗 - if (bitmapConfig == null) { - bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888; - } - - bitmap = bitmap.copy(bitmapConfig, true); - Canvas canvas = new Canvas(bitmap); - canvas.drawText(text, paddingLeft, paddingTop, paint); - return bitmap; - } - - /** - * 缩放图片 - * @param src - * @param w - * @param h - * @return - */ - public static Bitmap scaleWithWH(Bitmap src, double w, double h) { - if (w == 0 || h == 0 || src == null) { - return src; - } else { - // 记录src的宽高 - int width = src.getWidth(); - int height = src.getHeight(); - // 创建一个matrix容器 - Matrix matrix = new Matrix(); - // 计算缩放比例 - float scaleWidth = (float) (w / width); - float scaleHeight = (float) (h / height); - // 开始缩放 - matrix.postScale(scaleWidth, scaleHeight); - // 创建缩放后的图片 - return Bitmap.createBitmap(src, 0, 0, width, height, matrix, true); - } - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/ListViewHeight.java b/app/src/main/java/xyz/fycz/myreader/util/ListViewHeight.java deleted file mode 100644 index b2ac730..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/ListViewHeight.java +++ /dev/null @@ -1,157 +0,0 @@ -package xyz.fycz.myreader.util; - -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Message; -import android.view.View; -import android.view.ViewGroup; -import android.widget.GridView; -import android.widget.ListAdapter; -import android.widget.ListView; - -import xyz.fycz.myreader.base.BaseActivity; - -import java.lang.reflect.Field; - - - -public class ListViewHeight { - private static HandlerThread thread = new HandlerThread("listview"); - private static int totalHeight = 0; - static { - thread.start(); - } - private static Handler handler = new Handler(thread.getLooper()){ - @Override - public void handleMessage(Message msg) { - switch (msg.what){ - case 1: - - break; - } - } - }; - - /** - * 计算listview的高度 - * @param listView - * @return - */ - public static int setListViewHeightBasedOnChildren(final ListView listView) { - ListAdapter listAdapter = listView.getAdapter(); - if (listAdapter == null) { - // pre-condition - return 0; - } - int totalHeight = 0; - for (int i = 0; i < listAdapter.getCount(); i++) { - View listItem = listAdapter.getView(i, null, listView); - listItem.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), - View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); -// listItem.measure(0, 0); - totalHeight += listItem.getMeasuredHeight(); - } - final ViewGroup.LayoutParams params = listView.getLayoutParams(); - params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); -// MyApplication.getApplication().runOnUiThread(new Runnable() { -// @Override -// public void run() { - listView.setLayoutParams(params); -// } -// }); - - return totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); - } - - - - /** - * 日期gridview的高度 - * @param gridView - * @return - */ - public static int setDateGridViewHeightBasedOnChildren(GridView gridView) { - ListAdapter listAdapter = gridView.getAdapter(); - if (listAdapter == null) { - // pre-condition - return 0; - } - int totalHeight = 0; - for (int i = 0; i < (listAdapter.getCount()/7); i++) { - View listItem = listAdapter.getView(i, null, gridView); - listItem.measure(0, 0); - totalHeight += listItem.getMeasuredHeight(); - } - ViewGroup.LayoutParams params = gridView.getLayoutParams(); - params.height = totalHeight + (1 * (listAdapter.getCount()/7 - 1)); - gridView.setLayoutParams(params); - return totalHeight + (1 * (listAdapter.getCount()/7 - 1)); - } - - /** - * 计算gridview的高度 - * @param gridView - */ - public static void setGridViewHeightBasedOnChildren(GridView gridView) { - // 获取GridView对应的Adapter - ListAdapter listAdapter = gridView.getAdapter(); - if (listAdapter == null) { - return; - } - int rows; - int columnWidths; - int columns=0; - int horizontalBorderHeight = 0; - int verticalBorderHeight = 0; - - Class clazz=gridView.getClass(); - try { - //利用反射,取得横向分割线高度 - Field vertical=clazz.getDeclaredField("mVerticalSpacing"); - vertical.setAccessible(true); - verticalBorderHeight =(Integer)vertical.get(gridView); - - //利用反射,取得纵向分割线高度 - Field horizontalSpacing=clazz.getDeclaredField("mRequestedHorizontalSpacing"); - horizontalSpacing.setAccessible(true); - horizontalBorderHeight=(Integer)horizontalSpacing.get(gridView); - - //利用反射,取得每行显示的个数 - Field column=clazz.getDeclaredField("mRequestedNumColumns"); - column.setAccessible(true); - columns=(Integer)column.get(gridView); - - if(columns == -1 || columns == 0){ - Field columnWidth = clazz.getDeclaredField("mRequestedColumnWidth"); - columnWidth.setAccessible(true); - columnWidths = (Integer)columnWidth.get(gridView); - int pad = gridView.getPaddingLeft() * 2; - int width = BaseActivity.width - pad * 2; - columns = width / (columnWidths /*+ horizontalBorderHeight*/); - if(horizontalBorderHeight * (columns - 1) + columnWidths * columns > width){ - columns --; - } - } - - } catch (Exception e) { - // TODO: handle exception - e.printStackTrace(); - } - //判断数据总数除以每行个数是否整除。不能整除代表有多余,需要加一行 - if(listAdapter.getCount()%columns > 0){ - rows=listAdapter.getCount()/columns+1; - }else { - rows=listAdapter.getCount()/columns; - } - int totalHeight = 0; - for (int i = 0; i < rows; i++) { //只计算每项高度*行数 - View listItem = listAdapter.getView(i, null, gridView); - listItem.measure(0, 0); // 计算子项View 的宽高 - totalHeight += listItem.getMeasuredHeight(); // 统计所有子项的总高度 - } - ViewGroup.LayoutParams params = gridView.getLayoutParams(); - params.height = totalHeight + gridView.getPaddingTop() + + gridView.getPaddingBottom() + verticalBorderHeight * (rows-1);//最后加上分割线总高度 - gridView.setLayoutParams(params); - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/NotifyHelper.java b/app/src/main/java/xyz/fycz/myreader/util/NotifyHelper.java deleted file mode 100644 index d924ba6..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/NotifyHelper.java +++ /dev/null @@ -1,69 +0,0 @@ -package xyz.fycz.myreader.util; - -import android.app.NotificationManager; -import android.content.Context; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - - -public class NotifyHelper { - - private static NotificationManager mNotificationManager; - private static Map mNotifyId = new HashMap(); - private static ArrayList mCurrentConvIds = new ArrayList(); - - public static void init(Context context){ - mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); - - } - - public static int createNotifyId(String convId) { - if (!mNotifyId.containsKey(convId)) { - for (int i = 0; i < 1000; i++) { - if (!mNotifyId.containsValue(i)) { - mNotifyId.put(convId, i); - return i; - } - } - }else { - return (int)mNotifyId.get(convId); - } - return -1; - } - - public static void closeNotification(String convId){ - //关闭通知 - int notifyId = getNotifyId(convId); - if(notifyId != -1){ - mNotificationManager.cancel(notifyId); - mNotifyId.remove(convId); - } - - } - - public static int getNotifyId(String convId){ - if(mNotifyId.get(convId) == null){ - return -1; - }else { - return (int)mNotifyId.get(convId); - } - - } - - public static boolean isOpenConv(String convId){ - return mCurrentConvIds.contains(convId); - } - - public static void addCurrentConv(String convId){ - if(!mCurrentConvIds.contains(convId)){ - mCurrentConvIds.add(convId); - } - } - - public static void removeCurrenConv(String convId){ - mCurrentConvIds.remove(convId); - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/PermissionHelper.java b/app/src/main/java/xyz/fycz/myreader/util/PermissionHelper.java deleted file mode 100644 index 83c0f2b..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/PermissionHelper.java +++ /dev/null @@ -1,149 +0,0 @@ -package xyz.fycz.myreader.util; - -import android.Manifest; -import android.content.Context; -import android.content.pm.PackageManager; -import android.os.Build; - -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; - - - -public class PermissionHelper { - - /** - * 设备信息读取权限 - * @param context - * @return - */ - public static boolean isREAD_PHONE_STATE(Context context) { - boolean permission = false; - if (Build.VERSION.SDK_INT >= 23) { - int checkReadPhoneStatePermission = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE); - if (checkReadPhoneStatePermission != PackageManager.PERMISSION_GRANTED) { - // 弹出对话框接收权限 - ActivityCompat.requestPermissions((AppCompatActivity) context, new String[]{android.Manifest.permission.READ_PHONE_STATE}, 1); - ToastUtils.showWarring("当前应用未拥读取设备状态权限"); - } else if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { - // 弹出对话框接收权限 - ActivityCompat.requestPermissions((AppCompatActivity) context, new String[]{android.Manifest.permission.READ_PHONE_STATE}, 1); - ToastUtils.showWarring("当前应用未拥读取设备状态权限"); - } else { - permission = true; - } - } else { - permission = true; - } - return permission; - } - - /** - * 蓝牙设备权限 - * @param context - * @return - */ - public static boolean isACCESS_COARSE_LOCATION(Context context) { - boolean permission = false; - if (Build.VERSION.SDK_INT >= 23) { - int checkReadPhoneStatePermission = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION); - if (checkReadPhoneStatePermission != PackageManager.PERMISSION_GRANTED) { - // 弹出对话框接收权限 - ActivityCompat.requestPermissions((AppCompatActivity) context, new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION}, 1); - ToastUtils.showWarring("当前应用未拥有蓝牙设备使用权限"); - } else if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - // 弹出对话框接收权限 - ActivityCompat.requestPermissions((AppCompatActivity) context, new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION}, 1); - ToastUtils.showWarring("当前应用未拥有蓝牙设备使用权限"); - } else { - permission = true; - } - } else { - permission = true; - } - return permission; - } - - - /** - * 文件读写权限 - * @param context - * @return - */ - public static boolean isWRPermission(Context context) { - boolean permission = false; - if (Build.VERSION.SDK_INT >= 23) { - int checkReadPhoneStatePermission = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE); - if (checkReadPhoneStatePermission != PackageManager.PERMISSION_GRANTED) { - // 弹出对话框接收权限 - ActivityCompat.requestPermissions((AppCompatActivity) context, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); - ToastUtils.showWarring("当前应用未拥有存储设备读写权限"); - } else if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - // 弹出对话框接收权限 - ActivityCompat.requestPermissions((AppCompatActivity) context, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); - ToastUtils.showWarring("当前应用未拥有存储设备读写权限"); - } else { - permission = true; - } - } else { - permission = true; - } - return permission; - } - - /** - * 声音设备权限 - * @param context - * @return - */ - public static boolean isAudioPermission(Context context) { - boolean permission = false; - if (Build.VERSION.SDK_INT >= 23) { - int checkReadPhoneStatePermission = ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO); - if (checkReadPhoneStatePermission != PackageManager.PERMISSION_GRANTED) { - // 弹出对话框接收权限 - ActivityCompat.requestPermissions((AppCompatActivity) context, new String[]{android.Manifest.permission.RECORD_AUDIO}, 1); - ToastUtils.showWarring("当前应用未拥有音频录制权限"); - } else if (ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { - // 弹出对话框接收权限 - ActivityCompat.requestPermissions((AppCompatActivity) context, new String[]{android.Manifest.permission.RECORD_AUDIO}, 1); - ToastUtils.showWarring("当前应用未拥有音频录制权限"); - } else { - permission = true; - } - } else { - permission = true; - } - return permission; - } - - /** - * 摄像头权限 - * @param context - * @return - */ - public static boolean isCameraPermission(Context context) { - boolean permission = false; - if (Build.VERSION.SDK_INT >= 23) { - int checkReadPhoneStatePermission = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA); - if (checkReadPhoneStatePermission != PackageManager.PERMISSION_GRANTED) { - // 弹出对话框接收权限 - ActivityCompat.requestPermissions((AppCompatActivity) context, new String[]{android.Manifest.permission.CAMERA}, 1); - ToastUtils.showWarring("当前应用未拥有调用摄像头权限"); - } else if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { - // 弹出对话框接收权限 - ActivityCompat.requestPermissions((AppCompatActivity) context, new String[]{android.Manifest.permission.CAMERA}, 1); - ToastUtils.showWarring("当前应用未拥有调用摄像头权限"); - } else { - permission = true; - } - } else { - permission = true; - } - return permission; - } - - - -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/PermissionsChecker.java b/app/src/main/java/xyz/fycz/myreader/util/PermissionsChecker.java index ee78344..e783f0c 100644 --- a/app/src/main/java/xyz/fycz/myreader/util/PermissionsChecker.java +++ b/app/src/main/java/xyz/fycz/myreader/util/PermissionsChecker.java @@ -4,9 +4,7 @@ import android.content.Context; import android.content.pm.PackageManager; import androidx.core.content.ContextCompat; -/** - * Created by newbiechen on 2017/10/8. - */ + public class PermissionsChecker { private final Context mContext; diff --git a/app/src/main/java/xyz/fycz/myreader/util/PingUtil.java b/app/src/main/java/xyz/fycz/myreader/util/PingUtil.java deleted file mode 100644 index 07fffc5..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/PingUtil.java +++ /dev/null @@ -1,31 +0,0 @@ -package xyz.fycz.myreader.util; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; - - - -public class PingUtil { - - public static boolean ping(String host, int port) { - if (port == 0) port = 80; - - Socket connect = new Socket(); - try { - connect.connect(new InetSocketAddress(host, port), 10 * 1000); - return connect.isConnected(); - } catch (IOException e) { - e.printStackTrace(); - }finally{ - try { - connect.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - return false; - } - - -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/QRCodeUtil.java b/app/src/main/java/xyz/fycz/myreader/util/QRCodeUtil.java deleted file mode 100644 index 54e5be4..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/QRCodeUtil.java +++ /dev/null @@ -1,123 +0,0 @@ -package xyz.fycz.myreader.util; - - -import android.graphics.Bitmap; -import android.graphics.Canvas; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.qrcode.QRCodeWriter; -import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; -import xyz.fycz.myreader.application.MyApplication; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * 二维码生成工具类 - */ -public class QRCodeUtil { - /** - * 生成二维码Bitmap - * - * @param content 内容 - * @param widthPix 图片宽度 - * @param heightPix 图片高度 - * @param logoBm 二维码中心的Logo图标(可以为null) - * @param filePath 用于存储二维码图片的文件路径 - * @return 生成二维码及保存文件是否成功 - */ - public static boolean createQRImage(String content, int widthPix, int heightPix, Bitmap logoBm, String filePath) { - try { - if (content == null || "".equals(content)) { - return false; - } - - //配置参数 - Map hints = new HashMap<>(); - hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); - //容错级别 - hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); - //设置空白边距的宽度 -// hints.put(EncodeHintType.MARGIN, 2); //default is 4 - - // 图像数据转换,使用了矩阵转换 - BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, widthPix, heightPix, hints); - int[] pixels = new int[widthPix * heightPix]; - // 下面这里按照二维码的算法,逐个生成二维码的图片, - // 两个for循环是图片横列扫描的结果 - for (int y = 0; y < heightPix; y++) { - for (int x = 0; x < widthPix; x++) { - if (bitMatrix.get(x, y)) { - pixels[y * widthPix + x] = 0xff000000; - } else { - pixels[y * widthPix + x] = 0xffffffff; - } - } - } - - // 生成二维码图片的格式,使用ARGB_8888 - Bitmap bitmap = Bitmap.createBitmap(widthPix, heightPix, Bitmap.Config.ARGB_8888); - bitmap.setPixels(pixels, 0, widthPix, 0, 0, widthPix, heightPix); - - if (logoBm != null) { - bitmap = addLogo(bitmap, logoBm); - } - - //必须使用compress方法将bitmap保存到文件中再进行读取。直接返回的bitmap是没有任何压缩的,内存消耗巨大! - FileOutputStream fos = MyApplication.getApplication().openFileOutput(filePath, MyApplication.getApplication().MODE_PRIVATE); - return bitmap != null && bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); - } catch (WriterException | IOException e) { - e.printStackTrace(); - } - return false; - } - - /** - * 在二维码中间添加Logo图案 - */ - private static Bitmap addLogo(Bitmap src, Bitmap logo) { - if (src == null) { - return null; - } - - if (logo == null) { - return src; - } - - //获取图片的宽高 - int srcWidth = src.getWidth(); - int srcHeight = src.getHeight(); - int logoWidth = logo.getWidth(); - int logoHeight = logo.getHeight(); - - if (srcWidth == 0 || srcHeight == 0) { - return null; - } - - if (logoWidth == 0 || logoHeight == 0) { - return src; - } - - //logo大小为二维码整体大小的1/5 - float scaleFactor = srcWidth * 1.0f / 5 / logoWidth; - Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888); - try { - Canvas canvas = new Canvas(bitmap); - canvas.drawBitmap(src, 0, 0, null); - canvas.scale(scaleFactor, scaleFactor, srcWidth / 2, srcHeight / 2); - canvas.drawBitmap(logo, (srcWidth - logoWidth) / 2, (srcHeight - logoHeight) / 2, null); - canvas.save(); - canvas.restore(); - } catch (Exception e) { - bitmap = null; - e.getStackTrace(); - } - return bitmap; - } - -} \ No newline at end of file diff --git a/app/src/main/java/xyz/fycz/myreader/util/SharedPreferencesUtils.java b/app/src/main/java/xyz/fycz/myreader/util/SharedPreferencesUtils.java deleted file mode 100644 index da7f381..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/SharedPreferencesUtils.java +++ /dev/null @@ -1,137 +0,0 @@ -package xyz.fycz.myreader.util; - -import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.preference.PreferenceManager; -import xyz.fycz.myreader.application.MyApplication; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -public class SharedPreferencesUtils { - - private static Editor mEditor; - - private SharedPreferences mSharedPreferences; - - private static SharedPreferencesUtils mSharedPreferencesUtils; - - public static SharedPreferencesUtils getInstance() { - if(mSharedPreferencesUtils == null) { - mSharedPreferencesUtils = new SharedPreferencesUtils(MyApplication.getmContext(), - "FYReaderShare"); - } - return mSharedPreferencesUtils; - } - /** - * - * @param context - */ - public SharedPreferencesUtils(Context context){ - mSharedPreferences = PreferenceManager - .getDefaultSharedPreferences(context); - mEditor = mSharedPreferences.edit(); - } - /** - * - * @param context - * @param fileName - */ - public SharedPreferencesUtils(Context context, String fileName){ - mSharedPreferences = context - .getSharedPreferences(fileName, Context.MODE_PRIVATE); - mEditor = mSharedPreferences.edit(); - } - - /** - * 设置通知公告是否已被查看 - * @param key - * @param flag - */ - public void setNoticeFlag(String key, boolean flag) { - mEditor.putBoolean(key, flag); - mEditor.commit(); - } - - /** - * 判断在该机该用户的通知公告是否已被查看 - * @param key - * @return - */ - public boolean isNoticeFlag(String key){ - return mSharedPreferences.getBoolean(key,false); - } - - - /** - * 保存数据 - * @param key 键值 - * @param news 需要保存的数据 - */ - public void save(String key, String news) { - Set values = null; - //获取或创建key,如果xml文件中含有key - if(mSharedPreferences.contains(key)){ - //将数据存储到集合里 - values = mSharedPreferences.getStringSet(key, null); - //删除xml文件中key,并提交 - mEditor.remove(key).commit(); - }else{//如果xml文件中没有key - values = new HashSet(); - } - //将新的数据添加到集合中 - values.add(news); - //将集合保存到偏好设置中 - mEditor.putStringSet(key, values); - //提交 - mEditor.commit(); - } - - /** - * 清空数据 - */ - public void clear(){ - mEditor.clear(); - mEditor.commit(); - } - /** - * 获取数据 - * @param key 键值 - * @return 返回一个字符串 - */ - public List query(String key){ - //创建StringBuffer对象,用来存储从偏好设置中获取的数据 - List list = new ArrayList(); - //获取xml中对应key的值 - Set values = mSharedPreferences.getStringSet(key, null); - //判断该数据是否为空,如果不为空,则 - if(key != null && values != null){ - //遍历集合 - Iterator iterator = values.iterator(); - while(iterator.hasNext()){ - //将数据添加到StringBuffer - list.add(iterator.next()); - } - } - return list; - } - - /** - * 设置是否是第一次登录 - * @param values - */ - public void setFirstEntry(int values){ - mEditor.putInt("first_entry", values); - mEditor.commit(); - } - - public int getFirstEntry(){ - return mSharedPreferences.getInt("first_entry",-1); - } - - -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/SoftKeyBroadManager.java b/app/src/main/java/xyz/fycz/myreader/util/SoftKeyBroadManager.java deleted file mode 100644 index 5b9570d..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/SoftKeyBroadManager.java +++ /dev/null @@ -1,98 +0,0 @@ -package xyz.fycz.myreader.util; -import android.graphics.Rect; -import android.util.Log; -import android.view.View; -import android.view.ViewTreeObserver; - -import java.util.LinkedList; -import java.util.List; - -/** - * 软键盘弹出/关闭监听 - */ - -public class SoftKeyBroadManager implements ViewTreeObserver.OnGlobalLayoutListener{ - - public interface SoftKeyboardStateListener { - void onSoftKeyboardOpened(int keyboardHeightInPx); - - void onSoftKeyboardClosed(); - } - - private final List listeners = new LinkedList(); - private final View activityRootView; - private int lastSoftKeyboardHeightInPx; - private boolean isSoftKeyboardOpened; - - public SoftKeyBroadManager(View activityRootView) { - this(activityRootView,false); - } - - public SoftKeyBroadManager(View activityRootView, boolean isSoftKeyboardOpened) { - this.activityRootView = activityRootView; - this.isSoftKeyboardOpened = isSoftKeyboardOpened; - activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this); - } - - @Override - public void onGlobalLayout() { - final Rect r = new Rect(); - //r will be populated with the coordinates of your view that area still visible. - activityRootView.getWindowVisibleDisplayFrame(r); - - final int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top); - Log.d("SoftKeyboardStateHelper","heightDiff:" + heightDiff); - if (!isSoftKeyboardOpened && heightDiff > 500) { // if more than 100 pixels, its probably a keyboard... - isSoftKeyboardOpened = true; - notifyOnSoftKeyboardOpened(heightDiff); - //if (isSoftKeyboardOpened && heightDiff < 100) - } else if (isSoftKeyboardOpened && heightDiff < 500) { - isSoftKeyboardOpened = false; - notifyOnSoftKeyboardClosed(); - } - } - - public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) { - this.isSoftKeyboardOpened = isSoftKeyboardOpened; - } - - public boolean isSoftKeyboardOpened() { - return isSoftKeyboardOpened; - } - - /** - * Default value is zero (0) - * - * @return last saved keyboard height in px - */ - public int getLastSoftKeyboardHeightInPx() { - return lastSoftKeyboardHeightInPx; - } - - public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) { - listeners.add(listener); - } - - public void removeSoftKeyboardStateListener(SoftKeyboardStateListener listener) { - listeners.remove(listener); - } - - private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) { - this.lastSoftKeyboardHeightInPx = keyboardHeightInPx; - - for (SoftKeyboardStateListener listener : listeners) { - if (listener != null) { - listener.onSoftKeyboardOpened(keyboardHeightInPx); - } - } - } - - private void notifyOnSoftKeyboardClosed() { - for (SoftKeyboardStateListener listener : listeners) { - if (listener != null) { - listener.onSoftKeyboardClosed(); - } - } - } -} - diff --git a/app/src/main/java/xyz/fycz/myreader/util/TelephonyUtil.java b/app/src/main/java/xyz/fycz/myreader/util/TelephonyUtil.java deleted file mode 100644 index a14ea2f..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/TelephonyUtil.java +++ /dev/null @@ -1,51 +0,0 @@ -package xyz.fycz.myreader.util; - -import android.content.Context; -import android.telephony.TelephonyManager; - -import java.lang.reflect.Method; - - - -public class TelephonyUtil { - - - public static String getNum1(Context context){ - String tel; - String IMSI; - try { - TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - String deviceid = tm.getDeviceId(); - tel = tm.getLine1Number();//手机号码 - Class clazz = tm.getClass(); - Method getPhoneNumber = clazz.getDeclaredMethod("getLine1NumberForSubscriber",int.class); - String tel0 = (String)getPhoneNumber.invoke(tm, 0); - String tel1 = (String)getPhoneNumber.invoke(tm, 1); - - IMSI = tm.getSubscriberId(); - ToastUtils.showInfo(IMSI); - }catch (Exception e){ - e.printStackTrace(); - tel = ""; - } - - - return tel; - } - - public static String getNum2(Context context){ - String tel; - try { - TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - String deviceid = tm.getDeviceId(); - tel = tm.getLine1Number();//手机号码 - - }catch (Exception e){ - e.printStackTrace(); - tel = ""; - } - - return tel; - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/UploadImageTask.java b/app/src/main/java/xyz/fycz/myreader/util/UploadImageTask.java deleted file mode 100644 index 28d90c2..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/UploadImageTask.java +++ /dev/null @@ -1,5 +0,0 @@ -package xyz.fycz.myreader.util; - - -public class UploadImageTask{ -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/VibratorUtil.java b/app/src/main/java/xyz/fycz/myreader/util/VibratorUtil.java deleted file mode 100644 index d018c3e..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/VibratorUtil.java +++ /dev/null @@ -1,27 +0,0 @@ -package xyz.fycz.myreader.util; - -import android.app.Service; -import android.os.Vibrator; - -import androidx.appcompat.app.AppCompatActivity; - - -public class VibratorUtil { - - /** - * final Activity activity :调用该方法的Activity实例 - * long milliseconds :震动的时长,单位是毫秒 - * long[] pattern :自定义震动模式 。数组中数字的含义依次是[静止时长,震动时长,静止时长,震动时长。。。]时长的单位是毫秒 - * boolean isRepeat : 是否反复震动,如果是true,反复震动,如果是false,只震动一次 - */ - - public static void Vibrate(final AppCompatActivity activity, long milliseconds) { - Vibrator vib = (Vibrator) activity.getSystemService(Service.VIBRATOR_SERVICE); - vib.vibrate(milliseconds); - } - public static void Vibrate(final AppCompatActivity activity, long[] pattern, boolean isRepeat) { - Vibrator vib = (Vibrator) activity.getSystemService(Service.VIBRATOR_SERVICE); - vib.vibrate(pattern, isRepeat ? 1 : -1); - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/notification/NotificationUtil.java b/app/src/main/java/xyz/fycz/myreader/util/notification/NotificationUtil.java index 51d45c1..f1d6082 100644 --- a/app/src/main/java/xyz/fycz/myreader/util/notification/NotificationUtil.java +++ b/app/src/main/java/xyz/fycz/myreader/util/notification/NotificationUtil.java @@ -4,24 +4,17 @@ import android.annotation.TargetApi; import android.app.*; import android.content.Context; import android.content.Intent; -import android.content.pm.ApplicationInfo; import android.graphics.BitmapFactory; import android.graphics.Color; import android.net.Uri; import android.os.Build; import android.provider.Settings; -import androidx.appcompat.app.AlertDialog; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.creator.MyAlertDialog; -import xyz.fycz.myreader.greendao.service.BookMarkService; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; +import xyz.fycz.myreader.ui.dialog.MyAlertDialog; import static xyz.fycz.myreader.util.notification.NotificationClickReceiver.CANCEL_ACTION; diff --git a/app/src/main/java/xyz/fycz/myreader/util/utils/MD5Utils.java b/app/src/main/java/xyz/fycz/myreader/util/utils/MD5Utils.java new file mode 100644 index 0000000..733b080 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/util/utils/MD5Utils.java @@ -0,0 +1,43 @@ +package xyz.fycz.myreader.util.utils; + +/** + * Created by newbiechen on 2018/1/1. + */ + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * 将字符串转化为MD5 + */ + +public class MD5Utils { + + public static String strToMd5By32(String str) { + String reStr = null; + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + byte[] bytes = md5.digest(str.getBytes()); + StringBuilder stringBuffer = new StringBuilder(); + for (byte b : bytes) { + int bt = b & 0xff; + if (bt < 16) { + stringBuffer.append(0); + } + stringBuffer.append(Integer.toHexString(bt)); + } + reStr = stringBuffer.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return reStr; + } + + public static String strToMd5By16(String str) { + String reStr = strToMd5By32(str); + if (reStr != null) { + reStr = reStr.substring(8, 24); + } + return reStr; + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/util/utils/OkHttpUtils.java b/app/src/main/java/xyz/fycz/myreader/util/utils/OkHttpUtils.java new file mode 100644 index 0000000..f4f5cf4 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/util/utils/OkHttpUtils.java @@ -0,0 +1,69 @@ +package xyz.fycz.myreader.util.utils; + +import android.util.Log; +import okhttp3.*; +import xyz.fycz.myreader.application.TrustAllCerts; +import xyz.fycz.myreader.util.HttpUtil; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import java.io.IOException; +import java.security.SecureRandom; + +public class OkHttpUtils { + + public static OkHttpClient okHttpClient = HttpUtil.getOkHttpClient(); + + /** + * 同步获取html文件,默认编码utf-8 + */ + public static String getHtml(String url) throws IOException { + return getHtml(url, "utf-8"); + } + public static String getHtml(String url, String encodeType) throws IOException { + return getHtml(url, null, encodeType); + } + + public static String getHtml(String url, RequestBody requestBody, String encodeType) throws IOException { + + Request.Builder builder = new Request.Builder() + .addHeader("accept", "*/*") + .addHeader("connection", "Keep-Alive") + //.addHeader("Charsert", "utf-8") + .addHeader("Cache-Control", "no-cache") + .addHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"); + if (requestBody != null) { + builder.post(requestBody); + Log.d("HttpPost URl", url); + }else { + Log.d("HttpGet URl", url); + } + Request request = builder + .url(url) + .build(); + Response response = okHttpClient + .newCall(request) + .execute(); + ResponseBody body=response.body(); + if (body == null) { + return ""; + } else { + String bodyStr = new String(body.bytes(), encodeType); + Log.d("Http: read finish", bodyStr); + return bodyStr; + } + } + + private static SSLSocketFactory createSSLSocketFactory() { + SSLSocketFactory ssfFactory = null; + try { + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom()); + ssfFactory = sc.getSocketFactory(); + } catch (Exception e) { + } + + return ssfFactory; + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/BaseApi.java b/app/src/main/java/xyz/fycz/myreader/webapi/BaseApi.java index 336e39d..be14ff1 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/BaseApi.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/BaseApi.java @@ -6,8 +6,8 @@ import xyz.fycz.myreader.entity.JsonModel; import xyz.fycz.myreader.util.HttpUtil; import xyz.fycz.myreader.util.JsonArrayToObjectArray; import com.google.gson.Gson; -import xyz.fycz.myreader.callback.JsonCallback; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.JsonCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.source.HttpDataSource; import xyz.fycz.myreader.util.ToastUtils; @@ -156,8 +156,8 @@ public class BaseApi { * @param params * @param callback */ - public static void getCommonReturnHtmlStringApi(String url, Map params, String charsetName, final ResultCallback callback) { - HttpDataSource.httpGet_html(HttpUtil.makeURL(url, params), charsetName, new ResultCallback() { + public static void getCommonReturnHtmlStringApi(String url, Map params, String charsetName, boolean isRefresh, final ResultCallback callback) { + HttpDataSource.httpGet_html(HttpUtil.makeURL(url, params), charsetName, isRefresh ,new ResultCallback() { @Override public void onFinish(Object o, int code) { callback.onFinish(o,code); diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/BookStoreApi.java b/app/src/main/java/xyz/fycz/myreader/webapi/BookStoreApi.java index 816e48e..af5ed3f 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/BookStoreApi.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/BookStoreApi.java @@ -1,10 +1,8 @@ package xyz.fycz.myreader.webapi; -import xyz.fycz.myreader.callback.ResultCallback; -import xyz.fycz.myreader.webapi.crawler.BiQuGeReadCrawler; -import xyz.fycz.myreader.webapi.crawler.FindCrawler; -import xyz.fycz.myreader.webapi.crawler.QB5ReadCrawler; +import xyz.fycz.myreader.webapi.callback.ResultCallback; +import xyz.fycz.myreader.webapi.crawler.base.FindCrawler; /** * Created by zhao on 2017/7/24. @@ -20,7 +18,7 @@ public class BookStoreApi extends BaseApi{ */ public static void getBookTypeList(FindCrawler findCrawler, final ResultCallback callback){ - getCommonReturnHtmlStringApi(findCrawler.getFindUrl(), null, findCrawler.getCharset(), new ResultCallback() { + getCommonReturnHtmlStringApi(findCrawler.getFindUrl(), null, findCrawler.getCharset(), true, new ResultCallback() { @Override public void onFinish(Object o, int code) { callback.onFinish(findCrawler.getBookTypeList((String) o),0); @@ -42,7 +40,7 @@ public class BookStoreApi extends BaseApi{ */ public static void getBookRankList(String url, FindCrawler findCrawler, final ResultCallback callback){ - getCommonReturnHtmlStringApi(url, null, findCrawler.getCharset(), new ResultCallback() { + getCommonReturnHtmlStringApi(url, null, findCrawler.getCharset(),true, new ResultCallback() { @Override public void onFinish(Object o, int code) { callback.onFinish(findCrawler.getRankBookList((String) o),0); diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/CommonApi.java b/app/src/main/java/xyz/fycz/myreader/webapi/CommonApi.java index 72b798b..2804f90 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/CommonApi.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/CommonApi.java @@ -1,12 +1,21 @@ package xyz.fycz.myreader.webapi; +import io.reactivex.Observable; +import okhttp3.MediaType; +import okhttp3.RequestBody; import xyz.fycz.myreader.common.URLCONST; -import xyz.fycz.myreader.webapi.crawler.*; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.util.StringHelper; +import xyz.fycz.myreader.util.utils.OkHttpUtils; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; +import xyz.fycz.myreader.webapi.crawler.read.FYReadCrawler; +import xyz.fycz.myreader.webapi.crawler.read.TianLaiReadCrawler; -import java.util.HashMap; -import java.util.Map; +import java.io.IOException; public class CommonApi extends BaseApi { @@ -17,9 +26,9 @@ public class CommonApi extends BaseApi { * @param url * @param callback */ - public static void getBookChapters(String url, final ReadCrawler rc, final ResultCallback callback) { + public static void getBookChapters(String url, final ReadCrawler rc, boolean isRefresh, final ResultCallback callback) { String charset = rc.getCharset(); - getCommonReturnHtmlStringApi(url, null, charset, new ResultCallback() { + getCommonReturnHtmlStringApi(url, null, charset, isRefresh, new ResultCallback() { @Override public void onFinish(Object o, int code) { callback.onFinish(rc.getChaptersFromHtml((String) o), 0); @@ -53,7 +62,7 @@ public class CommonApi extends BaseApi { url = URLCONST.nameSpace_FY + url; } } - getCommonReturnHtmlStringApi(url, null, charset, new ResultCallback() { + getCommonReturnHtmlStringApi(url, null, charset, true, new ResultCallback() { @Override public void onFinish(Object o, int code) { callback.onFinish(rc.getContentFormHtml((String) o), 0); @@ -75,20 +84,13 @@ public class CommonApi extends BaseApi { */ public static void search(String key, final ReadCrawler rc, final ResultCallback callback) { - Map params = new HashMap<>(); String charset = "utf-8"; if (rc instanceof TianLaiReadCrawler) { charset = "utf-8"; } else { charset = rc.getCharset(); } - params.put(rc.getSearchKey(), key); - if (rc instanceof PinShuReadCrawler) { - params.put("SearchClass", 1); - }else if (rc instanceof QB5ReadCrawler){ - params.put("submit", "%CB%D1%CB%F7"); - } - getCommonReturnHtmlStringApi(rc.getSearchLink(), params, charset, new ResultCallback() { + getCommonReturnHtmlStringApi(makeSearchUrl(rc.getSearchLink(), key), null, charset, false, new ResultCallback() { @Override public void onFinish(Object o, int code) { callback.onFinish(rc.getBooksFromSearchHtml((String) o), code); @@ -101,6 +103,63 @@ public class CommonApi extends BaseApi { }); } + /** + * 搜索小说 + * + * @param key + */ + + public static Observable> search(String key, final ReadCrawler rc) { + String charset = "utf-8"; + if (rc instanceof TianLaiReadCrawler) { + charset = "utf-8"; + } else { + charset = rc.getCharset(); + } + String finalCharset = charset; + return Observable.create(emitter -> { + try { + if (rc.isPost()){ + String url = rc.getSearchLink(); + String[] urlInfo = url.split(","); + url = urlInfo[0]; + String body = makeSearchUrl(urlInfo[1], key); + MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded"); + RequestBody requestBody = RequestBody.create(mediaType, body); + emitter.onNext(rc.getBooksFromSearchHtml(OkHttpUtils.getHtml(url, requestBody, finalCharset))); + }else { + emitter.onNext(rc.getBooksFromSearchHtml(OkHttpUtils.getHtml(makeSearchUrl(rc.getSearchLink(), key), finalCharset))); + } + emitter.onComplete(); + } catch (IOException e) { + e.printStackTrace(); + emitter.onError(e); + } + }); + } + + public static String makeSearchUrl(String url, String key){ + return url.replace("{key}", key); + } + + /** + * 获取小说详细信息 + * + * @param book + */ + public static Observable getBookInfo(final Book book, final BookInfoCrawler bic) { + String url; + if (StringHelper.isEmpty(book.getInfoUrl())){ + url = book.getChapterUrl(); + }else { + url = book.getInfoUrl(); + } + return Observable.create(emitter -> { + emitter.onNext(bic.getBookInfo(OkHttpUtils.getHtml(url, bic.getCharset()), book)); + emitter.onComplete(); + }); + } + /** * 获取小说详细信息 * @@ -108,7 +167,11 @@ public class CommonApi extends BaseApi { * @param callback */ public static void getBookInfo(final Book book, final BookInfoCrawler bic, final ResultCallback callback) { - getCommonReturnHtmlStringApi(book.getChapterUrl(), null, bic.getCharset(), new ResultCallback() { + String url = book.getInfoUrl(); + if (StringHelper.isEmpty(url)){ + url = book.getChapterUrl(); + } + getCommonReturnHtmlStringApi(url, null, bic.getCharset(), false, new ResultCallback() { @Override public void onFinish(Object o, int code) { callback.onFinish(bic.getBookInfo((String) o, book), 0); diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/LanZousApi.java b/app/src/main/java/xyz/fycz/myreader/webapi/LanZousApi.java index 7064bad..90063fa 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/LanZousApi.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/LanZousApi.java @@ -3,7 +3,7 @@ package xyz.fycz.myreader.webapi; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.URLCONST; import xyz.fycz.myreader.util.SharedPreUtils; import xyz.fycz.myreader.util.StringHelper; @@ -28,7 +28,7 @@ public class LanZousApi { * @param callback */ public static void getUrl1(String lanZouUrl, final ResultCallback callback) { - getCommonReturnHtmlStringApi(lanZouUrl, null, "utf-8", new ResultCallback() { + getCommonReturnHtmlStringApi(lanZouUrl, null, "utf-8", true, new ResultCallback() { @Override public void onFinish(Object o, int code) { callback.onFinish(getUrl1((String) o), code); @@ -48,7 +48,7 @@ public class LanZousApi { * @param callback */ public static void getKey(String url, final ResultCallback callback) { - getCommonReturnHtmlStringApi(url, null, "utf-8", new ResultCallback() { + getCommonReturnHtmlStringApi(url, null, "utf-8", true, new ResultCallback() { @Override public void onFinish(Object o, int code) { callback.onFinish(getKey((String) o), code); diff --git a/app/src/main/java/xyz/fycz/myreader/callback/HttpCallback.java b/app/src/main/java/xyz/fycz/myreader/webapi/callback/HttpCallback.java similarity index 86% rename from app/src/main/java/xyz/fycz/myreader/callback/HttpCallback.java rename to app/src/main/java/xyz/fycz/myreader/webapi/callback/HttpCallback.java index 8a8a8dc..d2fc77b 100644 --- a/app/src/main/java/xyz/fycz/myreader/callback/HttpCallback.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/callback/HttpCallback.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.callback; +package xyz.fycz.myreader.webapi.callback; import android.graphics.Bitmap; diff --git a/app/src/main/java/xyz/fycz/myreader/callback/JsonCallback.java b/app/src/main/java/xyz/fycz/myreader/webapi/callback/JsonCallback.java similarity index 82% rename from app/src/main/java/xyz/fycz/myreader/callback/JsonCallback.java rename to app/src/main/java/xyz/fycz/myreader/webapi/callback/JsonCallback.java index 28e3a11..0c98c91 100644 --- a/app/src/main/java/xyz/fycz/myreader/callback/JsonCallback.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/callback/JsonCallback.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.callback; +package xyz.fycz.myreader.webapi.callback; import xyz.fycz.myreader.entity.JsonModel; diff --git a/app/src/main/java/xyz/fycz/myreader/callback/ResultCallback.java b/app/src/main/java/xyz/fycz/myreader/webapi/callback/ResultCallback.java similarity index 78% rename from app/src/main/java/xyz/fycz/myreader/callback/ResultCallback.java rename to app/src/main/java/xyz/fycz/myreader/webapi/callback/ResultCallback.java index bd7a3eb..9e16352 100644 --- a/app/src/main/java/xyz/fycz/myreader/callback/ResultCallback.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/callback/ResultCallback.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.callback; +package xyz.fycz.myreader.webapi.callback; /** diff --git a/app/src/main/java/xyz/fycz/myreader/callback/URLConnectionCallback.java b/app/src/main/java/xyz/fycz/myreader/webapi/callback/URLConnectionCallback.java similarity index 73% rename from app/src/main/java/xyz/fycz/myreader/callback/URLConnectionCallback.java rename to app/src/main/java/xyz/fycz/myreader/webapi/callback/URLConnectionCallback.java index c38354e..8e08c31 100644 --- a/app/src/main/java/xyz/fycz/myreader/callback/URLConnectionCallback.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/callback/URLConnectionCallback.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.callback; +package xyz.fycz.myreader.webapi.callback; /** * Created by zhao on 2016/4/16. diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawlerUtil.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawlerUtil.java index 511f171..c1a97e6 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawlerUtil.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawlerUtil.java @@ -3,7 +3,8 @@ package xyz.fycz.myreader.webapi.crawler; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.util.SharedPreUtils; -import xyz.fycz.myreader.util.StringHelper; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; +import xyz.fycz.myreader.webapi.crawler.read.FYReadCrawler; import java.util.ArrayList; import java.util.HashMap; @@ -24,7 +25,7 @@ public class ReadCrawlerUtil { if (searchSource == null) { StringBuilder sb = new StringBuilder(); for (BookSource bookSource : BookSource.values()) { - if (bookSource.equals(BookSource.fynovel) || bookSource.equals(BookSource.local) || bookSource.equals(BookSource.biquge)) + if (bookSource.equals(BookSource.fynovel) || bookSource.equals(BookSource.local)) continue; sb.append(bookSource.toString()); sb.append(","); @@ -49,10 +50,6 @@ public class ReadCrawlerUtil { if (searchSource == null) { for (BookSource bookSource : BookSource.values()) { if (bookSource.equals(BookSource.fynovel) || bookSource.equals(BookSource.local)) continue; - if (bookSource.equals(BookSource.biquge)) { - mSources.put(bookSource.text, true); - continue; - } mSources.put(bookSource.text, false); } } else { @@ -73,6 +70,18 @@ public class ReadCrawlerUtil { } + public static void resetReaderCrawlers(){ + StringBuilder sb = new StringBuilder(); + for (BookSource bookSource : BookSource.values()) { + if (bookSource.equals(BookSource.fynovel) || bookSource.equals(BookSource.local)) + continue; + sb.append(bookSource.toString()); + sb.append(","); + } + sb.deleteCharAt(sb.lastIndexOf(",")); + SharedPreUtils.getInstance().putString("searchSource", sb.toString()); + } + public static ReadCrawler getReadCrawler(String bookSource) { ResourceBundle rb = ResourceBundle.getBundle("crawler"); try { diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BookInfoCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/BookInfoCrawler.java similarity index 81% rename from app/src/main/java/xyz/fycz/myreader/webapi/crawler/BookInfoCrawler.java rename to app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/BookInfoCrawler.java index b5fec0e..a7d75d1 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BookInfoCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/BookInfoCrawler.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.webapi.crawler; +package xyz.fycz.myreader.webapi.crawler.base; import xyz.fycz.myreader.greendao.entity.Book; diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/FindCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/FindCrawler.java similarity index 93% rename from app/src/main/java/xyz/fycz/myreader/webapi/crawler/FindCrawler.java rename to app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/FindCrawler.java index 3a46db6..c2881c0 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/FindCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/FindCrawler.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.webapi.crawler; +package xyz.fycz.myreader.webapi.crawler.base; import xyz.fycz.myreader.entity.bookstore.BookType; import xyz.fycz.myreader.greendao.entity.Book; diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/ReadCrawler.java similarity index 80% rename from app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawler.java rename to app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/ReadCrawler.java index 91d25fa..a857e1b 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/ReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/ReadCrawler.java @@ -1,9 +1,9 @@ -package xyz.fycz.myreader.webapi.crawler; +package xyz.fycz.myreader.webapi.crawler.base; import xyz.fycz.myreader.entity.SearchBookBean; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; import java.util.ArrayList; @@ -17,7 +17,7 @@ public interface ReadCrawler { String getCharset(); String getSearchCharset(); String getNameSpace(); - String getSearchKey(); + Boolean isPost(); String getContentFormHtml(String html); ArrayList getChaptersFromHtml(String html); ConcurrentMultiValueMap getBooksFromSearchHtml(String html); diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/find/ABC.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/find/ABC.java deleted file mode 100644 index faa8f4d..0000000 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/find/ABC.java +++ /dev/null @@ -1,117 +0,0 @@ -package xyz.fycz.myreader.webapi.crawler.find; - -import android.content.Context; -import android.graphics.Bitmap; -import android.util.Log; -import android.webkit.*; -import okhttp3.*; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.callback.ResultCallback; -import xyz.fycz.myreader.creator.DialogCreator; -import xyz.fycz.myreader.entity.bookstore.BookType; -import xyz.fycz.myreader.entity.bookstore.QDBook; -import xyz.fycz.myreader.entity.bookstore.RankBook; -import xyz.fycz.myreader.entity.bookstore.SortBook; -import xyz.fycz.myreader.greendao.entity.Book; -import xyz.fycz.myreader.util.IOUtils; -import xyz.fycz.myreader.util.SharedPreUtils; -import xyz.fycz.myreader.util.StringHelper; -import xyz.fycz.myreader.webapi.CommonApi; -import xyz.fycz.myreader.webapi.crawler.FindCrawler; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.text.SimpleDateFormat; -import java.util.*; - -/** - * @author fengyue - * @date 2020/9/16 22:01 - */ -public class ABC extends FindCrawler { - private String rankUrl = ""; - private String sortUrl = ""; - private String[] sex = {"male", "female"}; - private String aParam = ""; - private String imgUrl = ""; - private String defaultCookie = ""; - private String yearmonthFormat = ""; - private LinkedHashMap rankName = new LinkedHashMap<>(); - private LinkedHashMap sortName = new LinkedHashMap<>(); - private boolean isFemale; - private boolean isSort; - - public ABC(boolean isFemale) { - this.isFemale = isFemale; - } - - public ABC(boolean isFemale, boolean isSort) { - this.isFemale = isFemale; - this.isSort = isSort; - } - - private void initMaleRankName() { - - } - - private void initSortNames() { - } - - - public List getRankTypes() { - return null; - } - - public void getRankBooks(BookType bookType, ResultCallback rc) { - - } - - private List getBooksFromJson(String json) { - return null; - } - - @Override - public String getCharset() { - return null; - } - - @Override - public String getFindName() { - return null; - } - - @Override - public String getFindUrl() { - return null; - } - - @Override - public boolean getTypePage(BookType curType, int page) { - return false; - } - - @Override - public boolean hasImg() { - return true; - } - - @Override - public List getBookTypeList(String html) { - return null; - } - - @Override - public List getRankBookList(String html) { - return null; - } - - - public void initCookie(Context mContext, ResultCallback rc) { - - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/find/QiDianMobileRank.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/find/QiDianMobileRank.java new file mode 100644 index 0000000..1be184a --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/find/QiDianMobileRank.java @@ -0,0 +1,270 @@ +package xyz.fycz.myreader.webapi.crawler.find; + +import android.content.Context; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import xyz.fycz.myreader.application.MyApplication; +import xyz.fycz.myreader.webapi.callback.ResultCallback; +import xyz.fycz.myreader.entity.bookstore.BookType; +import xyz.fycz.myreader.entity.bookstore.QDBook; +import xyz.fycz.myreader.entity.bookstore.RankBook; +import xyz.fycz.myreader.entity.bookstore.SortBook; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.util.IOUtils; +import xyz.fycz.myreader.util.SharedPreUtils; +import xyz.fycz.myreader.util.StringHelper; +import xyz.fycz.myreader.webapi.CommonApi; +import xyz.fycz.myreader.webapi.crawler.base.FindCrawler; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * @author fengyue + * @date 2020/9/16 22:01 + */ +public class QiDianMobileRank extends FindCrawler { + private String rankUrl = "https://m.qidian.com/majax/rank/{rankName}list?_csrfToken={cookie}&gender={sex}&pageNum={page}&catId=-1"; + private String sortUrl = "https://m.qidian.com/majax/category/list?_csrfToken={cookie}&gender={sex}&pageNum={page}&orderBy=&catId={catId}&subCatId="; + private String[] sex = {"male", "female"}; + private String yuepiaoParam = "&yearmonth={yearmonth}"; + private String imgUrl = "https://bookcover.yuewen.com/qdbimg/349573/{bid}/150"; + private String defaultCookie = "eXRDlZxmRDLvFAmdgzqvwWAASrxxp2WkVlH4ZM7e"; + private String yearmonthFormat = "yyyyMM"; + private LinkedHashMap rankName = new LinkedHashMap<>(); + private LinkedHashMap sortName = new LinkedHashMap<>(); + private boolean isFemale; + private boolean isSort; + + public QiDianMobileRank(boolean isFemale) { + this.isFemale = isFemale; + } + + public QiDianMobileRank(boolean isFemale, boolean isSort) { + this.isFemale = isFemale; + this.isSort = isSort; + } + + private void initMaleRankName() { + if (!isFemale) { + rankName.put("风云榜", "yuepiao"); + rankName.put("畅销榜", "hotsales"); + rankName.put("阅读榜", "readIndex"); + rankName.put("粉丝榜", "newfans"); + rankName.put("推荐榜", "rec"); + rankName.put("更新榜", "update"); + rankName.put("签约榜", "sign"); + rankName.put("新书榜", "newbook"); + rankName.put("新人榜", "newauthor"); + } else { + rankName.put("风云榜", "yuepiao"); + rankName.put("阅读榜", "readIndex"); + rankName.put("粉丝榜", "newfans"); + rankName.put("推荐榜", "rec"); + rankName.put("更新榜", "update"); + rankName.put("收藏榜", "collect"); + rankName.put("免费榜", "free"); + } + } + + private void initSortNames() { + /* + {value: -1, text: "全站"} +1: {value: 21, text: "玄幻"} +2: {value: 1, text: "奇幻"} +3: {value: 2, text: "武侠"} +4: {value: 22, text: "仙侠"} +5: {value: 4, text: "都市"} +6: {value: 15, text: "现实"} +7: {value: 6, text: "军事"} +8: {value: 5, text: "历史"} +9: {value: 7, text: "游戏"} +10: {value: 8, text: "体育"} +11: {value: 9, text: "科幻"} +12: {value: 10, text: "悬疑"} +13: {value: 12, text: "轻小说"} + */ + if (!isFemale) { + sortName.put("玄幻小说", 21); + sortName.put("奇幻小说", 1); + sortName.put("武侠小说", 2); + sortName.put("都市小说", 4); + sortName.put("现实小说", 15); + sortName.put("军事小说", 6); + sortName.put("历史小说", 5); + sortName.put("体育小说", 8); + sortName.put("科幻小说", 9); + sortName.put("悬疑小说", 10); + sortName.put("轻小说", 12); + sortName.put("短篇小说", 20076); + } else { + sortName.put("古代言情", 80); + sortName.put("仙侠奇缘", 81); + sortName.put("现代言情", 82); + sortName.put("烂漫青春", 83); + sortName.put("玄幻言情", 84); + sortName.put("悬疑推理", 85); + sortName.put("短篇小说", 30083); + sortName.put("科幻空间", 86); + sortName.put("游戏竞技", 88); + sortName.put("轻小说", 87); + sortName.put("现实生活", 30120); + } + } + + + public List getRankTypes() { + if (!isSort) { + initMaleRankName(); + } else { + initSortNames(); + } + List bookTypes = new ArrayList<>(); + Set names = !isSort ? rankName.keySet() : sortName.keySet(); + for (String name : names) { + BookType bookType = new BookType(); + bookType.setTypeName(name); + String url; + if (!isSort) { + url = rankUrl.replace("{rankName}", rankName.get(name)); + } else { + url = sortUrl.replace("{catId}", sortName.get(name) + ""); + } + url = url.replace("{sex}", !isFemale ? sex[0] : sex[1]); + SharedPreUtils spu = SharedPreUtils.getInstance(); + String cookie = spu.getString("qdCookie", ""); + if (!cookie.equals("")) { + url = url.replace("{cookie}", StringHelper.getSubString(cookie, "_csrfToken=", ";")); + } else { + url = url.replace("{cookie}", defaultCookie); + } + if ("风云榜".equals(name)) { + SimpleDateFormat sdf = new SimpleDateFormat(yearmonthFormat, Locale.CHINA); + String yearmonth = sdf.format(new Date()); + url = url + yuepiaoParam.replace("{yearmonth}", yearmonth); + } + bookType.setUrl(url); + bookTypes.add(bookType); + } + return bookTypes; + } + + public void getRankBooks(BookType bookType, ResultCallback rc) { + CommonApi.getCommonReturnHtmlStringApi(bookType.getUrl(), null, "UTF-8", true, + new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + rc.onFinish(getBooksFromJson((String) o), 1); + } + + @Override + public void onError(Exception e) { + rc.onError(e); + } + }); + } + + private List getBooksFromJson(String json) { + List books = new ArrayList<>(); + try { + JSONObject all = new JSONObject(json); + JSONObject data = all.getJSONObject("data"); + JSONArray jsonBooks = data.getJSONArray("records"); + for (int i = 0; i < jsonBooks.length(); i++) { + JSONObject jsonBook = jsonBooks.getJSONObject(i); + QDBook book = !isSort ? new RankBook() : new SortBook(); + book.setbName(jsonBook.getString("bName")); + book.setbAuth(jsonBook.getString("bAuth")); + book.setBid(jsonBook.getString("bid")); + book.setCat(jsonBook.getString("cat")); + book.setCatId(jsonBook.getInt("catId")); + book.setCnt(jsonBook.getString("cnt")); + book.setDesc(jsonBook.getString("desc")); + book.setImg(imgUrl.replace("{bid}", jsonBook.getString("bid"))); + if (!isSort) { + ((RankBook) book).setRankCnt(jsonBook.getString("rankCnt")); + ((RankBook) book).setRankNum(jsonBook.getInt("rankNum")); + }else { + ((SortBook) book).setState(jsonBook.getString("state")); + } + books.add(book); + } + } catch (JSONException e) { + e.printStackTrace(); + } + return books; + } + + @Override + public String getCharset() { + return null; + } + + @Override + public String getFindName() { + return !isFemale ? !isSort ? "排行榜[男生小说]" : "分类[男生小说]" : !isSort ? "排行榜[女生小说]" : "分类[女生小说]"; + } + + @Override + public String getFindUrl() { + return null; + } + + @Override + public boolean getTypePage(BookType curType, int page) { + if (!isSort) { + if (page > 30) { + return true; + } + }else { + if (page > 5) { + return true; + } + } + String pageNum = curType.getUrl().substring(curType.getUrl().indexOf("pageNum=") + 8, curType.getUrl().indexOf("&catId")); + curType.setUrl(curType.getUrl().replace("pageNum=" + pageNum, "pageNum=" + page)); + return false; + } + + @Override + public boolean hasImg() { + return true; + } + + @Override + public List getBookTypeList(String html) { + return null; + } + + @Override + public List getRankBookList(String html) { + return null; + } + + + public void initCookie(Context mContext, ResultCallback rc) { + MyApplication.getApplication().newThread(() -> { + BufferedReader br = null; + try { + br = new BufferedReader(new InputStreamReader(mContext.getAssets().open("_csrfToken.fy"))); + StringBuilder assetText = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + assetText.append(line); + } + String[] _csrfTokens = assetText.toString().split(","); + Random random = new Random(); + rc.onFinish(_csrfTokens[random.nextInt(_csrfTokens.length)], 1); + } catch (IOException e) { + rc.onError(e); + } finally { + IOUtils.close(br); + } + }); + } + +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/Ben100ReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/Ben100ReadCrawler.java new file mode 100644 index 0000000..1d1998d --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/Ben100ReadCrawler.java @@ -0,0 +1,151 @@ +package xyz.fycz.myreader.webapi.crawler.read; + +import android.text.Html; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + +import java.util.ArrayList; + + +public class Ben100ReadCrawler implements ReadCrawler, BookInfoCrawler { + public static final String NAME_SPACE = "https://www.100ben.net"; + public static final String NOVEL_SEARCH = "https://www.100ben.net/plus/search.php?keyword={key}"; + public static final String CHARSET = "UTF-8"; + public static final String SEARCH_CHARSET = "utf-8"; + + @Override + public String getSearchLink() { + return NOVEL_SEARCH; + } + + @Override + public String getCharset() { + return CHARSET; + } + + @Override + public String getNameSpace() { + return NAME_SPACE; + } + + @Override + public Boolean isPost() { + return false; + } + + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + + /** + * 从html中获取章节正文 + * + * @param html + * @return + */ + public String getContentFormHtml(String html) { + Document doc = Jsoup.parse(html); + Element divContent = doc.getElementById("content"); + if (divContent != null) { + String content = Html.fromHtml(divContent.html()).toString(); + char c = 160; + String spaec = "" + c; + content = content.replace(spaec, " "); + return content; + } else { + return ""; + } + } + + /** + * 从html中获取章节列表 + * + * @param html + * @return + */ + public ArrayList getChaptersFromHtml(String html) { + ArrayList chapters = new ArrayList<>(); + Document doc = Jsoup.parse(html); + try { + Element divList = doc.getElementById("dir"); + int i = 0; + Elements elementsByTag = divList.getElementsByTag("dd"); + for (int j = 0; j < elementsByTag.size(); j++) { + Element dd = elementsByTag.get(j); + Elements as = dd.getElementsByTag("a"); + Element a = as.get(0); + String title = a.text(); + Chapter chapter = new Chapter(); + chapter.setNumber(i++); + chapter.setTitle(title); + String url = NAME_SPACE + a.attr("href"); + chapter.setUrl(url); + chapters.add(chapter); + } + } catch (Exception e) { + e.printStackTrace(); + } + return chapters; + } + + /** + * 从搜索html中得到书列表 + * + * @param html + * @return + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String html) { + ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); + Document doc = Jsoup.parse(html); +// try { + Elements divs = doc.getElementsByClass("recommand"); + Element div = divs.get(0); + Elements elementsByTag = div.getElementsByTag("li"); + for (Element element : elementsByTag) { + Book book = new Book(); + String name = element.getElementsByClass("titles").first().getElementsByTag("a").first().text(); + book.setName(name); + String author = element.getElementsByClass("author").first().text().replace("作者:", ""); + book.setAuthor(author); + String imgUrl = element.getElementsByTag("img").first().attr("src"); + book.setImgUrl(imgUrl); + String chapterUrl = element.getElementsByClass("titles").first().getElementsByTag("a").first().attr("href"); + book.setChapterUrl(NAME_SPACE + chapterUrl); + String desc = element.getElementsByClass("intro").first().text(); + book.setDesc(desc); + book.setNewestChapterTitle(""); + book.setSource(BookSource.ben100.toString()); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } +// } catch (Exception e) { +// e.printStackTrace(); +// } + return books; + } + + /** + * 获取书籍详细信息 + * @param book + */ + public Book getBookInfo(String html, Book book){ + Document doc = Jsoup.parse(html); + Element img = doc.getElementById("fmimg"); + book.setImgUrl(img.getElementsByTag("img").get(0).attr("src")); + Element desc = doc.getElementById("intro"); + book.setDesc(desc.getElementsByTag("p").get(0).text()); + Element type = doc.getElementsByClass("con_top").get(0); + book.setType(type.getElementsByTag("a").get(2).text()); + return book; + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGe44ReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/BiQuGe44ReadCrawler.java similarity index 93% rename from app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGe44ReadCrawler.java rename to app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/BiQuGe44ReadCrawler.java index 7cfb6b7..e684d60 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGe44ReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/BiQuGe44ReadCrawler.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.webapi.crawler; +package xyz.fycz.myreader.webapi.crawler.read; import android.text.Html; import org.jsoup.Jsoup; @@ -9,16 +9,17 @@ import xyz.fycz.myreader.entity.SearchBookBean; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; import xyz.fycz.myreader.util.StringHelper; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import java.util.ArrayList; -public class BiQuGe44ReadCrawler implements ReadCrawler, BookInfoCrawler{ +public class BiQuGe44ReadCrawler implements ReadCrawler, BookInfoCrawler { public static final String NAME_SPACE = "https://www.wqge.cc"; - public static final String NOVEL_SEARCH = "https://www.wqge.cc/modules/article/search.php"; - public static final String SEARCH_KEY = "searchkey"; + public static final String NOVEL_SEARCH = "https://www.wqge.cc/modules/article/search.php?searchkey={key}"; public static final String CHARSET = "GBK"; public static final String SEARCH_CHARSET = "utf-8"; @Override @@ -35,12 +36,10 @@ public class BiQuGe44ReadCrawler implements ReadCrawler, BookInfoCrawler{ public String getNameSpace() { return NAME_SPACE; } - @Override - public String getSearchKey() { - return SEARCH_KEY; + public Boolean isPost() { + return false; } - @Override public String getSearchCharset() { return SEARCH_CHARSET; diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGeReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/BiQuGeReadCrawler.java similarity index 96% rename from app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGeReadCrawler.java rename to app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/BiQuGeReadCrawler.java index 3bad188..e30ee5a 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/BiQuGeReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/BiQuGeReadCrawler.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.webapi.crawler; +package xyz.fycz.myreader.webapi.crawler.read; import android.text.Html; import org.jsoup.Jsoup; @@ -10,8 +10,10 @@ import xyz.fycz.myreader.entity.bookstore.BookType; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; import xyz.fycz.myreader.util.StringHelper; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import java.util.ArrayList; import java.util.List; @@ -21,8 +23,7 @@ import java.util.regex.Pattern; public class BiQuGeReadCrawler implements ReadCrawler, BookInfoCrawler { private static final String NAME_SPACE = "https://www.52bqg.net"; - private static final String NOVEL_SEARCH = "https://www.52bqg.net/modules/article/search.php"; - private static final String SEARCH_KEY = "searchkey"; + private static final String NOVEL_SEARCH = "https://www.52bqg.net/modules/article/search.php?searchkey={key}"; private static final String CHARSET = "GBK"; public static final String SEARCH_CHARSET = "GBK"; @@ -37,12 +38,10 @@ public class BiQuGeReadCrawler implements ReadCrawler, BookInfoCrawler { public String getNameSpace() { return NAME_SPACE; } - @Override - public String getSearchKey() { - return SEARCH_KEY; + public Boolean isPost() { + return false; } - @Override public String getCharset() { return CHARSET; diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/CansShu99ReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/CansShu99ReadCrawler.java new file mode 100644 index 0000000..dfeba40 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/CansShu99ReadCrawler.java @@ -0,0 +1,139 @@ +package xyz.fycz.myreader.webapi.crawler.read; + +import android.text.Html; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + +import java.util.ArrayList; + + +public class CansShu99ReadCrawler implements ReadCrawler { + public static final String NAME_SPACE = "http://www.99csw.com"; + public static final String NOVEL_SEARCH = "http://www.99csw.com/book/search.php?type=all&keyword={key}"; + public static final String CHARSET = "UTF-8"; + public static final String SEARCH_CHARSET = "utf-8"; + + @Override + public String getSearchLink() { + return NOVEL_SEARCH; + } + + @Override + public String getCharset() { + return CHARSET; + } + + @Override + public String getNameSpace() { + return NAME_SPACE; + } + + @Override + public Boolean isPost() { + return false; + } + + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + + /** + * 从html中获取章节正文 + * + * @param html + * @return + */ + public String getContentFormHtml(String html) { + Document doc = Jsoup.parse(html); + Element divContent = doc.getElementById("content"); + if (divContent != null) { + String content = Html.fromHtml(divContent.html()).toString(); + char c = 160; + String spaec = "" + c; + content = content.replace(spaec, " "); + return content; + } else { + return ""; + } + } + + /** + * 从html中获取章节列表 + * + * @param html + * @return + */ + public ArrayList getChaptersFromHtml(String html) { + ArrayList chapters = new ArrayList<>(); + Document doc = Jsoup.parse(html); + try { + Element divList = doc.getElementById("dir"); + int i = 0; + Elements elementsByTag = divList.getElementsByTag("dd"); + for (int j = 0; j < elementsByTag.size(); j++) { + Element dd = elementsByTag.get(j); + Elements as = dd.getElementsByTag("a"); + Element a = as.get(0); + String title = a.text(); + Chapter chapter = new Chapter(); + chapter.setNumber(i++); + chapter.setTitle(title); + String url = NAME_SPACE + a.attr("href"); + chapter.setUrl(url); + chapters.add(chapter); + } + } catch (Exception e) { + e.printStackTrace(); + } + return chapters; + } + + /** + * 从搜索html中得到书列表 + * + * @param html + * @return + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String html) { + ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); + Document doc = Jsoup.parse(html); +// try { + Elements divs = doc.getElementsByClass("list_box"); + Element div = divs.get(0); + Elements elementsByTag = div.getElementsByTag("li"); + for (Element element : elementsByTag) { + Book book = new Book(); + String name = element.getElementsByTag("h2").first().getElementsByTag("a").first().text(); + book.setName(name); + String author = element.getElementsByTag("h4").first().getElementsByTag("a").first().text(); + book.setAuthor(author); + String type = element.getElementsByTag("h4").get(1).getElementsByTag("a").text(); + book.setType(type); + String desc = element.getElementsByClass("intro").first().text(); + book.setDesc(desc); + String imgUrl = element.getElementsByTag("img").first().attr("src"); + book.setImgUrl("http:" + imgUrl); + String chapterUrl = element.getElementsByTag("h2").first().getElementsByTag("a").first().attr("href"); + book.setChapterUrl(NAME_SPACE + chapterUrl); + book.setNewestChapterTitle(""); + book.setSource(BookSource.cangshu99.toString()); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } +// } catch (Exception e) { +// e.printStackTrace(); +// } + return books; + } + + +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ChaoXingReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ChaoXingReadCrawler.java new file mode 100644 index 0000000..09f8451 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ChaoXingReadCrawler.java @@ -0,0 +1,130 @@ +package xyz.fycz.myreader.webapi.crawler.read; + +import android.text.Html; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + +import java.util.ArrayList; + + +public class ChaoXingReadCrawler implements ReadCrawler { + public static final String NAME_SPACE = "http://yz4.chaoxing.com"; + public static final String NOVEL_SEARCH = "http://yz4.chaoxing.com/circlemarket/getsearch,start=0&size=25&sw={key}&channelId=52"; + public static final String CHAPTERS_URL = "https://special.zhexuezj.cn/mobile/mooc/tocourse/"; + public static final String DESC = "★★★ 超星·出版 ★★★\n★★★ 本书暂无简介 ★★★"; + public static final String CHARSET = "UTF-8"; + public static final String SEARCH_CHARSET = "UTF-8"; + + @Override + public String getSearchLink() { + return NOVEL_SEARCH; + } + + @Override + public String getCharset() { + return CHARSET; + } + + @Override + public String getNameSpace() { + return NAME_SPACE; + } + + @Override + public Boolean isPost() { + return true; + } + + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + + /** + * 从html中获取章节正文 + * + * @param html + * @return + */ + public String getContentFormHtml(String html) { + Document doc = Jsoup.parse(html); + Element divContent = doc.getElementById("contentBox"); + Elements ps = divContent.getElementsByTag("p"); + StringBuilder sb = new StringBuilder(); + for (Element p : ps){ + String content = Html.fromHtml(p.html()).toString(); + char c = 160; + String spaec = "" + c; + content = content.replace(spaec, " "); + sb.append(content); + sb.append("\n"); + } + return sb.toString(); + } + + /** + * 从html中获取章节列表 + * + * @param html + * @return + */ + public ArrayList getChaptersFromHtml(String html) { + ArrayList chapters = new ArrayList<>(); + Document doc = Jsoup.parse(html); + Element divList = doc.getElementsByClass("con").first(); + Elements elementsByTag = divList.getElementsByTag("a"); + int i = 0; + for (Element a : elementsByTag) { + String title = a.text(); + String url = a.attr("attr"); + Chapter chapter = new Chapter(); + chapter.setNumber(i++); + chapter.setTitle(title); + chapter.setUrl(url); + chapters.add(chapter); + } + return chapters; + } + + /** + * 从搜索html中得到书列表 + * + * @param json + * @return + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String json) { + ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); + try { + JSONArray booksArray = new JSONArray(json); + for (int i = 0; i < booksArray.length(); i++) { + JSONObject bookJson = booksArray.getJSONObject(i); + Book book = new Book(); + book.setName(bookJson.getString("name")); + book.setAuthor(bookJson.getString("author")); + book.setImgUrl(bookJson.getString("coverUrl")); + book.setNewestChapterTitle(""); + book.setChapterUrl(CHAPTERS_URL + bookJson.getInt("course_Id")); + book.setDesc(DESC); + book.setSource(BookSource.chaoxing.toString()); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } + } catch (JSONException e) { + e.printStackTrace(); + } + return books; + } + + +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/FYReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/FYReadCrawler.java similarity index 92% rename from app/src/main/java/xyz/fycz/myreader/webapi/crawler/FYReadCrawler.java rename to app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/FYReadCrawler.java index eef038f..e5e5896 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/FYReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/FYReadCrawler.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.webapi.crawler; +package xyz.fycz.myreader.webapi.crawler.read; import android.text.Html; @@ -11,7 +11,8 @@ import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; -import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import java.util.ArrayList; import java.util.regex.Matcher; @@ -21,10 +22,9 @@ import java.util.regex.Pattern; * 风月小说网html解析工具 */ -public class FYReadCrawler implements ReadCrawler{ +public class FYReadCrawler implements ReadCrawler { public static final String NAME_SPACE = "https://novel.fycz.xyz"; - public static final String NOVEL_SEARCH = "https://novel.fycz.xyz/search.html"; - public static final String SEARCH_KEY = "keyword"; + public static final String NOVEL_SEARCH = "https://novel.fycz.xyz/search.html?keyword={key}"; public static final String CHARSET = "utf-8"; public static final String SEARCH_CHARSET = "utf-8"; @Override @@ -40,12 +40,10 @@ public class FYReadCrawler implements ReadCrawler{ public String getNameSpace() { return NAME_SPACE; } - @Override - public String getSearchKey() { - return SEARCH_KEY; + public Boolean isPost() { + return false; } - @Override public String getSearchCharset() { return SEARCH_CHARSET; diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/JiuTaoReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/JiuTaoReadCrawler.java new file mode 100644 index 0000000..8b99a55 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/JiuTaoReadCrawler.java @@ -0,0 +1,127 @@ +package xyz.fycz.myreader.webapi.crawler.read; + +import android.text.Html; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + +import java.util.ArrayList; + + +public class JiuTaoReadCrawler implements ReadCrawler { + public static final String NAME_SPACE = "https://www.9txs.com"; + public static final String NOVEL_SEARCH = "https://www.9txs.com/search.html,searchkey={key}"; + public static final String CHARSET = "UTF-8"; + public static final String SEARCH_CHARSET = "UTF-8"; + + @Override + public String getSearchLink() { + return NOVEL_SEARCH; + } + + @Override + public String getCharset() { + return CHARSET; + } + + @Override + public String getNameSpace() { + return NAME_SPACE; + } + + @Override + public Boolean isPost() { + return true; + } + + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + + /** + * 从html中获取章节正文 + * + * @param html + * @return + */ + public String getContentFormHtml(String html) { + Document doc = Jsoup.parse(html); + Element divContent = doc.getElementById("content"); + if (divContent != null) { + String content = Html.fromHtml(divContent.html()).toString(); + char c = 160; + String spaec = "" + c; + content = content.replace(spaec, " ").replaceAll("您可以在.*最新章节!|\\\\", ""); + return content; + } else { + return ""; + } + } + + /** + * 从html中获取章节列表 + * + * @param html + * @return + */ + public ArrayList getChaptersFromHtml(String html) { + ArrayList chapters = new ArrayList<>(); + Document doc = Jsoup.parse(html); + Element divList = doc.getElementsByClass("read").first(); + Elements elementsByTag = divList.getElementsByTag("a"); + int i = 0; + for (int j = 12; j < elementsByTag.size(); j++) { + Element a = elementsByTag.get(j); + String title = a.text(); + String url = a.attr("href"); + Chapter chapter = new Chapter(); + chapter.setNumber(i++); + chapter.setTitle(title); + chapter.setUrl(NAME_SPACE + url); + chapters.add(chapter); + } + return chapters; + } + + /** + * 从搜索html中得到书列表 + * + * @param html + * @return + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String html) { + ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); + Document doc = Jsoup.parse(html); +// try { + Element div = doc.getElementsByClass("library").first(); + Elements lis = div.getElementsByTag("li"); + for (Element li : lis){ + Elements as = li.getElementsByTag("a"); + Book book = new Book(); + book.setName(as.get(1).text()); + book.setAuthor(as.get(2).text()); + book.setType(as.get(3).text()); + book.setNewestChapterTitle(as.get(4).text().replace("最新章节:", "")); + book.setDesc(li.getElementsByClass("intro").first().text()); + book.setImgUrl(li.getElementsByTag("img").attr("src")); + book.setChapterUrl(NAME_SPACE + as.get(1).attr("href").replace(".html", "/")); + book.setSource(BookSource.jiutao.toString()); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } +// } catch (Exception e) { +// e.printStackTrace(); +// } + return books; + } + + +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/MiQuReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/MiQuReadCrawler.java new file mode 100644 index 0000000..c868e7b --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/MiQuReadCrawler.java @@ -0,0 +1,140 @@ +package xyz.fycz.myreader.webapi.crawler.read; + +import android.text.Html; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + +import java.util.ArrayList; + + +public class MiQuReadCrawler implements ReadCrawler, BookInfoCrawler { + public static final String NAME_SPACE = "https://www.meegoq.com/"; + public static final String NOVEL_SEARCH = "https://www.meegoq.com/search.htm?keyword={key}"; + public static final String CHARSET = "UTF-8"; + public static final String SEARCH_CHARSET = "UTF-8"; + + @Override + public String getSearchLink() { + return NOVEL_SEARCH; + } + + @Override + public String getCharset() { + return CHARSET; + } + + @Override + public String getNameSpace() { + return NAME_SPACE; + } + + @Override + public Boolean isPost() { + return false; + } + + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + + /** + * 从html中获取章节正文 + * + * @param html + * @return + */ + public String getContentFormHtml(String html) { + Document doc = Jsoup.parse(html); + Element divContent = doc.getElementById("content"); + if (divContent != null) { + String content = Html.fromHtml(divContent.html()).toString(); + char c = 160; + String spaec = "" + c; + content = content.replace(spaec, " ").replace("applyChapterSetting();", ""); + return content; + } else { + return ""; + } + } + + /** + * 从html中获取章节列表 + * + * @param html + * @return + */ + public ArrayList getChaptersFromHtml(String html) { + ArrayList chapters = new ArrayList<>(); + Document doc = Jsoup.parse(html); + Element divList = doc.getElementsByClass("mulu").first(); + Elements elementsByTag = divList.getElementsByTag("a"); + int i = 0; + for (int j = 9; j < elementsByTag.size(); j++) { + Element a = elementsByTag.get(j); + String title = a.text(); + String url = "http:" + a.attr("href"); + Chapter chapter = new Chapter(); + chapter.setNumber(i++); + chapter.setTitle(title); + chapter.setUrl(url); + chapters.add(chapter); + } + return chapters; + } + + /** + * 从搜索html中得到书列表 + * + * @param html + * @return + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String html) { + ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); + Document doc = Jsoup.parse(html); + Elements divs = doc.getElementsByClass("lastest"); + Element div = divs.get(0); + Elements elementsByTag = div.getElementsByTag("li"); + for (int i = 1; i < elementsByTag.size() - 1; i++) { + Element element = elementsByTag.get(i); + Book book = new Book(); + Element info = element.getElementsByClass("n2").first(); + book.setName(info.text()); + book.setInfoUrl("http:" + info.getElementsByTag("a").attr("href")); + book.setChapterUrl("http:" + info.getElementsByTag("a").attr("href").replace("info", "book")); + book.setAuthor(element.getElementsByClass("a2").first().text()); + book.setType(element.getElementsByClass("nt").first().text()); + book.setNewestChapterTitle(element.getElementsByClass("c2").first().text()); + book.setSource(BookSource.miqu.toString()); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } + return books; + } + + /** + * 获取书籍详细信息 + * + * @param book + */ + public Book getBookInfo(String html, Book book) { + Document doc = Jsoup.parse(html); + Element img = doc.getElementsByClass("cover").first(); + book.setImgUrl(img.getElementsByTag("img").get(0).attr("src")); + + String desc = doc.select("meta[property=og:description]").attr("content"); + book.setDesc(desc); + + return book; + } + +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/PinShuReadCrawler.java similarity index 92% rename from app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler.java rename to app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/PinShuReadCrawler.java index 173409e..5334323 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/PinShuReadCrawler.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.webapi.crawler; +package xyz.fycz.myreader.webapi.crawler.read; import android.text.Html; import org.jsoup.Jsoup; @@ -9,8 +9,10 @@ import xyz.fycz.myreader.entity.SearchBookBean; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; import xyz.fycz.myreader.util.StringHelper; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import java.util.ArrayList; @@ -20,8 +22,7 @@ import java.util.ArrayList; */ public class PinShuReadCrawler implements ReadCrawler, BookInfoCrawler { public static final String NAME_SPACE = "https://www.vodtw.com"; - public static final String NOVEL_SEARCH = "https://www.vodtw.com/Book/Search.aspx"; - public static final String SEARCH_KEY = "SearchKey"; + public static final String NOVEL_SEARCH = "https://www.vodtw.com/Book/Search.aspx?SearchKey={key}&SearchClass=1"; public static final String CHARSET = "gbk"; public static final String SEARCH_CHARSET = "gbk"; @@ -39,10 +40,9 @@ public class PinShuReadCrawler implements ReadCrawler, BookInfoCrawler { public String getNameSpace() { return NAME_SPACE; } - @Override - public String getSearchKey() { - return SEARCH_KEY; + public Boolean isPost() { + return false; } @Override public String getSearchCharset() { diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler2.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/PinShuReadCrawler2.java similarity index 94% rename from app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler2.java rename to app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/PinShuReadCrawler2.java index 55d8488..2b22ecb 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/PinShuReadCrawler2.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/PinShuReadCrawler2.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.webapi.crawler; +package xyz.fycz.myreader.webapi.crawler.read; import android.text.Html; import org.jsoup.Jsoup; @@ -9,8 +9,10 @@ import xyz.fycz.myreader.entity.SearchBookBean; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; import xyz.fycz.myreader.util.StringHelper; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import java.util.ArrayList; @@ -39,12 +41,10 @@ public class PinShuReadCrawler2 implements ReadCrawler, BookInfoCrawler { public String getNameSpace() { return NAME_SPACE; } - @Override - public String getSearchKey() { - return SEARCH_KEY; + public Boolean isPost() { + return false; } - @Override public String getSearchCharset() { return SEARCH_CHARSET; diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/QB5ReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/QB5ReadCrawler.java similarity index 95% rename from app/src/main/java/xyz/fycz/myreader/webapi/crawler/QB5ReadCrawler.java rename to app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/QB5ReadCrawler.java index 64fc7da..144db3c 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/QB5ReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/QB5ReadCrawler.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.webapi.crawler; +package xyz.fycz.myreader.webapi.crawler.read; import android.text.Html; import org.jsoup.Jsoup; @@ -10,8 +10,11 @@ import xyz.fycz.myreader.entity.bookstore.BookType; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; import xyz.fycz.myreader.util.StringHelper; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.FindCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import java.util.ArrayList; import java.util.List; @@ -19,10 +22,9 @@ import java.util.List; public class QB5ReadCrawler extends FindCrawler implements ReadCrawler, BookInfoCrawler { private static final String NAME_SPACE = "https://www.qb5.tw"; - private static final String NOVEL_SEARCH = "https://www.qb5.tw/modules/article/search.php"; + private static final String NOVEL_SEARCH = "https://www.qb5.tw/modules/article/search.php?searchkey={key}&submit=%CB%D1%CB%F7"; public static final String FIND_URL = "https://www.qb5.tw"; public static final String FIND_NAME = "书城[全本小说]"; - private static final String SEARCH_KEY = "searchkey"; private static final String CHARSET = "GBK"; public static final String SEARCH_CHARSET = "GBK"; @@ -35,12 +37,10 @@ public class QB5ReadCrawler extends FindCrawler implements ReadCrawler, BookInfo public String getNameSpace() { return NAME_SPACE; } - @Override - public String getSearchKey() { - return SEARCH_KEY; + public Boolean isPost() { + return false; } - @Override public String getCharset() { return CHARSET; @@ -165,9 +165,7 @@ public class QB5ReadCrawler extends FindCrawler implements ReadCrawler, BookInfo char c = 160; String spaec = "" + c; content = content.replace(spaec, " "); - content = content.replace("全本小说网 www.qb5.tw,最快更新", "") - .replace(bookName, "") - .replace("最新章节!", ""); + content = content.replaceAll("全本小说.*最新章节!", ""); return content; } else { return ""; diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/QiQiReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/QiQiReadCrawler.java new file mode 100644 index 0000000..7b4440c --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/QiQiReadCrawler.java @@ -0,0 +1,134 @@ +package xyz.fycz.myreader.webapi.crawler.read; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.TextNode; +import org.jsoup.select.Elements; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + +import java.util.ArrayList; + + +public class QiQiReadCrawler implements ReadCrawler { + public static final String NAME_SPACE = "https://www.qq717.com"; + public static final String NOVEL_SEARCH = "https://www.qq717.com/search.php?keyword={key}"; + public static final String CHARSET = "UTF-8"; + public static final String SEARCH_CHARSET = "UTF-8"; + + @Override + public String getSearchLink() { + return NOVEL_SEARCH; + } + + @Override + public String getCharset() { + return CHARSET; + } + + @Override + public String getNameSpace() { + return NAME_SPACE; + } + + @Override + public Boolean isPost() { + return false; + } + + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + + /** + * 从html中获取章节正文 + * + * @param html + * @return + */ + public String getContentFormHtml(String html) { + Document doc = Jsoup.parse(html); + Element divContent = doc.getElementById("content"); + if (divContent != null) { + StringBuilder sb = new StringBuilder(); + for (TextNode textNode : divContent.textNodes()){ + sb.append(textNode.text()); + sb.append("\n"); + } + String content = sb.toString(); + char c = 160; + String spaec = "" + c; + content = content.replace(spaec, " ").replaceAll("奇奇小说全网.*com|更新最.*com\\\\/|哽噺.*com|www.*com\"", ""); + return content; + } else { + return ""; + } + } + + /** + * 从html中获取章节列表 + * + * @param html + * @return + */ + public ArrayList getChaptersFromHtml(String html) { + ArrayList chapters = new ArrayList<>(); + Document doc = Jsoup.parse(html); + Element divList = doc.getElementById("list"); + Elements elementsByClass = divList.getElementsByTag("dd"); + int i = 0; + for (Element div : elementsByClass) { + Element a = div.getElementsByTag("a").first(); + String title = a.text(); + String url = NAME_SPACE + a.attr("href"); + Chapter chapter = new Chapter(); + chapter.setNumber(i++); + chapter.setTitle(title); + chapter.setUrl(url); + chapters.add(chapter); + } + return chapters; + } + + /** + * 从搜索html中得到书列表 + * + * @param html + * @return + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String html) { + ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); + try { + Document doc = Jsoup.parse(html); + Elements divs = doc.getElementsByClass("result-list"); + Element div = divs.get(0); + Elements elementsByTag = div.getElementsByClass("result-item"); + for (Element element : elementsByTag) { + Book book = new Book(); + Element info = element.getElementsByTag("h3").first(); + book.setName(info.getElementsByTag("a").first().text()); + book.setChapterUrl(NAME_SPACE + info.getElementsByTag("a").first().attr("href")); + book.setAuthor(element.getElementsByTag("span").get(1).text()); + book.setType(element.getElementsByTag("span").get(3).text()); + book.setNewestChapterTitle(element.getElementsByTag("p").get(4).getElementsByTag("a").first().text()); + book.setImgUrl(element.getElementsByTag("img").first().attr("src")); + book.setDesc(element.getElementsByClass("result-game-item-desc").text()); + book.setSource(BookSource.qiqi.toString()); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } + } catch (Exception e) { + e.printStackTrace(); + } + return books; + } + + +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/QuanNovelReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/QuanNovelReadCrawler.java new file mode 100644 index 0000000..137ad85 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/QuanNovelReadCrawler.java @@ -0,0 +1,147 @@ +package xyz.fycz.myreader.webapi.crawler.read; + +import android.text.Html; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.TextNode; +import org.jsoup.select.Elements; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + +import java.util.ArrayList; + + +public class QuanNovelReadCrawler implements ReadCrawler, BookInfoCrawler { + public static final String NAME_SPACE = "https://qxs.la"; + public static final String NOVEL_SEARCH = "https://qxs.la/s_{key}"; + public static final String CHARSET = "GBK"; + public static final String SEARCH_CHARSET = "UTF-8"; + + @Override + public String getSearchLink() { + return NOVEL_SEARCH; + } + + @Override + public String getCharset() { + return CHARSET; + } + + @Override + public String getNameSpace() { + return NAME_SPACE; + } + + @Override + public Boolean isPost() { + return false; + } + + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + + /** + * 从html中获取章节正文 + * + * @param html + * @return + */ + public String getContentFormHtml(String html) { + Document doc = Jsoup.parse(html); + Element divContent = doc.getElementById("content"); + if (divContent != null) { + StringBuilder sb = new StringBuilder(); + for (TextNode textNode : divContent.textNodes()){ + sb.append(textNode.text()); + sb.append("\n"); + } + String content = sb.toString(); + char c = 160; + String spaec = "" + c; + content = content.replace(spaec, " ").replaceAll("\\s*您可以.*最.*章节.*", ""); + return content; + } else { + return ""; + } + } + + /** + * 从html中获取章节列表 + * + * @param html + * @return + */ + public ArrayList getChaptersFromHtml(String html) { + ArrayList chapters = new ArrayList<>(); + Document doc = Jsoup.parse(html); + Element divList = doc.getElementsByClass("chapters").first(); + Elements elementsByClass = divList.getElementsByClass("chapter"); + int i = 0; + for (Element div : elementsByClass) { + Element a = div.getElementsByTag("a").first(); + String title = a.text(); + String url = NAME_SPACE + a.attr("href"); + Chapter chapter = new Chapter(); + chapter.setNumber(i++); + chapter.setTitle(title); + chapter.setUrl(url); + chapters.add(chapter); + } + return chapters; + } + + /** + * 从搜索html中得到书列表 + * + * @param html + * @return + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String html) { + ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); + try { + Document doc = Jsoup.parse(html); + Elements divs = doc.getElementsByClass("main list"); + Element div = divs.get(0); + Elements elementsByTag = div.getElementsByTag("ul"); + for (int i = 1; i < elementsByTag.size(); i++) { + Element element = elementsByTag.get(i); + Book book = new Book(); + Element info = element.getElementsByClass("cc2").first(); + book.setName(info.getElementsByTag("a").first().text()); + book.setChapterUrl(NAME_SPACE + info.getElementsByTag("a").first().attr("href")); + book.setAuthor(element.getElementsByClass("cc4").first().getElementsByTag("a").first().text()); + book.setNewestChapterTitle(element.getElementsByClass("cc3").first().getElementsByTag("a").first().text()); + book.setSource(BookSource.quannovel.toString()); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } + } catch (Exception e) { + e.printStackTrace(); + } + return books; + } + + /** + * 获取书籍详细信息 + * + * @param book + */ + public Book getBookInfo(String html, Book book) { + Document doc = Jsoup.parse(html); + String type = doc.getElementsByClass("f_l t_r w3").text().replace("类型:", ""); + book.setType(type); + String desc = doc.getElementsByClass("desc").text().replace("简介:", ""); + book.setDesc(desc); + + return book; + } + +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/SoNovelReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/SoNovelReadCrawler.java new file mode 100644 index 0000000..3f91783 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/SoNovelReadCrawler.java @@ -0,0 +1,152 @@ +package xyz.fycz.myreader.webapi.crawler.read; + +import android.text.Html; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.TextNode; +import org.jsoup.select.Elements; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + +import java.util.ArrayList; +import java.util.List; + + +public class SoNovelReadCrawler implements ReadCrawler, BookInfoCrawler { + public static final String NAME_SPACE = "https://www.soxs.cc"; + public static final String NOVEL_SEARCH = "https://www.soxs.cc/search.html,searchtype=all&searchkey={key}"; + public static final String CHARSET = "UTF-8"; + public static final String SEARCH_CHARSET = "UTF-8"; + + @Override + public String getSearchLink() { + return NOVEL_SEARCH; + } + + @Override + public String getCharset() { + return CHARSET; + } + + @Override + public String getNameSpace() { + return NAME_SPACE; + } + + @Override + public Boolean isPost() { + return true; + } + + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + + /** + * 从html中获取章节正文 + * + * @param html + * @return + */ + public String getContentFormHtml(String html) { + Document doc = Jsoup.parse(html); + Element divContent = doc.getElementsByClass("content").first(); + if (divContent != null) { + StringBuilder sb = new StringBuilder(); + for (TextNode textNode : divContent.textNodes()){ + sb.append(textNode.text()); + sb.append("\n"); + } + String content = sb.toString(); + char c = 160; + String spaec = "" + c; + content = content.replace(spaec, " ").replaceAll("\\s*您可以.*最.*章节.*", ""); + return content; + } else { + return ""; + } + } + + /** + * 从html中获取章节列表 + * + * @param html + * @return + */ + public ArrayList getChaptersFromHtml(String html) { + ArrayList chapters = new ArrayList<>(); + Document doc = Jsoup.parse(html); + Element divList = doc.getElementsByClass("novel_list").get(1); + Elements elementsByTag = divList.getElementsByTag("dd"); + int i = 0; + for (Element dd : elementsByTag) { + Element a = dd.getElementsByTag("a").first(); + String title = a.text(); + String url = NAME_SPACE + a.attr("href"); + Chapter chapter = new Chapter(); + chapter.setNumber(i++); + chapter.setTitle(title); + chapter.setUrl(url); + chapters.add(chapter); + } + return chapters; + } + + /** + * 从搜索html中得到书列表 + * + * @param html + * @return + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String html) { + ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); + try { + Document doc = Jsoup.parse(html); + Elements divs = doc.getElementsByClass("novelslist2"); + Element div = divs.get(0); + Elements elementsByTag = div.getElementsByTag("li"); + for (int i = 1; i < elementsByTag.size(); i++) { + Element element = elementsByTag.get(i); + Book book = new Book(); + Element info = element.getElementsByClass("s2").first(); + book.setName(info.text()); + book.setChapterUrl(NAME_SPACE + info.getElementsByTag("a").attr("href")); + book.setAuthor(element.getElementsByClass("s4").first().text()); + book.setType(element.getElementsByTag("span").first().text()); + book.setNewestChapterTitle(element.getElementsByClass("s3").first().text()); + book.setSource(BookSource.sonovel.toString()); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } + } catch (Exception e) { + e.printStackTrace(); + } + return books; + } + + /** + * 获取书籍详细信息 + * + * @param book + */ + public Book getBookInfo(String html, Book book) { + Document doc = Jsoup.parse(html); + Element img = doc.getElementsByClass("book_cover").first(); + book.setImgUrl(img.getElementsByTag("img").get(0).attr("src")); + List descNodes = doc.getElementById("intro").textNodes(); + if (descNodes != null && descNodes.size() > 0) { + String desc = descNodes.get(0).text(); + book.setDesc(desc); + } + + return book; + } + +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/TianLaiReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/TianLaiReadCrawler.java similarity index 94% rename from app/src/main/java/xyz/fycz/myreader/webapi/crawler/TianLaiReadCrawler.java rename to app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/TianLaiReadCrawler.java index bfdd692..c891ecc 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/TianLaiReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/TianLaiReadCrawler.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.webapi.crawler; +package xyz.fycz.myreader.webapi.crawler.read; import android.text.Html; @@ -10,8 +10,9 @@ import xyz.fycz.myreader.entity.SearchBookBean; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; import xyz.fycz.myreader.util.StringHelper; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import java.util.ArrayList; @@ -20,10 +21,9 @@ import java.util.ArrayList; * Created by zhao on 2017/7/24. */ -public class TianLaiReadCrawler implements ReadCrawler{ +public class TianLaiReadCrawler implements ReadCrawler { public static final String NAME_SPACE = "https://www.23txt.com"; - public static final String NOVEL_SEARCH = "https://www.23txt.com/search.php"; - public static final String SEARCH_KEY = "q"; + public static final String NOVEL_SEARCH = "https://www.23txt.com/search.php?q={key}"; public static final String CHARSET = "GBK"; public static final String SEARCH_CHARSET = "utf-8"; @@ -40,12 +40,10 @@ public class TianLaiReadCrawler implements ReadCrawler{ public String getNameSpace() { return NAME_SPACE; } - @Override - public String getSearchKey() { - return SEARCH_KEY; + public Boolean isPost() { + return false; } - @Override public String getSearchCharset() { return SEARCH_CHARSET; diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/YunZhongReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/YunZhongReadCrawler.java new file mode 100644 index 0000000..a25af51 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/YunZhongReadCrawler.java @@ -0,0 +1,156 @@ +package xyz.fycz.myreader.webapi.crawler.read; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.TextNode; +import org.jsoup.select.Elements; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + +import java.util.ArrayList; + + +public class YunZhongReadCrawler implements ReadCrawler, BookInfoCrawler { + public static final String NAME_SPACE = "http://www.yunxs.com"; + public static final String NOVEL_SEARCH = "http://www.yunxs.com/plus/search.php?q={key}"; + public static final String CHARSET = "UTF-8"; + public static final String SEARCH_CHARSET = "UTF-8"; + + @Override + public String getSearchLink() { + return NOVEL_SEARCH; + } + + @Override + public String getCharset() { + return CHARSET; + } + + @Override + public String getNameSpace() { + return NAME_SPACE; + } + + @Override + public Boolean isPost() { + return false; + } + + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + + /** + * 从html中获取章节正文 + * + * @param html + * @return + */ + public String getContentFormHtml(String html) { + Document doc = Jsoup.parse(html); + Element divContent = doc.getElementsByClass("box_box").first(); + if (divContent != null) { + StringBuilder sb = new StringBuilder(); + for (TextNode textNode : divContent.textNodes()){ + sb.append(textNode.text()); + sb.append("\n"); + } + String content = sb.toString(); + char c = 160; + String spaec = "" + c; + content = content.replace(spaec, " "); + return content; + } else { + return ""; + } + } + + /** + * 从html中获取章节列表 + * + * @param html + * @return + */ + public ArrayList getChaptersFromHtml(String html) { + ArrayList chapters = new ArrayList<>(); + try { + Document doc = Jsoup.parse(html); + String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); + Element divList = doc.getElementsByClass("list_box").first(); + Elements elementsByTag = divList.getElementsByTag("a"); + int i = 0; + for (Element a : elementsByTag) { + String title = a.text(); + String url = readUrl + a.attr("href"); + Chapter chapter = new Chapter(); + chapter.setNumber(i++); + chapter.setTitle(title); + chapter.setUrl(url); + chapters.add(chapter); + } + } catch (Exception e) { + e.printStackTrace(); + } + return chapters; + } + + /** + * 从搜索html中得到书列表 + * + * @param html + * @return + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String html) { + ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); +// try { + Document doc = Jsoup.parse(html); + Elements divs = doc.getElementsByClass("ul_b_list"); + Element div = divs.get(0); + Elements elementsByTag = div.getElementsByTag("li"); + for (Element element : elementsByTag) { + Book book = new Book(); + Element info = element.getElementsByTag("h2").first(); + book.setName(info.getElementsByTag("a").first().text()); + book.setType(info.getElementsByTag("span").first().text()); + book.setAuthor(element.getElementsByClass("state").first().text().replaceAll("作者.|类型.*", "")); + book.setImgUrl(NAME_SPACE + element.getElementsByClass("pic").first().getElementsByTag("img").first().attr("src")); + book.setChapterUrl(NAME_SPACE + element.getElementsByTag("a").first().attr("href")); + book.setNewestChapterTitle(""); + book.setSource(BookSource.yunzhong.toString()); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } +// } catch (Exception e) { +// e.printStackTrace(); +// } + return books; + } + + /** + * 获取书籍详细信息 + * + * @param book + */ + public Book getBookInfo(String html, Book book) { + Document doc = Jsoup.parse(html); + + try { + String newestChapter = doc.select("meta[property=og:novel:latest_chapter_name]").attr("content"); + book.setNewestChapterTitle(newestChapter); + String desc = doc.getElementsByClass("words").first().getElementsByTag("p").get(2).text().replace("简介:", ""); + book.setDesc(desc); + } catch (Exception e) { + e.printStackTrace(); + } + + return book; + } + +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ZuoPinReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ZuoPinReadCrawler.java new file mode 100644 index 0000000..6ea7b19 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ZuoPinReadCrawler.java @@ -0,0 +1,133 @@ +package xyz.fycz.myreader.webapi.crawler.read; + +import android.text.Html; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + +import java.util.ArrayList; + + +public class ZuoPinReadCrawler implements ReadCrawler, BookInfoCrawler { + public static final String NAME_SPACE = "http://zuopinj.com"; + public static final String NOVEL_SEARCH = "http://so.zuopinj.com/search/index.php,tbname=bookname&show=title&tempid=3&keyboard={key}"; + public static final String CHARSET = "UTF-8"; + public static final String SEARCH_CHARSET = "UTF-8"; + + @Override + public String getSearchLink() { + return NOVEL_SEARCH; + } + + @Override + public String getCharset() { + return CHARSET; + } + + @Override + public String getNameSpace() { + return NAME_SPACE; + } + + @Override + public Boolean isPost() { + return true; + } + + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + + /** + * 从html中获取章节正文 + * + * @param html + * @return + */ + public String getContentFormHtml(String html) { + Document doc = Jsoup.parse(html); + Element divContent = doc.getElementById("htmlContent"); + if (divContent != null) { + String content = Html.fromHtml(divContent.html()).toString(); + char c = 160; + String spaec = "" + c; + content = content.replace(spaec, " "); + return content; + } else { + return ""; + } + } + + /** + * 从html中获取章节列表 + * + * @param html + * @return + */ + public ArrayList getChaptersFromHtml(String html) { + ArrayList chapters = new ArrayList<>(); + Document doc = Jsoup.parse(html); + Element divList = doc.getElementsByClass("book_list").first(); + Elements elementsByTag = divList.getElementsByTag("a"); + int i = 0; + for (Element a : elementsByTag) { + String title = a.text(); + String url = a.attr("href"); + Chapter chapter = new Chapter(); + chapter.setNumber(i++); + chapter.setTitle(title); + chapter.setUrl(url); + chapters.add(chapter); + } + return chapters; + } + + /** + * 从搜索html中得到书列表 + * + * @param html + * @return + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String html) { + ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); + Document doc = Jsoup.parse(html); + Element div = doc.getElementById("J_TableContainer"); + Elements elementsByClass = div.getElementsByClass("search-bookele"); + for (Element element : elementsByClass) { + Book book = new Book(); + book.setName(element.getElementsByTag("h3").get(0).text()); + book.setChapterUrl(element.getElementsByTag("a").attr("href")); + book.setAuthor(""); + book.setNewestChapterTitle(""); + book.setImgUrl(element.getElementsByTag("img").first().attr("src")); + book.setDesc(element.getElementsByTag("p").first().text()); + book.setSource(BookSource.zuopin.toString()); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } + return books; + } + + @Override + public Book getBookInfo(String html, Book book) { + Document doc = Jsoup.parse(html); + Element info = doc.getElementsByClass("infos").first(); + String author = info.getElementsByTag("span").get(0).text(); + author = author.substring(author.indexOf("作者:") + 3, author.indexOf("最后")); + book.setAuthor(author); + String newestChapter = doc.getElementsByClass("upd").first().getElementsByTag("a").first().text(); + book.setNewestChapterTitle(newestChapter); + book.setDesc(doc.getElementsByTag("p").first().text()); + return book; + } + +} diff --git a/app/src/main/java/xyz/fycz/myreader/widget/RefreshProgressBar.java b/app/src/main/java/xyz/fycz/myreader/widget/RefreshProgressBar.java new file mode 100644 index 0000000..155b9f7 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/widget/RefreshProgressBar.java @@ -0,0 +1,249 @@ +package xyz.fycz.myreader.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.os.Looper; +import android.util.AttributeSet; +import android.view.View; +import xyz.fycz.myreader.R; + +public class RefreshProgressBar extends View { + int a = 1; + private int maxProgress = 100; + private int durProgress = 0; + private int secondMaxProgress = 100; + private int secondDurProgress = 0; + private int bgColor = 0x00000000; + private int secondColor = 0xFFC1C1C1; + private int fontColor = 0xFF363636; + private int speed = 1; + private int secondFinalProgress = 0; + private Paint paint; + private Boolean isAutoLoading = false; + private Rect bgRect = new Rect(); + private Rect secondRect = new Rect(); + private RectF fontRectF = new RectF(); + + public RefreshProgressBar(Context context) { + this(context, null); + } + + public RefreshProgressBar(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public RefreshProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + init(context, attrs, defStyleAttr); + } + + public Boolean getIsAutoLoading() { + return isAutoLoading; + } + + public void setIsAutoLoading(Boolean loading) { + if (loading && getVisibility() != View.VISIBLE) { + setVisibility(View.VISIBLE); + } + isAutoLoading = loading; + if (!isAutoLoading) { + secondDurProgress = 0; + secondFinalProgress = 0; + } + maxProgress = 0; + + invalidate(); + } + + private void init(Context context, AttributeSet attrs, int defStyleAttr) { + paint = new Paint(); + paint.setStyle(Paint.Style.FILL); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RefreshProgressBar); + speed = a.getDimensionPixelSize(R.styleable.RefreshProgressBar_speed, speed); + maxProgress = a.getInt(R.styleable.RefreshProgressBar_max_progress, maxProgress); + durProgress = a.getInt(R.styleable.RefreshProgressBar_dur_progress, durProgress); + secondDurProgress = a.getDimensionPixelSize(R.styleable.RefreshProgressBar_second_dur_progress, secondDurProgress); + secondFinalProgress = secondDurProgress; + secondMaxProgress = a.getDimensionPixelSize(R.styleable.RefreshProgressBar_second_max_progress, secondMaxProgress); + bgColor = a.getColor(R.styleable.RefreshProgressBar_bg_color, bgColor); + secondColor = a.getColor(R.styleable.RefreshProgressBar_second_color, secondColor); + fontColor = a.getColor(R.styleable.RefreshProgressBar_font_color, fontColor); + a.recycle(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + paint.setColor(bgColor); + bgRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + canvas.drawRect(bgRect, paint); + + if (secondDurProgress > 0 && secondMaxProgress > 0) { + int secondDur = secondDurProgress; + if (secondDur > secondMaxProgress) { + secondDur = secondMaxProgress; + } + paint.setColor(secondColor); + int tempW = (int) (getMeasuredWidth() * 1.0f * (secondDur * 1.0f / secondMaxProgress)); + secondRect.set(getMeasuredWidth() / 2 - tempW / 2, 0, getMeasuredWidth() / 2 + tempW / 2, getMeasuredHeight()); + canvas.drawRect(secondRect, paint); + } + + if (durProgress > 0 && maxProgress > 0) { + paint.setColor(fontColor); + fontRectF.set(0, 0, getMeasuredWidth() * 1.0f * (durProgress * 1.0f / maxProgress), getMeasuredHeight()); + canvas.drawRect(fontRectF, paint); + } + + if (isAutoLoading) { + if (secondDurProgress >= secondMaxProgress) { + a = -1; + } else if (secondDurProgress <= 0) { + a = 1; + } + secondDurProgress += (a * speed); + if (secondDurProgress < 0) + secondDurProgress = 0; + else if (secondDurProgress > secondMaxProgress) + secondDurProgress = secondMaxProgress; + secondFinalProgress = secondDurProgress; + invalidate(); + } else { + if (secondDurProgress != secondFinalProgress) { + if (secondDurProgress > secondFinalProgress) { + secondDurProgress -= speed; + if (secondDurProgress < secondFinalProgress) { + secondDurProgress = secondFinalProgress; + } + } else { + secondDurProgress += speed; + if (secondDurProgress > secondFinalProgress) { + secondDurProgress = secondFinalProgress; + } + } + this.invalidate(); + } + if (secondDurProgress == 0 && durProgress == 0 && secondFinalProgress == 0 && getVisibility() == View.VISIBLE) { + setVisibility(View.INVISIBLE); + } + } + } + + public int getMaxProgress() { + return maxProgress; + } + + public void setMaxProgress(int maxProgress) { + this.maxProgress = maxProgress; + } + + public int getDurProgress() { + return durProgress; + } + + public void setDurProgress(int durProgress) { + if (durProgress < 0) { + durProgress = 0; + } + if (durProgress > maxProgress) { + durProgress = maxProgress; + } + this.durProgress = durProgress; + if (Looper.myLooper() == Looper.getMainLooper()) { + this.invalidate(); + } else { + this.postInvalidate(); + } + } + + public int getSecondMaxProgress() { + return secondMaxProgress; + } + + public void setSecondMaxProgress(int secondMaxProgress) { + this.secondMaxProgress = secondMaxProgress; + } + + public int getSecondDurProgress() { + return secondDurProgress; + } + + public void setSecondDurProgress(int secondDur) { + this.secondDurProgress = secondDur; + this.secondFinalProgress = secondDurProgress; + if (Looper.myLooper() == Looper.getMainLooper()) { + this.invalidate(); + } else { + this.postInvalidate(); + } + } + + public void setSecondDurProgressWithAnim(int secondDur) { + if (secondDur < 0) { + secondDur = 0; + } + if (secondDur > secondMaxProgress) { + secondDur = secondMaxProgress; + } + this.secondFinalProgress = secondDur; + if (Looper.myLooper() == Looper.getMainLooper()) { + this.invalidate(); + } else { + this.postInvalidate(); + } + } + + public void clean() { + durProgress = 0; + secondDurProgress = 0; + secondFinalProgress = 0; + if (Looper.myLooper() == Looper.getMainLooper()) { + this.invalidate(); + } else { + this.postInvalidate(); + } + } + + public int getBgColor() { + return bgColor; + } + + public void setBgColor(int bgColor) { + this.bgColor = bgColor; + } + + public int getSecondColor() { + return secondColor; + } + + public void setSecondColor(int secondColor) { + this.secondColor = secondColor; + } + + public int getFontColor() { + return fontColor; + } + + public void setFontColor(int fontColor) { + this.fontColor = fontColor; + } + + public int getSpeed() { + return speed; + } + + public void setSpeed(int speed) { + this.speed = speed; + } + + public int getSecondFinalProgress() { + return secondFinalProgress; + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/custom/BaseImageView.java b/app/src/main/java/xyz/fycz/myreader/widget/custom/BaseImageView.java similarity index 98% rename from app/src/main/java/xyz/fycz/myreader/custom/BaseImageView.java rename to app/src/main/java/xyz/fycz/myreader/widget/custom/BaseImageView.java index 193ac68..7e1f828 100644 --- a/app/src/main/java/xyz/fycz/myreader/custom/BaseImageView.java +++ b/app/src/main/java/xyz/fycz/myreader/widget/custom/BaseImageView.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.custom; +package xyz.fycz.myreader.widget.custom; import android.annotation.SuppressLint; import android.content.Context; diff --git a/app/src/main/java/xyz/fycz/myreader/custom/CircleImageView.java b/app/src/main/java/xyz/fycz/myreader/widget/custom/CircleImageView.java similarity index 99% rename from app/src/main/java/xyz/fycz/myreader/custom/CircleImageView.java rename to app/src/main/java/xyz/fycz/myreader/widget/custom/CircleImageView.java index 8c436da..f2ed08d 100644 --- a/app/src/main/java/xyz/fycz/myreader/custom/CircleImageView.java +++ b/app/src/main/java/xyz/fycz/myreader/widget/custom/CircleImageView.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package xyz.fycz.myreader.custom; +package xyz.fycz.myreader.widget.custom; import android.content.Context; import android.content.res.TypedArray; diff --git a/app/src/main/java/xyz/fycz/myreader/custom/ContainsEmojiEditText.java b/app/src/main/java/xyz/fycz/myreader/widget/custom/ContainsEmojiEditText.java similarity index 99% rename from app/src/main/java/xyz/fycz/myreader/custom/ContainsEmojiEditText.java rename to app/src/main/java/xyz/fycz/myreader/widget/custom/ContainsEmojiEditText.java index 0589023..65c7900 100644 --- a/app/src/main/java/xyz/fycz/myreader/custom/ContainsEmojiEditText.java +++ b/app/src/main/java/xyz/fycz/myreader/widget/custom/ContainsEmojiEditText.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.custom; +package xyz.fycz.myreader.widget.custom; /** * Created by zhao on 2017/2/10. diff --git a/app/src/main/java/xyz/fycz/myreader/custom/DragAdapter.java b/app/src/main/java/xyz/fycz/myreader/widget/custom/DragAdapter.java similarity index 95% rename from app/src/main/java/xyz/fycz/myreader/custom/DragAdapter.java rename to app/src/main/java/xyz/fycz/myreader/widget/custom/DragAdapter.java index 71eb08f..3a6f9e2 100644 --- a/app/src/main/java/xyz/fycz/myreader/custom/DragAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/widget/custom/DragAdapter.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.custom; +package xyz.fycz.myreader.widget.custom; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/xyz/fycz/myreader/custom/DragFloatBtnT.java b/app/src/main/java/xyz/fycz/myreader/widget/custom/DragFloatBtnT.java similarity index 99% rename from app/src/main/java/xyz/fycz/myreader/custom/DragFloatBtnT.java rename to app/src/main/java/xyz/fycz/myreader/widget/custom/DragFloatBtnT.java index b076d50..b51299a 100644 --- a/app/src/main/java/xyz/fycz/myreader/custom/DragFloatBtnT.java +++ b/app/src/main/java/xyz/fycz/myreader/widget/custom/DragFloatBtnT.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.custom; +package xyz.fycz.myreader.widget.custom; import android.annotation.SuppressLint; import android.content.Context; diff --git a/app/src/main/java/xyz/fycz/myreader/custom/DragSortGridView.java b/app/src/main/java/xyz/fycz/myreader/widget/custom/DragSortGridView.java similarity index 99% rename from app/src/main/java/xyz/fycz/myreader/custom/DragSortGridView.java rename to app/src/main/java/xyz/fycz/myreader/widget/custom/DragSortGridView.java index 8d8264c..e620916 100644 --- a/app/src/main/java/xyz/fycz/myreader/custom/DragSortGridView.java +++ b/app/src/main/java/xyz/fycz/myreader/widget/custom/DragSortGridView.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.custom; +package xyz.fycz.myreader.widget.custom; import android.animation.ValueAnimator; import android.annotation.SuppressLint; diff --git a/app/src/main/java/xyz/fycz/myreader/custom/MyTextView.java b/app/src/main/java/xyz/fycz/myreader/widget/custom/MyTextView.java similarity index 97% rename from app/src/main/java/xyz/fycz/myreader/custom/MyTextView.java rename to app/src/main/java/xyz/fycz/myreader/widget/custom/MyTextView.java index 56704d0..3308d01 100644 --- a/app/src/main/java/xyz/fycz/myreader/custom/MyTextView.java +++ b/app/src/main/java/xyz/fycz/myreader/widget/custom/MyTextView.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.custom; +package xyz.fycz.myreader.widget.custom; import android.content.Context; diff --git a/app/src/main/java/xyz/fycz/myreader/custom/ReadTextView.java b/app/src/main/java/xyz/fycz/myreader/widget/custom/ReadTextView.java similarity index 85% rename from app/src/main/java/xyz/fycz/myreader/custom/ReadTextView.java rename to app/src/main/java/xyz/fycz/myreader/widget/custom/ReadTextView.java index 426fb96..7c3ddba 100644 --- a/app/src/main/java/xyz/fycz/myreader/custom/ReadTextView.java +++ b/app/src/main/java/xyz/fycz/myreader/widget/custom/ReadTextView.java @@ -1,4 +1,4 @@ -package xyz.fycz.myreader.custom; +package xyz.fycz.myreader.widget.custom; import android.content.Context; import android.widget.TextView; diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page/LocalPageLoader.java b/app/src/main/java/xyz/fycz/myreader/widget/page/LocalPageLoader.java index 9a1cff2..ebbb13e 100644 --- a/app/src/main/java/xyz/fycz/myreader/widget/page/LocalPageLoader.java +++ b/app/src/main/java/xyz/fycz/myreader/widget/page/LocalPageLoader.java @@ -4,7 +4,7 @@ import android.util.Log; import io.reactivex.*; import io.reactivex.disposables.Disposable; import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.entity.Void; @@ -19,7 +19,6 @@ import xyz.fycz.myreader.util.utils.RxUtils; import java.io.*; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page/NetPageLoader.java b/app/src/main/java/xyz/fycz/myreader/widget/page/NetPageLoader.java index cc32f45..6cef6bb 100644 --- a/app/src/main/java/xyz/fycz/myreader/widget/page/NetPageLoader.java +++ b/app/src/main/java/xyz/fycz/myreader/widget/page/NetPageLoader.java @@ -1,13 +1,13 @@ package xyz.fycz.myreader.widget.page; -import xyz.fycz.myreader.callback.ResultCallback; +import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Chapter; import xyz.fycz.myreader.greendao.service.ChapterService; -import xyz.fycz.myreader.webapi.crawler.ReadCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import xyz.fycz.myreader.util.utils.FileUtils; import xyz.fycz.myreader.webapi.CommonApi; diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page/PageLoader.java b/app/src/main/java/xyz/fycz/myreader/widget/page/PageLoader.java index 2dc8b9e..7068be1 100644 --- a/app/src/main/java/xyz/fycz/myreader/widget/page/PageLoader.java +++ b/app/src/main/java/xyz/fycz/myreader/widget/page/PageLoader.java @@ -1282,7 +1282,8 @@ public abstract class PageLoader { } //调用异步进行预加载加载 - Single.create((SingleOnSubscribe>) e -> e.onSuccess(loadPageList(nextChapter))).compose(RxUtils::toSimpleSingle) + Single.create((SingleOnSubscribe>) e -> e.onSuccess(loadPageList(nextChapter))) + .compose(RxUtils::toSimpleSingle) .subscribe(new SingleObserver>() { @Override public void onSubscribe(Disposable d) { diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page/PageView.java b/app/src/main/java/xyz/fycz/myreader/widget/page/PageView.java index 61e688b..24f26be 100644 --- a/app/src/main/java/xyz/fycz/myreader/widget/page/PageView.java +++ b/app/src/main/java/xyz/fycz/myreader/widget/page/PageView.java @@ -11,7 +11,7 @@ import android.view.ViewConfiguration; import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.service.ChapterService; -import xyz.fycz.myreader.webapi.crawler.ReadCrawler; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import xyz.fycz.myreader.widget.animation.*; /** diff --git a/app/src/main/res/drawable/ic_check.xml b/app/src/main/res/drawable/ic_check.xml new file mode 100644 index 0000000..620bc91 --- /dev/null +++ b/app/src/main/res/drawable/ic_check.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_more_setting.xml b/app/src/main/res/layout/activity_more_setting.xml index 57e3de9..72562e8 100644 --- a/app/src/main/res/layout/activity_more_setting.xml +++ b/app/src/main/res/layout/activity_more_setting.xml @@ -198,6 +198,29 @@ android:textColor="@color/textAssist" android:text="@string/disable_source_tip"/> + + + + - + + + - - - + + + + + - - + android:text="搜索" + android:textColor="@color/textPrimaryInverted" + android:textSize="18sp"/> - + + - + + + - - - - + + + app:srcCompat="@drawable/ic_refresh" + app:tint="@color/textPrimary"/> - + - + - + - + - + + + + android:orientation="horizontal"> - + - - - - - - + android:text="清空历史记录" + android:textColor="@color/textPrimary" + android:textSize="14sp"/> - + - + + + android:layout_height="match_parent"> @@ -163,7 +170,7 @@ android:overScrollMode="never" android:scrollbars="none"> --> - - + --> + - - + + + - diff --git a/app/src/main/res/layout/dialog_book_source.xml b/app/src/main/res/layout/dialog_book_source.xml new file mode 100644 index 0000000..7a28cfc --- /dev/null +++ b/app/src/main/res/layout/dialog_book_source.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/dialog_number_picker.xml b/app/src/main/res/layout/dialog_number_picker.xml new file mode 100644 index 0000000..b29fca0 --- /dev/null +++ b/app/src/main/res/layout/dialog_number_picker.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_read_setting.xml b/app/src/main/res/layout/dialog_read_setting.xml index ee0a930..311b075 100644 --- a/app/src/main/res/layout/dialog_read_setting.xml +++ b/app/src/main/res/layout/dialog_read_setting.xml @@ -63,25 +63,24 @@ android:paddingRight="10dp"> + app:tint="@color/little_black_white"/> + android:src="@drawable/ic_refresh" + app:tint="@color/little_black_white"/> + android:src="@drawable/ic_bookmark" + app:tint="@color/little_black_white"/> - - + + android:text="删除/移除"/> diff --git a/app/src/main/res/layout/item_change_source.xml b/app/src/main/res/layout/item_change_source.xml new file mode 100644 index 0000000..a1cd721 --- /dev/null +++ b/app/src/main/res/layout/item_change_source.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_about_content.xml b/app/src/main/res/layout/layout_about_content.xml index cb8acdd..2cf5121 100644 --- a/app/src/main/res/layout/layout_about_content.xml +++ b/app/src/main/res/layout/layout_about_content.xml @@ -70,7 +70,7 @@ android:layout_height="wrap_content" android:paddingBottom="6dp"> - @@ -35,7 +35,7 @@ android:layout_height="24dp" android:layout_marginTop="5dp" android:text="bookname" - android:maxLength="15" + android:maxLength="12" android:textSize="16sp" android:textColor="@color/textPrimary"/> @@ -66,9 +66,10 @@ android:layout_height="wrap_content" android:paddingBottom="2dp" android:text="book desc" - android:maxLines="3" + android:ellipsize="end" + android:maxLines="1" android:textSize="13sp" - android:textColor="@color/title_black"/> + android:textColor="@color/textSecondary"/> + diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index f364922..140ae64 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -39,4 +39,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1ca2a88..78cbd9f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -150,6 +150,11 @@ 问题反馈 分组切换 分组管理 + 设置分组 + 搜索线程数 + 当前线程数:%1$s + 最新章节:%1$s + 书源:%1$s 共%2$d个源 diff --git a/app/src/main/resources/crawler.properties b/app/src/main/resources/crawler.properties index 62458b6..ac95256 100644 --- a/app/src/main/resources/crawler.properties +++ b/app/src/main/resources/crawler.properties @@ -1,6 +1,16 @@ -tianlai=xyz.fycz.myreader.webapi.crawler.TianLaiReadCrawler -fynovel=xyz.fycz.myreader.webapi.crawler.FYReadCrawler -biquge44=xyz.fycz.myreader.webapi.crawler.BiQuGe44ReadCrawler -biquge=xyz.fycz.myreader.webapi.crawler.BiQuGeReadCrawler -pinshu=xyz.fycz.myreader.webapi.crawler.PinShuReadCrawler -qb5=xyz.fycz.myreader.webapi.crawler.QB5ReadCrawler \ No newline at end of file +tianlai=xyz.fycz.myreader.webapi.crawler.read.TianLaiReadCrawler +fynovel=xyz.fycz.myreader.webapi.crawler.read.FYReadCrawler +biquge44=xyz.fycz.myreader.webapi.crawler.read.BiQuGe44ReadCrawler +biquge=xyz.fycz.myreader.webapi.crawler.read.BiQuGeReadCrawler +pinshu=xyz.fycz.myreader.webapi.crawler.read.PinShuReadCrawler +qb5=xyz.fycz.myreader.webapi.crawler.read.QB5ReadCrawler +miqu=xyz.fycz.myreader.webapi.crawler.read.MiQuReadCrawler +chaoxing=xyz.fycz.myreader.webapi.crawler.read.ChaoXingReadCrawler +zuopin=xyz.fycz.myreader.webapi.crawler.read.ZuoPinReadCrawler +cangshu99=xyz.fycz.myreader.webapi.crawler.read.CansShu99ReadCrawler +ben100=xyz.fycz.myreader.webapi.crawler.read.Ben100ReadCrawler +jiutao=xyz.fycz.myreader.webapi.crawler.read.JiuTaoReadCrawler +yunzhong=xyz.fycz.myreader.webapi.crawler.read.YunZhongReadCrawler +sonovel=xyz.fycz.myreader.webapi.crawler.read.SoNovelReadCrawler +quannovel=xyz.fycz.myreader.webapi.crawler.read.QuanNovelReadCrawler +qiqi=xyz.fycz.myreader.webapi.crawler.read.QiQiReadCrawler \ No newline at end of file diff --git a/app/version_code.properties b/app/version_code.properties index 9d3cd74..c8b1c08 100644 --- a/app/version_code.properties +++ b/app/version_code.properties @@ -1,2 +1,2 @@ -#Sat Sep 26 17:54:16 CST 2020 -VERSION_CODE=147 +#Thu Oct 01 23:09:39 CST 2020 +VERSION_CODE=149