diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml index c6c5118..4a25623 100644 --- a/.idea/assetWizardSettings.xml +++ b/.idea/assetWizardSettings.xml @@ -19,8 +19,8 @@ diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index f4879e1..ba535aa 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml index 8bc84c2..56782ca 100644 --- a/.idea/sqldialects.xml +++ b/.idea/sqldialects.xml @@ -1,7 +1,6 @@ - \ No newline at end of file diff --git a/README.md b/README.md index 9120666..3d1c36c 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,199 @@ # FYReader-master 风月读书,一款开源、无广告的小说阅读软件。 - 11个网络小说书源:天籁小说、笔趣阁44、品书网、笔趣阁、 +demo下载:https://fycz.lanzoui.com/iBofFh42pxg + +#### 一、关于书源 + +* 软件内置了15个书源如下: + * 11个网络小说书源:天籁小说、笔趣阁44、品书网、笔趣阁、 全本小说、米趣小说、九桃小说、云中书库、 搜小说网、全小说网、奇奇小说 - 4个实体书书源:超星图书·实体、作品集·实体、99藏书·实体、100本·实体 - - 发现界面:排行榜、分类、书城 - - 详细功能可查看图片或下载自行体验或自行编译 - -demo下载:https://fycz.lanzoui.com/iBofFh42pxg + * 4个实体书书源:超星图书·实体、作品集·实体、99藏书·实体、100本·实体 + +* 如何自行制作并添加书源. + + * 基于面向接口开发的思想,对于书源我设计了如下接口: + + * ```java + // 这个接口位于xyz.fycz.myreader.webapi.crawler.base包下 + public interface ReadCrawler { + String getSearchLink(); // 书源的搜索url + String getCharset(); // 书源的字符编码 + String getSearchCharset(); // 书源搜索关键字的字符编码,和书源的字符编码就行 + String getNameSpace(); // 书源主页地址 + Boolean isPost(); // 是否以post请求搜索 + String getContentFormHtml(String html); // 获取书籍内容规则 + ArrayList getChaptersFromHtml(String html); // 获取书籍章节列表规则 + ConcurrentMultiValueMap getBooksFromSearchHtml(String html); // 搜索书籍规则 + } + ``` + + * 了解上述接口的方法,我们就可以开始创建书源了 + + * 第一步:创建一个书源类实现上述接口,下面以笔趣阁44为例进行说明 + + * ```java + // 注意:如果搜索书籍页没有图片、最新章节、书籍简介等信息,可以通过实现BookInfoCrawler接口,从书籍详情页获取 + public class BiQuGe44ReadCrawler implements ReadCrawler, BookInfoCrawler { + //网站主页地址 + public static final String NAME_SPACE = "https://www.wqge.cc"; + /* + 搜索url,搜索关键词以{key}进行占位 + 如果是post请求,以“,”分隔url,“,”前是搜索地址,“,”后是请求体,搜索关键词同样以{key}占位 + 例如:"https://www.9txs.com/search.html,searchkey={key}" + */ + 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 + 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); + String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); + Element divList = doc.getElementById("list"); + String lastTile = null; + int i = 0; + Elements elementsByTag = divList.getElementsByTag("dd"); + for (int j = 9; j < elementsByTag.size(); j++) { + Element dd = elementsByTag.get(j); + Elements as = dd.getElementsByTag("a"); + if (as.size() > 0) { + Element a = as.get(0); + String title = a.text() ; + if (!StringHelper.isEmpty(lastTile) && title.equals(lastTile)) { + continue; + } + Chapter chapter = new Chapter(); + chapter.setNumber(i++); + chapter.setTitle(title); + String url = readUrl + a.attr("href"); + chapter.setUrl(url); + chapters.add(chapter); + lastTile = title; + } + } + return chapters; + } + + /** + * 从搜索html中得到书列表 + * @param html + * @return + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String html) { + ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); + Document doc = Jsoup.parse(html); + Elements divs = doc.getElementsByTag("table"); + Element div = divs.get(0); + Elements elementsByTag = div.getElementsByTag("tr"); + for (int i = 1; i < elementsByTag.size(); i++) { + Element element = elementsByTag.get(i); + Book book = new Book(); + Elements info = element.getElementsByTag("td"); + book.setName(info.get(0).text()); + book.setChapterUrl(NAME_SPACE + info.get(0).getElementsByTag("a").attr("href")); + book.setAuthor(info.get(2).text()); + book.setNewestChapterTitle(info.get(1).text()); + book.setSource(BookSource.biquge44.toString()); + // SearchBookBean用于合并相同书籍 + 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.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; + } + + } + ``` + + * 第二步:注册书源信息。有两个地方需要注册: + + * 1)在xyz.fycz.myreader.enums.BookSource类(这是个枚举类型)中添加你的书源的命名以及书源名称,例如: + + * ```java + biquge44("笔趣阁44") // biquge44是书源的命名,笔趣阁44是书源名称 + ``` + + * 2)在app/src/main/resources/crawler.properties配置文件中添加书源类信息,例如: + + * ```java + // biquge44书源的命名,与BookSource中的命名一致,xyz.fycz.myreader.webapi.crawler.read.BiQuGe44ReadCrawler是书源类的完整路径 + biquge44=xyz.fycz.myreader.webapi.crawler.read.BiQuGe44ReadCrawler + ``` + + * 第三步:启用书源(新增的书源默认禁用)。只需在软件内-我的-设置-禁用书源中取消该书源的禁用即可。 + +#### 二、关于发现界面 + +* 软件内置的两个发现源: + * 某点的排行榜、分类,全本小说网 + * 制作发现源方法与书源类似,在此不再赘述 + -如有问题请加QQ群:1085028304 ![Image](https://github.com/fengyuecanzhu/FYReader/tree/master/img/1.png) ![Image](https://github.com/fengyuecanzhu/FYReader/tree/master/img/2.png) @@ -22,5 +203,4 @@ demo下载:https://fycz.lanzoui.com/iBofFh42pxg ![Image](https://github.com/fengyuecanzhu/FYReader/tree/master/img/6.png) ![Image](https://github.com/fengyuecanzhu/FYReader/tree/master/img/7.png) ![Image](https://github.com/fengyuecanzhu/FYReader/tree/master/img/8.png) -![Image](https://github.com/fengyuecanzhu/FYReader/tree/master/img/9.png) -![Image](https://github.com/fengyuecanzhu/FYReader/tree/master/img/10.png) \ No newline at end of file +![Image](https://github.com/fengyuecanzhu/FYReader/tree/master/img/9.png) \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 2c03329..81ffd48 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -138,6 +138,9 @@ dependencies { //RxAndroid implementation 'io.reactivex.rxjava2:rxjava:2.2.19' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' + + //ImmersionBar + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' } greendao { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e66becc..1f4a8a7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -110,10 +110,6 @@ - - - - diff --git a/app/src/main/assets/updatelog.fy b/app/src/main/assets/updatelog.fy index e998b38..63a8cae 100644 --- a/app/src/main/assets/updatelog.fy +++ b/app/src/main/assets/updatelog.fy @@ -1,3 +1,16 @@ +2020.11.03 +风月读书v1.20.1110311 +1、修复已知bug +2、新增WebDav备份教程 + +2020.10.22 +风月读书v1.20.102217 +1、优化阅读界面菜单 +2、新增阅读内容拷贝对话框 +3、优化备份与恢复(支持备份书签、搜索历史) +4、新增WebDav服务(可将书籍备份至WebDav服务器) +5、修复已知问题 + 2020.10.03 风月读书v1.20.100315 1、优化搜索书籍高频刷新的问题 diff --git a/app/src/main/assets/webdavhelp.fy b/app/src/main/assets/webdavhelp.fy new file mode 100644 index 0000000..0013f79 --- /dev/null +++ b/app/src/main/assets/webdavhelp.fy @@ -0,0 +1,3 @@ +1、 正确填写WebDAV 服务器地址、WebDAV 账号、WebDAV 密码;(要获得这三项的信息,需要注册一个坚果云账号,如果直接在手机上注册,坚果云会让你下载app,过程比较麻烦,为了一步到位,最好是在电脑上打开这个注册链接:https://www.jianguoyun.com/d/signup;注册后,进入坚果云;点击右上角账户名处选择 “账户信息”,然后选择“安全选项”;在“安全选项” 中找到“第三方应用管理”,并选择“添加应用”,输入名称如“阅读”后,会生成密码,选择完成;其中https://dav.jianguoyun.com/dav/就是填入“WebDAV 服务器地址”的内容,“使用情况”后面的邮箱地址就是你的“WebDAV 账号”,点击显示密码后得到的密码就是你的“WebDAV 密码”。) + +2、 无需操作,APP默认每天自动云备份一次。 \ No newline at end of file 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 24976bb..ead050f 100644 --- a/app/src/main/java/xyz/fycz/myreader/application/MyApplication.java +++ b/app/src/main/java/xyz/fycz/myreader/application/MyApplication.java @@ -41,7 +41,6 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import xyz.fycz.myreader.R; -import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.common.URLCONST; import xyz.fycz.myreader.ui.dialog.APPDownloadTip; @@ -72,13 +71,9 @@ public class MyApplication extends Application { createNotificationChannel(); } mFixedThreadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());//初始化线程池 - BaseActivity.setCloseAntiHijacking(true); initNightTheme(); - } - - public void initNightTheme() { if (isNightFS()){ AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); @@ -247,49 +242,6 @@ public class MyApplication extends Application { /** * 检查更新 */ - /*public static void checkVersionByServer(final Activity activity, final boolean isManualCheck) { - MyApplication.getApplication().newThread(new Runnable() { - @Override - public void run() { - Document doc = null; - try { - doc = Jsoup.connect("https://novel.fycz.xyz/app/update.html").get(); - int newestVersion = 0; - String updateContent = ""; - String downloadLink = null; - boolean isForceUpdate = false; - StringBuilder s = new StringBuilder(); - assert doc != null; - Elements nodes = doc.getElementsByClass("secd-rank-list"); - newestVersion = Integer.valueOf(nodes.get(0).getElementsByTag("a").get(1).text()); - downloadLink = nodes.get(0).getElementsByTag("a").get(1).attr("href"); - updateContent = nodes.get(0).getElementsByTag("a").get(2).text(); - isForceUpdate = Boolean.parseBoolean(nodes.get(0).getElementsByTag("a").get(3).text()); - String[] updateContents = updateContent.split("/"); - for (String string : updateContents) { - s.append(string); - s.append("\n"); - } - int versionCode = getVersionCode(); - if (newestVersion > versionCode) { - MyApplication m = new MyApplication(); - Setting setting = SysManager.getSetting(); - if (isManualCheck || setting.getNewestVersionCode() < newestVersion || isForceUpdate) { - setting.setNewestVersionCode(newestVersion); - SysManager.saveSetting(setting); - int i = setting.getNewestVersionCode(); - m.updateApp(activity, downloadLink, newestVersion, s.toString(), isForceUpdate); - } - } else if (isManualCheck) { - TextHelper.showText("已经是最新版本!"); - } - } catch (IOException e) { - e.printStackTrace(); - TextHelper.showText("无网络连接!"); - } - } - }); - }*/ public static void checkVersionByServer(final AppCompatActivity activity, final boolean isManualCheck, final BookcaseFragment mBookcaseFragment) { MyApplication.getApplication().newThread(() -> { @@ -436,26 +388,5 @@ public class MyApplication extends Application { public static boolean isDestroy(Activity mActivity) { return mActivity == null || mActivity.isFinishing() || mActivity.isDestroyed(); } - - - /**************** - * - * 发起添加群流程。群号:风月读书交流群(1085028304) 的 key 为: 8PIOnHFuH6A38hgxvD_Rp2Bu-Ke1ToBn - * 调用 joinQQGroup(8PIOnHFuH6A38hgxvD_Rp2Bu-Ke1ToBn) 即可发起手Q客户端申请加群 风月读书交流群(1085028304) - * - * @param key 由官网生成的key - * @return 返回true表示呼起手Q成功,返回false表示呼起失败 - ******************/ - public static boolean joinQQGroup(Context context, String key) { - Intent intent = new Intent(); - intent.setData(Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26jump_from%3Dwebapi%26k%3D" + key)); - // 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - try { - context.startActivity(intent); - return true; - } catch (Exception e) { - // 未安装手Q或安装的版本不支持 - return false; - } - } + } 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 097a025..7e3bd53 100644 --- a/app/src/main/java/xyz/fycz/myreader/application/SysManager.java +++ b/app/src/main/java/xyz/fycz/myreader/application/SysManager.java @@ -5,10 +5,9 @@ import xyz.fycz.myreader.enums.BookcaseStyle; import xyz.fycz.myreader.enums.Font; import xyz.fycz.myreader.enums.Language; import xyz.fycz.myreader.enums.ReadStyle; +import xyz.fycz.myreader.model.storage.Backup; 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; @@ -79,13 +78,7 @@ public class SysManager { public static void resetSetting(){ Setting setting = getSetting(); - /*setting.setVolumeTurnPage(true); - setting.setMatchChapter(true); - setting.setRefreshWhenStart(true); - setting.setOpenBookStore(true); - setting.setResetScreen(3);*/ - ReadCrawlerUtil.resetReaderCrawlers(); + Backup.INSTANCE.backup(MyApplication.getmContext(), APPCONST.BACKUP_FILE_DIR,null, false); setting.setSettingVersion(APPCONST.SETTING_VERSION); - saveSetting(setting); } } diff --git a/app/src/main/java/xyz/fycz/myreader/base/BaseActivity.java b/app/src/main/java/xyz/fycz/myreader/base/BaseActivity.java index 4d04562..a2f26bd 100644 --- a/app/src/main/java/xyz/fycz/myreader/base/BaseActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/base/BaseActivity.java @@ -1,115 +1,192 @@ package xyz.fycz.myreader.base; -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build; +import android.annotation.SuppressLint; +import android.content.Intent; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.KeyEvent; -import android.view.Window; -import android.view.WindowManager; -import android.view.inputmethod.InputMethodManager; +import android.view.Menu; +import android.view.MenuItem; +import androidx.annotation.LayoutRes; +import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import butterknife.ButterKnife; +import butterknife.Unbinder; + +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; import xyz.fycz.myreader.ActivityManage; -import xyz.fycz.myreader.util.Anti_hijackingUtils; +import xyz.fycz.myreader.R; +import xyz.fycz.myreader.application.MyApplication; +import xyz.fycz.myreader.application.SysManager; +import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.util.StatusBarUtil; +import java.lang.reflect.Method; +import java.util.ArrayList; +/** + * @author fengyue + * @date 2020/8/12 20:02 + */ +public abstract class BaseActivity extends AppCompatActivity { + private static final int INVALID_VAL = -1; -public class BaseActivity extends AppCompatActivity { - - public static int width = 0; - public static int height = 0; - public static boolean home; - public static boolean back; - private boolean catchHomeKey = false; - private boolean disallowAntiHijacking;//暂停防界面劫持 + protected CompositeDisposable mDisposable; + //ButterKnife + private Toolbar mToolbar; - private static boolean closeAntiHijacking;//关闭防界面劫持 + private Unbinder unbinder; + private int curNightMode; + /****************************abstract area*************************************/ - private InputMethodManager mInputMethodManager; //输入管理器 - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + @LayoutRes + protected abstract int getContentId(); - //将每一个Activity都加入activity管理器 - ActivityManage.addActivity(this); - Log.d("ActivityName: ",getLocalClassName()); - DisplayMetrics dm = new DisplayMetrics(); - //获取屏幕宽高 - if(height == 0 || width == 0){ - getWindowManager().getDefaultDisplay().getMetrics(dm); - width = dm.widthPixels; - height = dm.heightPixels; + /************************init area************************************/ + protected void addDisposable(Disposable d){ + if (mDisposable == null){ + mDisposable = new CompositeDisposable(); } + mDisposable.add(d); + } - mInputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + /** + * 配置Toolbar + * @param toolbar + */ + protected void setUpToolbar(Toolbar toolbar){ } - public static void setCloseAntiHijacking(boolean closeAntiHijacking) { - BaseActivity.closeAntiHijacking = closeAntiHijacking; + protected void initData(Bundle savedInstanceState){ } + /** + * 初始化零件 + */ + protected void initWidget() { - @Override - protected void onDestroy() { - ActivityManage.removeActivity(this); - super.onDestroy(); } + /** + * 初始化点击事件 + */ + protected void initClick(){ + } + /** + * 逻辑使用区 + */ + protected void processLogic(){ + } + /** + * @return 是否夜间模式 + */ + protected boolean isNightTheme() { + return !SysManager.getSetting().isDayStyle(); + } + + /** + * 设置夜间模式 + * @param isNightMode + */ + protected void setNightTheme(boolean isNightMode) { + Setting setting = SysManager.getSetting(); + setting.setDayStyle(!isNightMode); + MyApplication.getApplication().initNightTheme(); + } + + + + /*************************lifecycle area*****************************************************/ @Override - protected void onPause() { - if (!disallowAntiHijacking && !closeAntiHijacking) { - Anti_hijackingUtils.getinstance().onPause(this);//防界面劫持提示任务 + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initTheme(); + ActivityManage.addActivity(this); + setContentView(getContentId()); + unbinder = ButterKnife.bind(this); + initData(savedInstanceState); + initToolbar(); + initWidget(); + initClick(); + processLogic(); + } + + private void initToolbar(){ + //更严谨是通过反射判断是否存在Toolbar + mToolbar = findViewById(R.id.toolbar); + if (mToolbar != null){ + supportActionBar(mToolbar); + setUpToolbar(mToolbar); } - super.onPause(); } @Override protected void onResume() { - if (!closeAntiHijacking) { - Anti_hijackingUtils.getinstance().onResume(this);//注销防界面劫持提示任务 - } - BaseActivity.home = false; - BaseActivity.back = false; - disallowAntiHijacking = false; super.onResume(); + if (isThemeChange()){ + recreate(); + } } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK){ - back = true;//以便于判断是否按返回键触发界面劫持提示 + protected void onDestroy() { + super.onDestroy(); + ActivityManage.removeActivity(this); + unbinder.unbind(); + if (mDisposable != null){ + mDisposable.dispose(); } - return super.onKeyDown(keyCode, event); + } + /** + * 初始化主题 + */ + public void initTheme() { + //if (isNightTheme()) { + //setTheme(R.style.AppNightTheme); + curNightMode = AppCompatDelegate.getDefaultNightMode(); + /*} else { + //curNightMode = false; + //setTheme(R.style.AppDayTheme); + }*/ } - - public void setDisallowAntiHijacking(boolean disallowAntiHijacking) { - this.disallowAntiHijacking = disallowAntiHijacking; + protected boolean isThemeChange(){ + return curNightMode != AppCompatDelegate.getDefaultNightMode(); } + /**************************used method area*******************************************/ + protected void startActivity(Class activity){ + Intent intent = new Intent(this, activity); + startActivity(intent); + } + protected ActionBar supportActionBar(Toolbar toolbar){ + setSupportActionBar(toolbar); + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null){ + actionBar.setDisplayHomeAsUpEnabled(true); + actionBar.setDisplayShowHomeEnabled(true); + } + mToolbar.setNavigationOnClickListener( + (v) -> finish() + ); + return actionBar; + } - /** - * 设置状态栏颜色 - * @param colorId - */ - public void setStatusBar(int colorId, boolean dark){ + protected void setStatusBarColor(int statusColor, boolean dark){ //沉浸式代码配置 //当FitsSystemWindows设置 true 时,会在屏幕最上方预留出状态栏高度的 padding StatusBarUtil.setRootViewFitsSystemWindows(this, true); //设置状态栏透明 StatusBarUtil.setTranslucentStatus(this); - if (colorId != 0) { - StatusBarUtil.setStatusBarColor(this, getResources().getColor(colorId)); - } + StatusBarUtil.setStatusBarColor(this, getResources().getColor(statusColor)); + //一般的手机的状态栏文字和图标都是白色的, 可如果你的应用也是纯白色的, 或导致状态栏文字看不清 //所以如果你是这种情况,请使用以下代码, 设置状态使用深色文字图标风格, 否则你可以选择性注释掉这个if内容 if (!dark) { @@ -119,11 +196,49 @@ public class BaseActivity extends AppCompatActivity { StatusBarUtil.setStatusBarColor(this, 0x55000000); } } - + } /** + * 设置MENU图标颜色 + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + for (int i = 0; i < menu.size(); i++) { + Drawable drawable = menu.getItem(i).getIcon(); + if (drawable != null) { + drawable.mutate(); + drawable.setColorFilter(getColor(R.color.textPrimary), PorterDuff.Mode.SRC_ATOP); + } + } + return super.onCreateOptionsMenu(menu); } - public InputMethodManager getmInputMethodManager() { - return mInputMethodManager; + @SuppressLint("PrivateApi") + @SuppressWarnings("unchecked") + @Override + public boolean onMenuOpened(int featureId, Menu menu) { + if (menu != null) { + //展开菜单显示图标 + if (menu.getClass().getSimpleName().equalsIgnoreCase("MenuBuilder")) { + try { + Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); + method.setAccessible(true); + method.invoke(menu, true); + method = menu.getClass().getDeclaredMethod("getNonActionItems"); + ArrayList menuItems = (ArrayList) method.invoke(menu); + if (!menuItems.isEmpty()) { + for (MenuItem menuItem : menuItems) { + Drawable drawable = menuItem.getIcon(); + if (drawable != null) { + drawable.mutate(); + drawable.setColorFilter(getResources().getColor(R.color.textPrimary), PorterDuff.Mode.SRC_ATOP); + } + } + } + } catch (Exception ignored) { + } + } + + } + return super.onMenuOpened(featureId, menu); } } diff --git a/app/src/main/java/xyz/fycz/myreader/base/BaseActivity2.java b/app/src/main/java/xyz/fycz/myreader/base/BaseActivity2.java deleted file mode 100644 index cdfe6b1..0000000 --- a/app/src/main/java/xyz/fycz/myreader/base/BaseActivity2.java +++ /dev/null @@ -1,244 +0,0 @@ -package xyz.fycz.myreader.base; - -import android.annotation.SuppressLint; -import android.content.Intent; -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; -import android.os.Bundle; - -import android.view.Menu; -import android.view.MenuItem; -import androidx.annotation.LayoutRes; -import androidx.annotation.Nullable; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.app.AppCompatDelegate; -import androidx.appcompat.widget.Toolbar; -import butterknife.ButterKnife; -import butterknife.Unbinder; - -import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.disposables.Disposable; -import xyz.fycz.myreader.ActivityManage; -import xyz.fycz.myreader.R; -import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.application.SysManager; -import xyz.fycz.myreader.entity.Setting; -import xyz.fycz.myreader.util.StatusBarUtil; - -import java.lang.reflect.Method; -import java.util.ArrayList; - -/** - * @author fengyue - * @date 2020/8/12 20:02 - */ -public abstract class BaseActivity2 extends AppCompatActivity { - private static final int INVALID_VAL = -1; - - protected CompositeDisposable mDisposable; - //ButterKnife - private Toolbar mToolbar; - - private Unbinder unbinder; - - private int curNightMode; - /****************************abstract area*************************************/ - - @LayoutRes - protected abstract int getContentId(); - - /************************init area************************************/ - protected void addDisposable(Disposable d){ - if (mDisposable == null){ - mDisposable = new CompositeDisposable(); - } - mDisposable.add(d); - } - - /** - * 配置Toolbar - * @param toolbar - */ - protected void setUpToolbar(Toolbar toolbar){ - } - - protected void initData(Bundle savedInstanceState){ - } - /** - * 初始化零件 - */ - protected void initWidget() { - - } - /** - * 初始化点击事件 - */ - protected void initClick(){ - } - /** - * 逻辑使用区 - */ - protected void processLogic(){ - } - /** - * @return 是否夜间模式 - */ - protected boolean isNightTheme() { - return !SysManager.getSetting().isDayStyle(); - } - - /** - * 设置夜间模式 - * @param isNightMode - */ - protected void setNightTheme(boolean isNightMode) { - Setting setting = SysManager.getSetting(); - setting.setDayStyle(!isNightMode); - MyApplication.getApplication().initNightTheme(); - } - - - - - /*************************lifecycle area*****************************************************/ - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - initTheme(); - ActivityManage.addActivity(this); - setContentView(getContentId()); - initData(savedInstanceState); - unbinder = ButterKnife.bind(this); - initToolbar(); - initWidget(); - initClick(); - processLogic(); - } - - private void initToolbar(){ - //更严谨是通过反射判断是否存在Toolbar - mToolbar = findViewById(R.id.toolbar); - if (mToolbar != null){ - supportActionBar(mToolbar); - setUpToolbar(mToolbar); - } - } - - @Override - protected void onResume() { - super.onResume(); - if (isThemeChange()){ - recreate(); - } - } - - @Override - protected void onDestroy() { - super.onDestroy(); - ActivityManage.removeActivity(this); - unbinder.unbind(); - if (mDisposable != null){ - mDisposable.dispose(); - } - } - /** - * 初始化主题 - */ - public void initTheme() { - //if (isNightTheme()) { - //setTheme(R.style.AppNightTheme); - curNightMode = AppCompatDelegate.getDefaultNightMode(); - /*} else { - //curNightMode = false; - //setTheme(R.style.AppDayTheme); - }*/ - } - - protected boolean isThemeChange(){ - return curNightMode != AppCompatDelegate.getDefaultNightMode(); - } - /**************************used method area*******************************************/ - - protected void startActivity(Class activity){ - Intent intent = new Intent(this, activity); - startActivity(intent); - } - - protected ActionBar supportActionBar(Toolbar toolbar){ - setSupportActionBar(toolbar); - ActionBar actionBar = getSupportActionBar(); - if (actionBar != null){ - actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.setDisplayShowHomeEnabled(true); - } - mToolbar.setNavigationOnClickListener( - (v) -> finish() - ); - return actionBar; - } - - protected void setStatusBarColor(int statusColor, boolean dark){ - //沉浸式代码配置 - //当FitsSystemWindows设置 true 时,会在屏幕最上方预留出状态栏高度的 padding - StatusBarUtil.setRootViewFitsSystemWindows(this, true); - //设置状态栏透明 - StatusBarUtil.setTranslucentStatus(this); - StatusBarUtil.setStatusBarColor(this, getResources().getColor(statusColor)); - - //一般的手机的状态栏文字和图标都是白色的, 可如果你的应用也是纯白色的, 或导致状态栏文字看不清 - //所以如果你是这种情况,请使用以下代码, 设置状态使用深色文字图标风格, 否则你可以选择性注释掉这个if内容 - if (!dark) { - if (!StatusBarUtil.setStatusBarDarkTheme(this, true)) { - //如果不支持设置深色风格 为了兼容总不能让状态栏白白的看不清, 于是设置一个状态栏颜色为半透明, - //这样半透明+白=灰, 状态栏的文字能看得清 - StatusBarUtil.setStatusBarColor(this, 0x55000000); - } - } - } /** - * 设置MENU图标颜色 - */ - @Override - public boolean onCreateOptionsMenu(Menu menu) { - for (int i = 0; i < menu.size(); i++) { - Drawable drawable = menu.getItem(i).getIcon(); - if (drawable != null) { - drawable.mutate(); - drawable.setColorFilter(getColor(R.color.textPrimary), PorterDuff.Mode.SRC_ATOP); - } - } - return super.onCreateOptionsMenu(menu); - } - - @SuppressLint("PrivateApi") - @SuppressWarnings("unchecked") - @Override - public boolean onMenuOpened(int featureId, Menu menu) { - if (menu != null) { - //展开菜单显示图标 - if (menu.getClass().getSimpleName().equalsIgnoreCase("MenuBuilder")) { - try { - Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); - method.setAccessible(true); - method.invoke(menu, true); - method = menu.getClass().getDeclaredMethod("getNonActionItems"); - ArrayList menuItems = (ArrayList) method.invoke(menu); - if (!menuItems.isEmpty()) { - for (MenuItem menuItem : menuItems) { - Drawable drawable = menuItem.getIcon(); - if (drawable != null) { - drawable.mutate(); - drawable.setColorFilter(getResources().getColor(R.color.textPrimary), PorterDuff.Mode.SRC_ATOP); - } - } - } - } catch (Exception ignored) { - } - } - - } - return super.onMenuOpened(featureId, menu); - } - -} diff --git a/app/src/main/java/xyz/fycz/myreader/base/BaseTabActivity.java b/app/src/main/java/xyz/fycz/myreader/base/BaseTabActivity.java index 2d65410..585a8a1 100644 --- a/app/src/main/java/xyz/fycz/myreader/base/BaseTabActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/base/BaseTabActivity.java @@ -16,7 +16,7 @@ import java.util.List; * @date 2020/8/12 20:02 */ -public abstract class BaseTabActivity extends BaseActivity2 { +public abstract class BaseTabActivity extends BaseActivity { /**************View***************/ @BindView(R.id.tab_tl_indicator) protected TabLayout mTlIndicator; 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 e0843dd..e864af9 100644 --- a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java +++ b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java @@ -13,7 +13,7 @@ public class APPCONST { public static String publicKey = "";//服务端公钥 public static String privateKey;//app私钥 public final static String s = "11940364935628058505"; - public static final String KEY = ""; + public static final String KEY = "readerByFengyue"; public static final String ALARM_SCHEDULE_MSG = "alarm_schedule_msg"; @@ -79,7 +79,7 @@ public class APPCONST { public static final int PERMISSIONS_REQUEST_STORAGE = 10001; //设置版本号 - public static final int SETTING_VERSION = 5; + public static final int SETTING_VERSION = 6; public static final String FORMAT_FILE_DATE = "yyyy-MM-dd"; diff --git a/app/src/main/java/xyz/fycz/myreader/model/backup/BackupAndRestore.java b/app/src/main/java/xyz/fycz/myreader/model/backup/BackupAndRestore.java deleted file mode 100644 index 4e4ecb9..0000000 --- a/app/src/main/java/xyz/fycz/myreader/model/backup/BackupAndRestore.java +++ /dev/null @@ -1,129 +0,0 @@ -package xyz.fycz.myreader.model.backup; - -import xyz.fycz.myreader.application.SysManager; -import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.entity.Setting; -import xyz.fycz.myreader.greendao.entity.Book; -import xyz.fycz.myreader.greendao.service.BookService; -import xyz.fycz.myreader.util.IOUtils; -import xyz.fycz.myreader.util.utils.FileUtils; -import java.io.*; -import java.util.ArrayList; -import java.util.List; - -/** - * @author fengyue - * @date 2020/4/25 9:07 - */ - -public class BackupAndRestore { - - BookService mBookService = BookService.getInstance(); - - /** - * 备份书架 - * @return 是否备份成功 - */ - public boolean backup(String backupName){ - List books = mBookService.getAllBooks(); - StringBuilder s = new StringBuilder(); - for (Book book : books) { - s.append(book); - s.append(",\n"); - } - s.deleteCharAt(s.lastIndexOf(",")); - File booksFile = FileUtils.getFile(APPCONST.FILE_DIR + backupName + "/books" + FileUtils.SUFFIX_FY); - File settingFile = FileUtils.getFile(APPCONST.FILE_DIR + backupName + "/setting" + FileUtils.SUFFIX_FY); - BufferedWriter bw = null; - ObjectOutputStream oos = null; - try { - bw = new BufferedWriter(new FileWriter(booksFile)); - bw.write(s.toString()); - bw.flush(); - oos = new ObjectOutputStream(new FileOutputStream(settingFile)); - oos.writeObject(SysManager.getSetting()); - oos.flush(); - return true; - } catch (IOException e) { - e.printStackTrace(); - return false; - } finally { - IOUtils.close(bw, oos); - } - } - - /** - * 恢复书架 - * @return 是否恢复成功 - */ - public boolean restore(String backupName) { - File booksFile = FileUtils.getFile(APPCONST.FILE_DIR + backupName + "/books" + FileUtils.SUFFIX_FY); - File settingFile = FileUtils.getFile(APPCONST.FILE_DIR + backupName + "/setting" + FileUtils.SUFFIX_FY); - if (!booksFile.exists() || !settingFile.exists()){ - return false; - } - BufferedReader br = null; - ObjectInputStream ois = null; - try { - br = new BufferedReader(new FileReader(booksFile)); - String tem = ""; - StringBuilder s = new StringBuilder(); - while ((tem = br.readLine()) != null){ - s.append(tem).append("\n"); - } - String[] sBooks = s.toString().split("\\},"); - List books = new ArrayList<>(); - for (String sBook : sBooks){ - sBook.replace("{", ""); - sBook.replace("}", ""); - String[] sBookFields = sBook.split(",\n"); - for (int i = 0; i < sBookFields.length; i++) { - sBookFields[i] = sBookFields[i].substring(sBookFields[i].indexOf("'") + 1, sBookFields[i].lastIndexOf("'")); - } - String source = "null"; - boolean isCloseUpdate = false; - boolean isDownloadAll = true; - String group = "allBook"; - String infoUrl = ""; - if(!sBookFields[2].contains("novel.fycz.xyz")){ - source = sBookFields[17]; - } - if ("本地书籍".equals(sBookFields[4])){ - sBookFields[15] = "0"; - } - if (sBookFields.length >= 19){ - isCloseUpdate = Boolean.parseBoolean(sBookFields[18]); - } - if (sBookFields.length >= 20){ - isDownloadAll = Boolean.parseBoolean(sBookFields[19]); - } - if (sBookFields.length >= 21){ - group = sBookFields[20]; - } - 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]) - , source, isCloseUpdate, isDownloadAll, group, 0); - books.add(book); - } - mBookService.deleteAllBooks(); - mBookService.addBooks(books); - ois = new ObjectInputStream(new FileInputStream(settingFile)); - Object obj = ois.readObject(); - if (obj instanceof Setting){ - Setting setting = (Setting) obj; - SysManager.saveSetting(setting); - } - return true; - } catch (IOException | ClassNotFoundException e) { - e.printStackTrace(); - return false; - } finally { - IOUtils.close(br, ois); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/xyz/fycz/myreader/model/backup/UserService.java b/app/src/main/java/xyz/fycz/myreader/model/backup/UserService.java deleted file mode 100644 index be9c073..0000000 --- a/app/src/main/java/xyz/fycz/myreader/model/backup/UserService.java +++ /dev/null @@ -1,333 +0,0 @@ -package xyz.fycz.myreader.model.backup; - -import io.reactivex.annotations.NonNull; -import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.model.storage.Backup; -import xyz.fycz.myreader.model.storage.Restore; -import xyz.fycz.myreader.webapi.callback.ResultCallback; -import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.common.URLCONST; -import xyz.fycz.myreader.util.*; -import xyz.fycz.myreader.util.utils.FileUtils; - -import java.io.*; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; - -/** - * @author fengyue - * @date 2020/4/26 11:03 - */ -public class UserService { - /** - * 登录 - * @param userLoginInfo 用户名输入的用户名和密码等登录信息 - * @return 是否成功登录 - */ - public static void login(final Map userLoginInfo, final ResultCallback resultCallback) { - MyApplication.getApplication().newThread(() -> { - HttpURLConnection conn = null; - try { - URL url = new URL(URLCONST.APP_WEB_URL + "login"); - conn = (HttpURLConnection) url.openConnection(); - conn.setRequestMethod("POST"); - conn.setConnectTimeout(60 * 1000); - conn.setReadTimeout(60 * 1000); - conn.setDoInput(true); - conn.setDoOutput(true); - String params = "username=" + userLoginInfo.get("loginName") + - "&password=" + userLoginInfo.get("loginPwd") + makeSignalParam(); - // 获取URLConnection对象对应的输出流 - PrintWriter out = new PrintWriter(conn.getOutputStream()); - // 发送请求参数 - out.print(params); - // flush输出流的缓冲 - out.flush(); - InputStream in = conn.getInputStream(); - BufferedReader bw = new BufferedReader(new InputStreamReader(in, "utf-8")); - StringBuilder sb = new StringBuilder(); - String line = bw.readLine(); - while (line != null) { - sb.append(line); - line = bw.readLine(); - } - resultCallback.onFinish(sb.toString(), 1); - } catch (IOException e) { - e.printStackTrace(); - resultCallback.onError(e); - }finally { - if (conn != null) { - conn.disconnect(); - } - } - }); - } - - public static void register(final Map userRegisterInfo, final ResultCallback resultCallback) { - MyApplication.getApplication().newThread(() -> { - HttpURLConnection conn = null; - try { - URL url = new URL(URLCONST.APP_WEB_URL + "reg"); - conn = (HttpURLConnection) url.openConnection(); - conn.setRequestMethod("POST"); - conn.setDoInput(true); - conn.setDoOutput(true); - String params = "username=" + userRegisterInfo.get("username") + "&password=" + - CyptoUtils.encode(APPCONST.KEY, userRegisterInfo.get("password")) + "&key=" + - CyptoUtils.encode(APPCONST.KEY, APPCONST.publicKey) + makeSignalParam(); - // 获取URLConnection对象对应的输出流 - PrintWriter out = new PrintWriter(conn.getOutputStream()); - // 发送请求参数 - out.print(params); - // flush输出流的缓冲 - out.flush(); - BufferedReader bw = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); - StringBuilder sb = new StringBuilder(); - String line = bw.readLine(); - while (line != null) { - sb.append(line); - line = bw.readLine(); - } - resultCallback.onFinish(sb.toString(), 1); - } catch (IOException e) { - e.printStackTrace(); - resultCallback.onError(e); - } finally { - if (conn != null) { - conn.disconnect(); - } - } - - }); - } - - /** - * 写配置 - * @param userLoginInfo - * @return - */ - public static boolean writeConfig(Map userLoginInfo){ - FileOutputStream fos = null; - try { - fos = MyApplication.getApplication().openFileOutput("userConfig.fy", MyApplication.getApplication().MODE_PRIVATE); - String userInfo = "username='" + userLoginInfo.get("loginName") + "',\npassword='" + userLoginInfo.get("loginPwd") + "'"; - byte[] bs = userInfo.getBytes(); - fos.write(bs); - //写完后一定要刷新 - fos.flush(); - return true; - } catch (IOException e) { - e.printStackTrace(); - return false; - } finally { - IOUtils.close(fos); - } - } - - /** - * 读配置 - * @return - */ - public static Map readConfig(){ - File file = MyApplication.getApplication().getFileStreamPath("userConfig.fy"); - if (!file.exists()){ - return null; - } - BufferedReader br = null; - try { - br = new BufferedReader(new FileReader(file)); - String tem; - StringBuilder config = new StringBuilder(); - while ((tem = br.readLine()) != null){ - config.append(tem); - } - String[] user = config.toString().split(","); - String userName = user[0].substring(user[0].indexOf("'") + 1, user[0].lastIndexOf("'")); - String password = user[1].substring(user[1].indexOf("'") + 1, user[1].lastIndexOf("'")); - Map userInfo = new HashMap<>(); - userInfo.put("userName", userName); - userInfo.put("password", password); - return userInfo; - } catch (IOException e) { - e.printStackTrace(); - }finally { - IOUtils.close(br); - } - return null; - } - - public static void writeUsername(String username){ - File file = FileUtils.getFile(APPCONST.QQ_DATA_DIR + "user"); - BufferedWriter bw = null; - try { - bw = new BufferedWriter(new FileWriter(file)); - bw.write(username); - bw.flush(); - } catch (IOException e) { - e.printStackTrace(); - }finally { - IOUtils.close(bw); - } - } - - public static String readUsername(){ - File file = new File(APPCONST.QQ_DATA_DIR + "user"); - if (!file.exists()){ - return ""; - } - BufferedReader br = null; - try { - br = new BufferedReader(new FileReader(file)); - return br.readLine(); - } catch (IOException e) { - e.printStackTrace(); - return ""; - } finally { - IOUtils.close(br); - } - } - - /** - * 网络备份 - * @return - */ - public static void webBackup(ResultCallback rc){ - Map userInfo = readConfig(); - if (userInfo == null){ - rc.onFinish(false, 0); - } - Backup.INSTANCE.backup(MyApplication.getmContext(), APPCONST.FILE_DIR + "webBackup/", new Backup.CallBack() { - @Override - public void backupSuccess() { - MyApplication.getApplication().newThread(() ->{ - File inputFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup"); - if (!inputFile.exists()) { - rc.onFinish(false, 0); - } - File zipFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup.zip"); - FileInputStream fis = null; - HttpURLConnection conn = null; - try { - //压缩文件 - ZipUtils.zipFile(inputFile, zipFile); - fis = new FileInputStream(zipFile); - URL url = new URL(URLCONST.APP_WEB_URL + "bak?username=" + userInfo.get("userName") + - makeSignalParam()); - conn = (HttpURLConnection) url.openConnection(); - conn.setRequestMethod("POST"); - conn.setRequestProperty("Content-type", "multipart/form-data"); - conn.setDoInput(true); - conn.setDoOutput(true); - OutputStream out = conn.getOutputStream(); - byte[] bytes = new byte[1024]; - int len = -1; - while ((len = fis.read(bytes)) != -1){ - out.write(bytes, 0, len); - } - out.flush(); - zipFile.delete(); - BufferedReader bw = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); - StringBuilder sb = new StringBuilder(); - String line = bw.readLine(); - while (line != null) { - sb.append(line); - line = bw.readLine(); - } - String[] info = sb.toString().split(":"); - int code = Integer.parseInt(info[0].trim()); - rc.onFinish(code == 104, 0); - } catch (Exception e) { - e.printStackTrace(); - rc.onError(e); - } finally { - IOUtils.close(fis); - if (conn != null) { - conn.disconnect(); - } - } - }); - } - - @Override - public void backupError(@NonNull String msg) { - ToastUtils.showError(msg); - rc.onFinish(false, 0); - } - }, false); - - } - - /** - * 网络恢复 - * @return - */ - public static void webRestore(ResultCallback rc){ - Map userInfo = readConfig(); - if (userInfo == null){ - rc.onFinish(false, 0); - } - FileOutputStream fos = null; - File zipFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup.zip"); - HttpURLConnection conn = null; - try { - URL url = new URL(URLCONST.APP_WEB_URL + "ret?username=" + userInfo.get("userName") + - makeSignalParam()); - conn = (HttpURLConnection) url.openConnection(); - conn.setRequestMethod("POST"); - conn.setDoInput(true); - InputStream is = conn.getInputStream(); - fos = new FileOutputStream(zipFile); - //一边读,一边写 - byte[] bytes = new byte[512]; - int readCount = 0; - while ((readCount = is.read(bytes)) != -1) { - fos.write(bytes,0, readCount); - } - //刷新,输出流一定要刷新 - fos.flush(); - if (zipFile.length() == 0){ - zipFile.delete(); - rc.onFinish(false, 0); - } - ZipUtils.unzipFile(zipFile.getAbsolutePath(), APPCONST.FILE_DIR); - Restore.INSTANCE.restore(APPCONST.FILE_DIR + "webBackup/", new Restore.CallBack() { - @Override - public void restoreSuccess() { - zipFile.delete(); - rc.onFinish(true, 0); - } - - @Override - public void restoreError(@NonNull String msg) { - ToastUtils.showError(msg); - rc.onFinish(false, 0); - } - }); - } catch (Exception e) { - e.printStackTrace(); - rc.onError(e); - }finally { - IOUtils.close(fos); - if (conn != null) { - conn.disconnect(); - } - } - } - - - private static String makeSignalParam(){ - return "&signal=" + AppInfoUtils.getSingInfo(MyApplication.getmContext(), - MyApplication.getApplication().getPackageName(), AppInfoUtils.SHA1); - } - - /** - * 判断是否登录 - * @return - */ - public static boolean isLogin(){ - File file = MyApplication.getApplication().getFileStreamPath("userConfig.fy"); - return file.exists(); - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/model/storage/WebDavHelp.kt b/app/src/main/java/xyz/fycz/myreader/model/storage/WebDavHelp.kt index ba2e8d0..f8ac305 100644 --- a/app/src/main/java/xyz/fycz/myreader/model/storage/WebDavHelp.kt +++ b/app/src/main/java/xyz/fycz/myreader/model/storage/WebDavHelp.kt @@ -53,8 +53,9 @@ object WebDavHelp { if (initWebDav()) { var files = WebDav(url + "FYReader/").listFiles() files = files.reversed() - for (index: Int in 0 until min(10, files.size)) { - files[index].displayName?.let { + //for (index: Int in 0 until min(10, files.size)) { + for (element in files) { + element.displayName?.let { names.add(it) } } 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 b1fdec1..f1551c1 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 @@ -11,7 +11,7 @@ import androidx.cardview.widget.CardView; import butterknife.BindView; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; -import xyz.fycz.myreader.base.BaseActivity2; +import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.common.URLCONST; import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.util.ShareUtils; @@ -22,7 +22,7 @@ import xyz.fycz.myreader.util.ToastUtils; * @author fengyue * @date 2020/9/18 22:21 */ -public class AboutActivity extends BaseActivity2 { +public class AboutActivity extends BaseActivity { @BindView(R.id.tv_version_name) TextView tvVersionName; @BindView(R.id.vm_author) @@ -33,8 +33,6 @@ public class AboutActivity extends BaseActivity2 { CardView vmUpdate; @BindView(R.id.vw_update_log) CardView vmUpdateLog; - @BindView(R.id.vw_qq) - CardView vmQQ; @BindView(R.id.vw_git) CardView vmGit; @BindView(R.id.vw_disclaimer) @@ -75,16 +73,6 @@ public class AboutActivity extends BaseActivity2 { SharedPreUtils.getInstance().getString(getString(R.string.downloadLink, URLCONST.LAN_ZOUS_URL)))); vmUpdate.setOnClickListener(v -> MyApplication.checkVersionByServer(this, true, null)); vmUpdateLog.setOnClickListener(v -> DialogCreator.createAssetTipDialog(this, "更新日志", "updatelog.fy")); - vmQQ.setOnClickListener(v -> { - if (!MyApplication.joinQQGroup(this,"8PIOnHFuH6A38hgxvD_Rp2Bu-Ke1ToBn")){ - //数据 - ClipData mClipData = ClipData.newPlainText("Label", "1085028304"); - //把数据设置到剪切板上 - assert mClipboardManager != null; - mClipboardManager.setPrimaryClip(mClipData); - ToastUtils.showError("未安装手Q或安装的版本不支持!\n已复制QQ群号,您可自行前往QQ添加!"); - } - }); vmGit.setOnClickListener(v -> openIntent(Intent.ACTION_VIEW, getString(R.string.this_github_url))); vmDisclaimer.setOnClickListener(v -> DialogCreator.createAssetTipDialog(this, "免责声明", "disclaimer.fy")); 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 326baa1..a51b963 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 @@ -18,12 +18,11 @@ import butterknife.BindView; 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.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.base.BaseActivity; import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.ui.dialog.SourceExchangeDialog; @@ -50,7 +49,7 @@ import java.util.ArrayList; * @author fengyue * @date 2020/8/17 11:39 */ -public class BookDetailedActivity extends BaseActivity2 { +public class BookDetailedActivity extends BaseActivity { @BindView(R.id.book_detail_iv_cover) CoverImageView mIvCover; /* @BindView(R.id.book_detail_iv_blur_cover) @@ -337,7 +336,7 @@ public class BookDetailedActivity extends BaseActivity2 { private RequestBuilder defaultCover() { return Glide.with(this) - .load(R.mipmap.no_image) + .load(R.mipmap.default_cover) .apply(RequestOptions.bitmapTransform(new BlurTransformation(this, 25))); } 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 4ebbc5e..98adbf8 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 @@ -16,7 +16,7 @@ import butterknife.BindView; 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.base.BaseActivity; import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.ui.dialog.DialogCreator; @@ -43,7 +43,7 @@ import java.util.List; * @author fengyue * @date 2020/9/13 21:11 */ -public class BookstoreActivity extends BaseActivity2 { +public class BookstoreActivity extends BaseActivity { @BindView(R.id.refresh_layout) RefreshLayout mRlRefresh; @BindView(R.id.rv_type_list) diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/CatalogActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/CatalogActivity.java index 06c6efb..ebe0428 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/CatalogActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/CatalogActivity.java @@ -10,7 +10,7 @@ import androidx.viewpager.widget.ViewPager; import butterknife.BindView; import com.google.android.material.tabs.TabLayout; import xyz.fycz.myreader.R; -import xyz.fycz.myreader.base.BaseActivity2; +import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.ui.adapter.TabFragmentPageAdapter; @@ -20,7 +20,7 @@ import xyz.fycz.myreader.ui.fragment.CatalogFragment; /** * 书籍目录activity */ -public class CatalogActivity extends BaseActivity2 { +public class CatalogActivity extends BaseActivity { @BindView(R.id.catalog_tab) diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/FontsActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/FontsActivity.java index 91c6353..d866887 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/FontsActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/FontsActivity.java @@ -8,14 +8,12 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; -import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; -import android.widget.TextView; import androidx.appcompat.widget.Toolbar; import butterknife.BindView; import xyz.fycz.myreader.R; -import xyz.fycz.myreader.base.BaseActivity2; +import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.enums.Font; import xyz.fycz.myreader.ui.adapter.FontsAdapter; @@ -35,7 +33,7 @@ import static xyz.fycz.myreader.util.UriFileUtil.getPath; * @author fengyue * @date 2020/9/19 12:04 */ -public class FontsActivity extends BaseActivity2 { +public class FontsActivity extends BaseActivity { @BindView(R.id.lv_fonts) ListView lvFonts; @BindView(R.id.pb_loading) 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 deleted file mode 100644 index a01af55..0000000 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/LoginActivity.java +++ /dev/null @@ -1,231 +0,0 @@ -package xyz.fycz.myreader.ui.activity; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Intent; -import android.graphics.Bitmap; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.MotionEvent; -import android.view.View; -import android.view.inputmethod.InputMethodManager; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; -import androidx.appcompat.widget.Toolbar; -import butterknife.BindView; -import com.google.android.material.textfield.TextInputLayout; -import xyz.fycz.myreader.R; -import xyz.fycz.myreader.model.backup.UserService; -import xyz.fycz.myreader.base.BaseActivity2; -import xyz.fycz.myreader.webapi.callback.ResultCallback; -import xyz.fycz.myreader.common.APPCONST; -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; -import xyz.fycz.myreader.util.utils.NetworkUtils; -import xyz.fycz.myreader.util.utils.StringUtils; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author fengyue - * @date 2020/9/18 22:27 - */ -public class LoginActivity extends BaseActivity2 implements TextWatcher { - @BindView(R.id.et_user) - TextInputLayout user; - @BindView(R.id.et_password) - TextInputLayout password; - @BindView(R.id.bt_login) - Button loginBtn; - @BindView(R.id.tv_register) - TextView tvRegister; - @BindView(R.id.et_captcha) - TextInputLayout etCaptcha; - @BindView(R.id.iv_captcha) - ImageView ivCaptcha; - - private String code; - - @SuppressLint("HandlerLeak") - private Handler mHandler = new Handler() { - @SuppressLint("HandlerLeak") - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case 1: - loginBtn.setEnabled(true); - break; - case 2: - createCaptcha(); - break; - } - } - }; - - @Override - protected int getContentId() { - return R.layout.activity_login; - } - - @Override - protected void setUpToolbar(Toolbar toolbar) { - super.setUpToolbar(toolbar); - setStatusBarColor(R.color.colorPrimary, true); - getSupportActionBar().setTitle("登录"); - } - - @Override - protected void initData(Bundle savedInstanceState) { - super.initData(savedInstanceState); - } - - @Override - protected void initWidget() { - super.initWidget(); - mHandler.sendMessage(mHandler.obtainMessage(2)); - String username = UserService.readUsername(); - user.getEditText().setText(username); - user.getEditText().requestFocus(username.length()); - //监听内容改变 -> 控制按钮的点击状态 - user.getEditText().addTextChangedListener(this); - password.getEditText().addTextChangedListener(this); - etCaptcha.getEditText().addTextChangedListener(this); - } - - @Override - protected void initClick() { - super.initClick(); - ivCaptcha.setOnClickListener(v -> mHandler.sendMessage(mHandler.obtainMessage(2))); - - loginBtn.setOnClickListener(v -> { - mHandler.sendMessage(mHandler.obtainMessage(2)); - if (!code.toLowerCase().equals(etCaptcha.getEditText().getText().toString().toLowerCase())){ - DialogCreator.createTipDialog(this, "验证码错误!"); - return; - } - if (!NetworkUtils.isNetWorkAvailable()) { - ToastUtils.showError("无网络连接!"); - return; - } - ProgressDialog dialog = DialogCreator.createProgressDialog(this, null, "正在登陆..."); - loginBtn.setEnabled(false); - final String loginName = user.getEditText().getText().toString().trim(); - String loginPwd = password.getEditText().getText().toString(); - final Map userLoginInfo = new HashMap<>(); - userLoginInfo.put("loginName", loginName); - userLoginInfo.put("loginPwd", CyptoUtils.encode(APPCONST.KEY, loginPwd)); - //验证用户名和密码 - UserService.login(userLoginInfo, new ResultCallback() { - @Override - public void onFinish(Object o, int code) { - String result = (String) o; - String[] info = result.split(":"); - int resultCode = Integer.parseInt(info[0].trim()); - String resultName = info[1].trim(); - //最后输出结果 - if (resultCode == 102) { - UserService.writeConfig(userLoginInfo); - UserService.writeUsername(loginName); - Intent intent = new Intent(); - intent.putExtra("isLogin", true); - setResult(Activity.RESULT_OK, intent); - finish(); - ToastUtils.showSuccess(resultName); - } else { - mHandler.sendMessage(mHandler.obtainMessage(1)); - dialog.dismiss(); - ToastUtils.showWarring(resultName); - } - - } - - @Override - public void onError(Exception e) { - ToastUtils.showError("登录失败\n" + e.getLocalizedMessage()); - mHandler.sendMessage(mHandler.obtainMessage(1)); - dialog.dismiss(); - } - }); - - }); - - tvRegister.setOnClickListener(v -> { - Intent intent = new Intent(LoginActivity.this, RegisterActivity.class); - startActivity(intent); - }); - } - - public void createCaptcha() { - code = CodeUtil.getInstance().createCode(); - Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code); - ivCaptcha.setImageBitmap(codeBitmap); - } - - - /** - * 当有控件获得焦点focus 自动弹出键盘 - * 1. 点击软键盘的enter键 自动收回键盘 - * 2. 代码控制 InputMethodManager - * requestFocus - * showSoftInput:显示键盘 必须先让这个view成为焦点requestFocus - * - * hideSoftInputFromWindow 隐藏键盘 - */ - @Override - public boolean onTouchEvent(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_DOWN){ - //隐藏键盘 - //1.获取系统输入的管理器 - InputMethodManager inputManager = - (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); - - //2.隐藏键盘 - inputManager.hideSoftInputFromWindow(user.getWindowToken(),0); - - //3.取消焦点 - View focusView = getCurrentFocus(); - if (focusView != null) { - focusView.clearFocus(); //取消焦点 - } - - //getCurrentFocus().clearFocus(); - - //focusView.requestFocus();//请求焦点 - } - return true; - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable s) { - //禁止输入中文 - StringUtils.isNotChinese(s); - //判断两个输入框是否有内容 - if (user.getEditText().getText().toString().length() > 0 && - password.getEditText().getText().toString().length() > 0 && - etCaptcha.getEditText().getText().toString().length() > 0){ - //按钮可以点击 - loginBtn.setEnabled(true); - }else{ - //按钮不能点击 - loginBtn.setEnabled(false); - } - } -} 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 436afb7..d07ae88 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 @@ -21,7 +21,7 @@ import com.google.android.material.bottomnavigation.BottomNavigationView; 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.base.BaseActivity; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.ui.fragment.BookcaseFragment; @@ -40,7 +40,7 @@ import static androidx.fragment.app.FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CU * @author fengyue * @date 2020/9/13 13:03 */ -public class MainActivity extends BaseActivity2 { +public class MainActivity extends BaseActivity { @BindView(R.id.bottom_navigation_view) BottomNavigationView bottomNavigation; @BindView(R.id.view_pager_main) 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 319e56b..860520e 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,8 +3,6 @@ package xyz.fycz.myreader.ui.activity; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; -import android.text.InputType; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.*; @@ -13,19 +11,11 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.SwitchCompat; import androidx.appcompat.widget.Toolbar; import butterknife.BindView; -import com.google.android.material.textfield.TextInputLayout; -import io.reactivex.Single; -import io.reactivex.SingleOnSubscribe; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.schedulers.Schedulers; 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.base.observer.MySingleObserver; +import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.model.storage.BackupRestoreUi; -import xyz.fycz.myreader.model.storage.WebDavHelp; import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.ui.dialog.MultiChoiceDialog; import xyz.fycz.myreader.ui.dialog.MyAlertDialog; @@ -33,7 +23,6 @@ import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.service.BookService; -import xyz.fycz.myreader.util.StringHelper; import xyz.fycz.myreader.util.utils.FileUtils; import xyz.fycz.myreader.util.SharedPreUtils; import xyz.fycz.myreader.util.ToastUtils; @@ -51,7 +40,7 @@ import static xyz.fycz.myreader.common.APPCONST.BOOK_CACHE_PATH; * 阅读界面的更多设置 */ -public class MoreSettingActivity extends BaseActivity2 { +public class MoreSettingActivity extends BaseActivity { @BindView(R.id.more_setting_ll_webdav) LinearLayout mLlWebdav; @BindView(R.id.more_setting_rl_volume) 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 efb5cbb..28d7c98 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 @@ -1,121 +1,535 @@ package xyz.fycz.myreader.ui.activity; - -import android.content.DialogInterface; -import android.content.Intent; +import android.annotation.SuppressLint; +import android.app.Dialog; +import android.app.Notification; +import android.content.*; +import android.graphics.BitmapFactory; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; import android.os.Bundle; -import android.view.KeyEvent; -import android.view.Window; -import android.view.WindowManager; +import android.os.Handler; +import android.os.Message; +import android.view.*; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.LinearLayout; import android.widget.ProgressBar; +import android.widget.SeekBar; import android.widget.TextView; - import androidx.appcompat.app.AppCompatActivity; - +import androidx.appcompat.widget.Toolbar; +import androidx.core.content.ContextCompat; import butterknife.BindView; -import butterknife.ButterKnife; +import butterknife.OnClick; +import com.google.android.material.appbar.AppBarLayout; +import com.gyf.immersionbar.ImmersionBar; import com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBar; import xyz.fycz.myreader.ActivityManage; import xyz.fycz.myreader.R; +import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.common.APPCONST; +import xyz.fycz.myreader.entity.Setting; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.enums.Font; +import xyz.fycz.myreader.enums.ReadStyle; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.BookMark; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.greendao.service.BookMarkService; +import xyz.fycz.myreader.greendao.service.BookService; +import xyz.fycz.myreader.greendao.service.ChapterService; import xyz.fycz.myreader.model.storage.Backup; +import xyz.fycz.myreader.ui.dialog.CopyContentDialog; import xyz.fycz.myreader.ui.dialog.DialogCreator; -import xyz.fycz.myreader.ui.presenter.ReadPresenter; +import xyz.fycz.myreader.ui.dialog.MyAlertDialog; +import xyz.fycz.myreader.ui.dialog.SourceExchangeDialog; +import xyz.fycz.myreader.util.*; +import xyz.fycz.myreader.util.notification.NotificationClickReceiver; +import xyz.fycz.myreader.util.notification.NotificationUtil; +import xyz.fycz.myreader.util.utils.ColorUtil; +import xyz.fycz.myreader.util.utils.NetworkUtils; +import xyz.fycz.myreader.util.utils.SystemBarUtils; +import xyz.fycz.myreader.webapi.CommonApi; +import xyz.fycz.myreader.webapi.callback.ResultCallback; +import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; +import xyz.fycz.myreader.widget.page.LocalPageLoader; +import xyz.fycz.myreader.widget.page.PageLoader; +import xyz.fycz.myreader.widget.page.PageMode; import xyz.fycz.myreader.widget.page.PageView; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import static android.view.View.GONE; +import static android.view.View.VISIBLE; +import static xyz.fycz.myreader.util.UriFileUtil.getPath; + +/** + * @author fengyue + * @date 2020/10/21 16:46 + */ public class ReadActivity extends BaseActivity { + /*****************************View***********************************/ + @BindView(R.id.toolbar) + Toolbar toolbar; + @BindView(R.id.read_abl_top_menu) + AppBarLayout readAblTopMenu; + @BindView(R.id.ll_chapter_view) + LinearLayout chapterView; + @BindView(R.id.tv_chapter_title_top) + TextView chapterTitle; + @BindView(R.id.tv_chapter_url) + TextView chapterUrl; + @BindView(R.id.read_pv_content) + PageView pageView; @BindView(R.id.pb_loading) ProgressBar pbLoading; - @BindView(R.id.read_pv_page) - PageView srlContent; @BindView(R.id.pb_nextPage) VerticalSeekBar pbNextPage; + @BindView(R.id.read_tv_page_tip) + TextView readTvPageTip; + @BindView(R.id.read_tv_pre_chapter) + TextView readTvPreChapter; + @BindView(R.id.read_sb_chapter_progress) + SeekBar readSbChapterProgress; + @BindView(R.id.read_tv_next_chapter) + TextView readTvNextChapter; + @BindView(R.id.read_tv_category) + TextView readTvCategory; + @BindView(R.id.read_tv_night_mode) + TextView readTvNightMode; + @BindView(R.id.read_tv_download) + TextView readTvDownload; + @BindView(R.id.read_tv_setting) + TextView readTvSetting; + @BindView(R.id.read_ll_bottom_menu) + LinearLayout readLlBottomMenu; + + /***************************variable*****************************/ + private ImmersionBar immersionBar; + private Book mBook; + private ArrayList mChapters = new ArrayList<>(); + private ChapterService mChapterService; + private BookService mBookService; + private BookMarkService mBookMarkService; + private NotificationUtil notificationUtil; + private Setting mSetting; + + private boolean isCollected = true;//是否在书架中 + + private boolean isPrev;//是否向前翻页 + + private boolean autoPage = false;//是否自动翻页 + + private boolean loadFinish = false; + + private Dialog mPageModeDialog;//翻页模式视图 + + private int curCacheChapterNum = 0;//缓存章节数 + + private int needCacheChapterNum;//需要缓存的章节 + + private PageLoader mPageLoader;//页面加载器 + + private int screenTimeOut;//息屏时间(单位:秒),dengy零表示常亮 + + private Runnable keepScreenRunnable;//息屏线程 + private Runnable autoPageRunnable;//自动翻页 + private Runnable upHpbNextPage;//更新自动翻页进度条 + private Runnable sendDownloadNotification; + private static boolean isStopDownload = true; + + private int tempCacheChapterNum; + private int tempCount; + private String downloadingChapter; + + private ReadCrawler mReadCrawler; - @BindView(R.id.tv_end_page_tip) - TextView tvEndPageTip; + private int nextPageTime;//下次翻页时间 - private ReadPresenter mReadPresenter; + private int upHpbInterval = 30;//更新翻页进度速度 + private int downloadInterval = 150; + + private final CharSequence[] pageMode = { + "覆盖", "仿真", "滑动", "滚动", "无动画" + }; + + private SourceExchangeDialog mSourceDialog; + private Dialog mSettingDialog; + + private boolean hasChangeSource; + + private Animation mTopInAnim; + private Animation mTopOutAnim; + private Animation mBottomInAnim; + private Animation mBottomOutAnim; + + // 接收电池信息和时间更新的广播 + private BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { + int level = intent.getIntExtra("level", 0); + try { + mPageLoader.updateBattery(level); + } catch (Exception e) { + e.printStackTrace(); + } + } + // 监听分钟的变化 + else if (Intent.ACTION_TIME_TICK.equals(intent.getAction())) { + try { + mPageLoader.updateTime(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + }; + + @SuppressLint("HandlerLeak") + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case 1: + init(); + break; + case 2: + int chapterPos = msg.arg1; + int pagePos = msg.arg2; + mPageLoader.skipToChapter(chapterPos); + mPageLoader.skipToPage(pagePos); + pbLoading.setVisibility(View.GONE); + break; + case 3: + updateDownloadProgress((TextView) msg.obj); + break; + case 4: + saveLastChapterReadPosition(); + screenOffTimerStart(); + initMenu(); + break; + case 5: + + break; + case 6: + mPageLoader.openChapter(); + if (isPrev) {//判断是否向前翻页打开章节,如果是则打开自己后跳转到最后一页,否则不跳转 + try {//概率性异常(空指针异常) + mPageLoader.skipToPage(mPageLoader.getAllPagePos() - 1); + } catch (Exception e) { + e.printStackTrace(); + } + } + break; + case 7: + ToastUtils.showWarring("无网络连接!"); + mPageLoader.chapterError(); + break; + case 8: + pbLoading.setVisibility(View.GONE); + break; + case 9: + ToastUtils.showInfo("正在后台缓存书籍,具体进度可查看通知栏!"); + notificationUtil.requestNotificationPermissionDialog(ReadActivity.this); + break; + case 10: + if (mPageLoader != null) { + mPageLoader.chapterError(); + } + } + } + }; + + + /**************************override***********************************/ @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - requestWindowFeature(Window.FEATURE_NO_TITLE); // 隐藏应用程序的标题栏,即当前activity的label - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // 隐藏android系统的状态栏 - setContentView(R.layout.activity_read_new); - ButterKnife.bind(this); - mReadPresenter = new ReadPresenter(this); - mReadPresenter.start(); + protected int getContentId() { + return R.layout.activity_read; } @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - mReadPresenter.onActivityResult(requestCode, resultCode, data); + protected void setUpToolbar(Toolbar toolbar) { + super.setUpToolbar(toolbar); + getSupportActionBar().setTitle(mBook.getName()); } + @Override + protected void initData(Bundle savedInstanceState) { + super.initData(savedInstanceState); + mBookService = BookService.getInstance(); + mChapterService = ChapterService.getInstance(); + mBookMarkService = BookMarkService.getInstance(); + mSetting = SysManager.getSetting(); + if (!loadBook()) { + finish(); + return; + } + if (SharedPreUtils.getInstance().getBoolean(getString(R.string.isNightFS), false)) { + mSetting.setDayStyle(!ColorUtil.isColorLight(getColor(R.color.textPrimary))); + } + //息屏时间 + screenTimeOut = mSetting.getResetScreen() * 60; + //保持屏幕常亮 + keepScreenRunnable = this::unKeepScreenOn; + autoPageRunnable = this::nextPage; + upHpbNextPage = this::upHpbNextPage; + sendDownloadNotification = this::sendNotification; + + notificationUtil = NotificationUtil.getInstance(); + isCollected = getIntent().getBooleanExtra("isCollected", true); + hasChangeSource = getIntent().getBooleanExtra("hasChangeSource", false); - public ReadPresenter getmReadPresenter() { - return mReadPresenter; + mReadCrawler = ReadCrawlerUtil.getReadCrawler(mBook.getSource()); + mPageLoader = pageView.getPageLoader(mBook, mReadCrawler, mSetting); + //Dialog + mSourceDialog = new SourceExchangeDialog(this, mBook); } - public PageView getSrlContent() { - return srlContent; + @Override + protected void initWidget() { + super.initWidget(); + ImmersionBar.with(this).fullScreen(true).init(); + //隐藏StatusBar + pageView.post( + this::hideSystemBar + ); + if (!mSetting.isBrightFollowSystem()) { + BrightUtil.setBrightness(this, BrightUtil.progressToBright(mSetting.getBrightProgress())); + } + pbLoading.setVisibility(View.VISIBLE); + createSettingDetailView(); + initTopMenu(); + initBottomMenu(); } + @Override + protected void initClick() { + super.initClick(); + pageView.setTouchListener(new PageView.TouchListener() { + @Override + public boolean onTouch() { + return !hideReadMenu(); + } - public ProgressBar getPbLoading() { - return pbLoading; - } + @Override + public void center() { + toggleMenu(true); + if (autoPage) { + autoPageStop(); + } + } + + @Override + public void prePage() { + isPrev = true; + } + + @Override + public void nextPage(boolean hasNextPage) { + isPrev = false; + if (!hasNextPage) { + if (autoPage) { + autoPageStop(); + } + } + } + @Override + public void cancel() { + } + }); + mPageLoader.setOnPageChangeListener( + new PageLoader.OnPageChangeListener() { + @Override + public void onChapterChange(int pos) { + lastLoad(pos); + for (int i = 0; i < 5; i++) { + preLoad(pos - 1 + i); + } + mBook.setHistoryChapterId(mChapters.get(pos).getTitle()); + mHandler.sendMessage(mHandler.obtainMessage(4)); + MyApplication.getApplication().newThread(() -> { + if (mPageLoader.getPageStatus() == PageLoader.STATUS_LOADING) { + if (!NetworkUtils.isNetWorkAvailable()) { + mHandler.sendMessage(mHandler.obtainMessage(7)); + } else { + mHandler.sendMessage(mHandler.obtainMessage(6)); + } + } + }); + + } + + @Override + public void requestChapters(List requestChapters) { + /*for (final Chapter chapter : requestChapters){ + getChapterContent(chapter, null); + }*/ + } + + @Override + public void onCategoryFinish(List chapters) { + } - public TextView getTvEndPageTip() { - return tvEndPageTip; + @Override + public void onPageCountChange(int count) { + + } + + @Override + public void onPageChange(int pos) { + mHandler.sendMessage(mHandler.obtainMessage(4)); + } + } + ); + + readSbChapterProgress.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + readTvPageTip.setText((progress + 1) + "/" + (seekBar.getMax() + 1)); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + //进行切换 + int pagePos = seekBar.getProgress(); + if (pagePos != mPageLoader.getPagePos() && pagePos < mPageLoader.getAllPagePos()) { + mPageLoader.skipToPage(pagePos); + } + } + }); + + 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; + toggleMenu(true); + Intent intent = new Intent(this, ReadActivity.class) + .putExtra(APPCONST.BOOK, mBook) + .putExtra("hasChangeSource", true); + if (!isCollected) { + intent.putExtra("isCollected", false); + } + finish(); + startActivity(intent); + }); } + @Override + protected void processLogic() { + super.processLogic(); + //注册广播 + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); + intentFilter.addAction(Intent.ACTION_TIME_TICK); + registerReceiver(mReceiver, intentFilter); + + //当书籍Collected且书籍id不为空的时候保存上次阅读信息 + if (isCollected && !StringHelper.isEmpty(mBook.getId())) { + //保存上次阅读信息 + SharedPreUtils.getInstance().putString(getString(R.string.lastRead), mBook.getId()); + } + getData(); + } @Override - protected void onDestroy() { - mReadPresenter.onDestroy(); - super.onDestroy(); + protected void onResume() { + super.onResume(); + hideSystemBar(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + boolean isVolumeTurnPage = SysManager.getSetting().isVolumeTurnPage(); + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_UP: + if (isVolumeTurnPage) { + return mPageLoader.skipToPrePage(); + } + case KeyEvent.KEYCODE_VOLUME_DOWN: + if (isVolumeTurnPage) { + return mPageLoader.skipToNextPage(); + } + } + return super.onKeyDown(keyCode, event); } - /*@Override - protected void onPause() { - super.onPause(); - }*/ @Override public void onBackPressed() { - if (!mReadPresenter.isCollected()){ - DialogCreator.createCommonDialog(ReadActivity.this, "加入书架", "喜欢本书就加入书架吧", true, new DialogInterface.OnClickListener() { + if (readAblTopMenu.getVisibility() == View.VISIBLE) { + // 非全屏下才收缩,全屏下直接退出 + //if (!ReadSettingManager.getInstance().isFullScreen()) { + if (true) { + toggleMenu(true); + return; + } + } else if (mSettingDialog.isShowing()) { + mSettingDialog.dismiss(); + return; + } + finish(); + } + + @Override + public void finish() { + if (!isCollected) { + DialogCreator.createCommonDialog(this, "加入书架", "喜欢本书就加入书架吧", true, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mReadPresenter.saveLastChapterReadPosition(); - mReadPresenter.setCollected(true); + saveLastChapterReadPosition(); + isCollected = true; exit(); } } , (dialog, which) -> { - mReadPresenter.deleteBook(); + mBookService.deleteBookById(mBook.getId()); exit(); }); } else { - mReadPresenter.saveLastChapterReadPosition(); + saveLastChapterReadPosition(); exit(); } } - private void exit(){ + private void exit() { // 返回给BookDetail Intent result = new Intent(); - result.putExtra(APPCONST.RESULT_IS_COLLECTED, mReadPresenter.isCollected()); - if (mReadPresenter.getmPageLoader() != null) { - result.putExtra(APPCONST.RESULT_LAST_READ_POSITION, mReadPresenter.getmPageLoader().getPagePos()); - result.putExtra(APPCONST.RESULT_HISTORY_CHAPTER, mReadPresenter.getmPageLoader().getChapterPos()); + result.putExtra(APPCONST.RESULT_IS_COLLECTED, isCollected); + if (mPageLoader != null) { + result.putExtra(APPCONST.RESULT_LAST_READ_POSITION, mPageLoader.getPagePos()); + result.putExtra(APPCONST.RESULT_HISTORY_CHAPTER, mPageLoader.getChapterPos()); } setResult(AppCompatActivity.RESULT_OK, result); if (!ActivityManage.isExist(MainActivity.class)) { @@ -123,27 +537,990 @@ public class ReadActivity extends BaseActivity { startActivity(intent); } Backup.INSTANCE.autoBack(); - super.onBackPressed(); + super.finish(); } + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(mReceiver); + mHandler.removeCallbacks(keepScreenRunnable); + mHandler.removeCallbacks(upHpbNextPage); + mHandler.removeCallbacks(autoPageRunnable); + /*mHandler.removeCallbacks(sendDownloadNotification); + notificationUtil.cancelAll(); + MyApplication.getApplication().shutdownThreadPool();*/ + if (autoPage) { + autoPageStop(); + } + for (int i = 0; i < 9; i++) { + mHandler.removeMessages(i + 1); + } + if (mPageLoader != null) { + mPageLoader.closeBook(); + mPageLoader = null; + } + } @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - boolean isVolumeTurnPage = SysManager.getSetting().isVolumeTurnPage(); - switch (keyCode) { - case KeyEvent.KEYCODE_VOLUME_UP : - if (isVolumeTurnPage) { - return mReadPresenter.getmPageLoader().skipToPrePage(); + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_read, menu); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + if ("本地书籍".equals(mBook.getType())) { + menu.findItem(R.id.action_change_source).setVisible(false); + menu.findItem(R.id.action_open_link).setVisible(false); + } + menu.setGroupVisible(R.id.action_load_finish, loadFinish); + + return super.onPrepareOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_change_source: + mSourceDialog.show(); + break; + case R.id.action_reload: + isPrev = false; + if (!"本地书籍".equals(mBook.getType())) { + mChapterService.deleteChapterCacheFile(mChapters.get(mPageLoader.getChapterPos())); } - case KeyEvent.KEYCODE_VOLUME_DOWN : - if (isVolumeTurnPage) { - return mReadPresenter.getmPageLoader().skipToNextPage(); + mPageLoader.refreshChapter(mChapters.get(mPageLoader.getChapterPos())); + break; + case R.id.action_add_bookmark: + if (mChapters == null || mChapters.size() == 0) { + if ("本地书籍".equals(mBook.getType())) { + ToastUtils.showWarring("请等待章节拆分完成后再添加书签"); + } else { + ToastUtils.showError("章节目录为空,添加书签失败!"); + } + return true; } + Chapter curChapter = mChapters.get(mPageLoader.getChapterPos()); + BookMark bookMark = new BookMark(); + bookMark.setBookId(mBook.getId()); + bookMark.setTitle(curChapter.getTitle()); + bookMark.setBookMarkChapterNum(mPageLoader.getChapterPos()); + bookMark.setBookMarkReadPosition(mPageLoader.getPagePos()); + mBookMarkService.addOrUpdateBookMark(bookMark); + DialogCreator.createTipDialog(this, "《" + mBook.getName() + + "》:" + bookMark.getTitle() + "[" + (bookMark.getBookMarkReadPosition() + 1) + + "]\n书签添加成功,书签列表可在目录界面查看!"); + return true; + case R.id.action_copy_content: + new CopyContentDialog(this, mPageLoader.getContent()).show(); + break; + case R.id.action_open_link: + Uri uri = Uri.parse(mBook.getChapterUrl()); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + startActivity(intent); + break; } - return super.onKeyDown(keyCode, event); + return super.onOptionsItemSelected(item); + } + + /** + * 结果回调 + * + * @param requestCode + * @param resultCode + * @param data + */ + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode == RESULT_OK) { + switch (requestCode) { + case APPCONST.REQUEST_FONT: + Font font = (Font) data.getSerializableExtra(APPCONST.FONT); + mSetting.setFont(font); +// init(); + MyApplication.runOnUiThread(() -> mPageLoader.setFont(font)); + break; + case APPCONST.REQUEST_CHAPTER_PAGE: + int[] chapterAndPage = data.getIntArrayExtra(APPCONST.CHAPTER_PAGE); + assert chapterAndPage != null; + skipToChapterAndPage(chapterAndPage[0], chapterAndPage[1]); + break; + case APPCONST.REQUEST_RESET_SCREEN_TIME: + int resetScreen = data.getIntExtra(APPCONST.RESULT_RESET_SCREEN, 0); + screenTimeOut = resetScreen * 60; + screenOffTimerStart(); + break; + } + } + } + /**************************method*********************************/ + /** + * 初始化 + */ + private void init() { + screenOffTimerStart(); + mPageLoader.init(); + mPageLoader.refreshChapterList(); + loadFinish = true; + invalidateOptionsMenu(); + mHandler.sendMessage(mHandler.obtainMessage(8)); + } + + private void initMenu() { + if (mChapters != null && mChapters.size() != 0) { + Chapter curChapter = mChapters.get(mPageLoader.getChapterPos()); + String url = curChapter.getUrl(); + chapterTitle.setText(curChapter.getTitle()); + chapterUrl.setText(StringHelper.isEmpty(url) ? curChapter.getId() : url); + readSbChapterProgress.setProgress(mPageLoader.getPagePos()); + readSbChapterProgress.setMax(mPageLoader.getAllPagePos() - 1); + readTvPageTip.setText((readSbChapterProgress.getProgress() + 1) + "/" + (readSbChapterProgress.getMax() + 1)); + } + } + /************************书籍相关******************************/ + /** + * 进入阅读书籍有三种方式: + * 1、直接从书架进入,这种方式书籍一定Collected + * 2、从外部打开txt文件,这种方式会添加进书架 + * 3、从快捷图标打开上次阅读书籍 + * + * @return 是否加载成功 + */ + private boolean loadBook() { + //是否直接打开本地txt文件 + String path = null; + if (Intent.ACTION_VIEW.equals(getIntent().getAction())) { + Uri uri = getIntent().getData(); + if (uri != null) { + path = getPath(this, uri); + } + } + if (!StringHelper.isEmpty(path)) { + //本地txt文件路径不为空,添加书籍 + addLocalBook(path); + } else { + //路径为空,说明不是直接打开txt文件 + mBook = (Book) getIntent().getSerializableExtra(APPCONST.BOOK); + //mBook为空,说明是从快捷方式启动 + if (mBook == null) { + String bookId = SharedPreUtils.getInstance().getString(getString(R.string.lastRead), ""); + if ("".equals(bookId)) {//没有上次阅读信息 + ToastUtils.showWarring("当前没有阅读任何书籍,无法加载上次阅读书籍!"); + finish(); + return false; + } else {//有信息 + mBook = mBookService.getBookById(bookId); + if (mBook == null) {//上次阅读的书籍不存在 + ToastUtils.showWarring("上次阅读书籍已不存在/移除书架,无法加载!"); + finish(); + return false; + }//存在就继续执行 + } + } + } + return true; + } + + /** + * 添加本地书籍 + * + * @param path + */ + private void addLocalBook(String path) { + File file = new File(path); + if (!file.exists()) { + return; + } + Book book = new Book(); + book.setName(file.getName().replace(".txt", "")); + book.setChapterUrl(path); + book.setType("本地书籍"); + book.setHistoryChapterId("未开始阅读"); + book.setNewestChapterTitle("未拆分章节"); + book.setAuthor("本地书籍"); + book.setSource(BookSource.local.toString()); + book.setDesc("无"); + book.setIsCloseUpdate(true); + //判断书籍是否已经添加 + Book existsBook = mBookService.findBookByAuthorAndName(book.getName(), book.getAuthor()); + if (book.equals(existsBook)) { + mBook = existsBook; + return; + } + + mBookService.addBook(book); + mBook = book; + } + + /** + * 添加到书架并缓存书籍 + * + * @param tvDownloadProgress + */ + private void addBookToCaseAndDownload(final TextView tvDownloadProgress) { + DialogCreator.createCommonDialog(this, this.getString(R.string.tip), this.getString(R.string.download_no_add_tips), true, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + downloadBook(tvDownloadProgress); + isCollected = true; + } + }, (dialog, which) -> dialog.dismiss()); + } + /************************章节相关*************************/ + /** + * 章节数据网络同步 + */ + private void getData() { + mChapters = (ArrayList) mChapterService.findBookAllChapterByBookId(mBook.getId()); + if (!isCollected || mChapters.size() == 0 || ("本地书籍".equals(mBook.getType()) && + !ChapterService.isChapterCached(mBook.getId(), mChapters.get(0).getTitle()))) { + if ("本地书籍".equals(mBook.getType())) { + if (!new File(mBook.getChapterUrl()).exists()) { + ToastUtils.showWarring("书籍缓存为空且源文件不存在,书籍加载失败!"); + finish(); + return; + } + ((LocalPageLoader) mPageLoader).loadChapters(new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + ArrayList chapters = (ArrayList) o; + mBook.setChapterTotalNum(chapters.size()); + mBook.setNewestChapterTitle(chapters.get(chapters.size() - 1).getTitle()); + mBookService.updateEntity(mBook); + if (mChapters.size() == 0) { + updateAllOldChapterData(chapters); + } + initChapters(); + mHandler.sendMessage(mHandler.obtainMessage(1)); + } + + @Override + public void onError(Exception e) { + mChapters.clear(); + initChapters(); + mHandler.sendMessage(mHandler.obtainMessage(1)); + } + }); + } else { + CommonApi.getBookChapters(mBook.getChapterUrl(), mReadCrawler, false, new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + ArrayList chapters = (ArrayList) o; + updateAllOldChapterData(chapters); + initChapters(); + } + + @Override + public void onError(Exception e) { +// settingChange = true; + initChapters(); + mHandler.sendMessage(mHandler.obtainMessage(1)); + } + }); + } + } else { + initChapters(); + } + } + + /** + * 更新所有章节 + * + * @param newChapters + */ + private void updateAllOldChapterData(ArrayList newChapters) { + for (Chapter newChapter : newChapters) { + newChapter.setId(StringHelper.getStringRandom(25)); + newChapter.setBookId(mBook.getId()); + mChapters.add(newChapter); +// mChapterService.addChapter(newChapters.get(j)); + } + mChapterService.addChapters(mChapters); + } + + /** + * 初始化章节 + */ + private void initChapters() { + mBook.setNoReadNum(0); + mBook.setChapterTotalNum(mChapters.size()); + if (!StringHelper.isEmpty(mBook.getId())) { + mBookService.updateEntity(mBook); + } + if (mChapters.size() == 0) { + ToastUtils.showWarring("该书查询不到任何章节"); + mHandler.sendMessage(mHandler.obtainMessage(8)); + } else { + if (mBook.getHisttoryChapterNum() < 0) { + mBook.setHisttoryChapterNum(0); + } else if (mBook.getHisttoryChapterNum() >= mChapters.size()) { + mBook.setHisttoryChapterNum(mChapters.size() - 1); + } + if ("本地书籍".equals(mBook.getType())) { + 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) { +// mChapters.get(mBook.getHisttoryChapterNum()).setContent((String) o); + mChapterService.saveOrUpdateChapter(mChapters.get(mBook.getHisttoryChapterNum()), (String) o); + mHandler.sendMessage(mHandler.obtainMessage(1)); +// getAllChapterData(); + } + + @Override + public void onError(Exception e) { + mHandler.sendMessage(mHandler.obtainMessage(1)); + } + }); + initMenu(); + } + } + + + /** + * 跳转到指定章节的指定页面 + * + * @param chapterPos + * @param pagePos + */ + private void skipToChapterAndPage(final int chapterPos, final int pagePos) { + isPrev = false; + if (StringHelper.isEmpty(mChapters.get(chapterPos).getContent())) { + if ("本地书籍".equals(mBook.getType())) { + ToastUtils.showWarring("该章节无内容!"); + return; + } + pbLoading.setVisibility(View.VISIBLE); + getChapterContent(mChapters.get(chapterPos), new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + mChapterService.saveOrUpdateChapter(mChapters.get(chapterPos), (String) o); + mHandler.sendMessage(mHandler.obtainMessage(2, chapterPos, pagePos)); + } + + @Override + public void onError(Exception e) { + mHandler.sendMessage(mHandler.obtainMessage(2, chapterPos, pagePos)); + mHandler.sendEmptyMessage(10); + } + }); + } else { + mHandler.sendMessage(mHandler.obtainMessage(2, chapterPos, pagePos)); + } + } + + /** + * 获取章节内容 + * + * @param chapter + * @param resultCallback + */ + private void getChapterContent(final Chapter chapter, ResultCallback resultCallback) { + if (StringHelper.isEmpty(chapter.getBookId())) { + chapter.setId(mBook.getId()); + } + if (!StringHelper.isEmpty(chapter.getContent())) { + if (resultCallback != null) { + resultCallback.onFinish(mChapterService.getChapterCatheContent(chapter), 0); + } + } else { + if ("本地书籍".equals(mBook.getType())) { + return; + } + if (resultCallback != null) { + CommonApi.getChapterContent(chapter.getUrl(), mReadCrawler, resultCallback); + } else { + CommonApi.getChapterContent(chapter.getUrl(), mReadCrawler, new ResultCallback() { + @Override + public void onFinish(final Object o, int code) { +// chapter.setContent((String) o); + mChapterService.saveOrUpdateChapter(chapter, (String) o); + } + + @Override + public void onError(Exception e) { + + } + + }); + } + } + } + + /** + * 预加载下一章 + */ + private void preLoad(int position) { + if (position + 1 < mChapters.size()) { + Chapter chapter = mChapters.get(position + 1); + if (StringHelper.isEmpty(chapter.getContent())) { + mPageLoader.getChapterContent(chapter); + } + } + } + + /** + * 预加载上一章 + * + * @param position + */ + private void lastLoad(int position) { + if (position > 0) { + Chapter chapter = mChapters.get(position - 1); + if (StringHelper.isEmpty(chapter.getContent())) { + mPageLoader.getChapterContent(chapter); + } + } + } + + /** + * 保存最后阅读章节的进度 + */ + public void saveLastChapterReadPosition() { + if (!StringHelper.isEmpty(mBook.getId()) && mPageLoader.getPageStatus() == PageLoader.STATUS_FINISH) { + mBook.setLastReadPosition(mPageLoader.getPagePos()); + mBook.setHisttoryChapterNum(mPageLoader.getChapterPos()); + mBookService.updateEntity(mBook); + } + } + /********************菜单相关*************************/ + /** + * 初始化顶部菜单 + */ + private void initTopMenu() { + if (Build.VERSION.SDK_INT >= 19) { + readAblTopMenu.setPadding(0, ImmersionBar.getStatusBarHeight(this), 0, 0); + } + } + + /** + * 初始化底部菜单 + */ + private void initBottomMenu() { + //判断是否全屏 + //if (mSetting.getHideStatusBar()) { + if (!mSetting.isDayStyle()) { + readTvNightMode.setText("白天"); + Drawable drawable = ContextCompat.getDrawable(this, R.mipmap.z4); + readTvNightMode.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null); + } + if (true) { + //还需要设置mBottomMenu的底部高度 + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) readLlBottomMenu.getLayoutParams(); + params.bottomMargin = ImmersionBar.getNavigationBarHeight(this); + readLlBottomMenu.setLayoutParams(params); + } else { + //设置mBottomMenu的底部距离 + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) readLlBottomMenu.getLayoutParams(); + params.bottomMargin = 0; + readLlBottomMenu.setLayoutParams(params); + } + } + + /** + * 隐藏阅读界面的菜单显示 + * + * @return 是否隐藏成功 + */ + private boolean hideReadMenu() { + hideSystemBar(); + if (readAblTopMenu.getVisibility() == VISIBLE) { + toggleMenu(true); + return true; + } else if (mSettingDialog.isShowing()) { + mSettingDialog.dismiss(); + return true; + } + return false; + } + + /** + * 切换菜单栏的可视状态 + * 默认是隐藏的 + */ + private void toggleMenu(boolean hideStatusBar) { + initMenuAnim(); + if (readAblTopMenu.getVisibility() == View.VISIBLE) { + //关闭 + readAblTopMenu.startAnimation(mTopOutAnim); + readLlBottomMenu.startAnimation(mBottomOutAnim); + readAblTopMenu.setVisibility(GONE); + readLlBottomMenu.setVisibility(GONE); + readTvPageTip.setVisibility(GONE); + if (hideStatusBar) { + hideSystemBar(); + } + } else { + readTvPageTip.setVisibility(VISIBLE); + readAblTopMenu.setVisibility(View.VISIBLE); + readLlBottomMenu.setVisibility(View.VISIBLE); + readAblTopMenu.startAnimation(mTopInAnim); + readLlBottomMenu.startAnimation(mBottomInAnim); + showSystemBar(); + } + } + + //初始化菜单动画 + private void initMenuAnim() { + if (mTopInAnim != null) return; + mTopInAnim = AnimationUtils.loadAnimation(this, R.anim.slide_top_in); + mTopOutAnim = AnimationUtils.loadAnimation(this, R.anim.slide_top_out); + mBottomInAnim = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_in); + mBottomOutAnim = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_out); + } + + private void showSystemBar() { + //显示 + SystemBarUtils.showUnStableStatusBar(this); + SystemBarUtils.showUnStableNavBar(this); + } + + private void hideSystemBar() { + //隐藏 + SystemBarUtils.hideStableStatusBar(this); + SystemBarUtils.hideStableNavBar(this); + } + + /******************设置相关*****************/ + + + /** + * 创建详细设置视图 + */ + private void createSettingDetailView() { + mSettingDialog = DialogCreator.createReadDetailSetting(this, mSetting, + this::changeStyle, v -> reduceTextSize(), v -> increaseTextSize(), v -> { + if (mSetting.isVolumeTurnPage()) { + mSetting.setVolumeTurnPage(false); + ToastUtils.showSuccess("音量键翻页已关闭!"); + } else { + mSetting.setVolumeTurnPage(true); + ToastUtils.showSuccess("音量键翻页已开启!"); + } + SysManager.saveSetting(mSetting); + }, v -> { + Intent intent = new Intent(this, FontsActivity.class); + startActivityForResult(intent, APPCONST.REQUEST_FONT); + mSettingDialog.dismiss(); + }, this::showPageModeDialog, v -> { + if (mSetting.getPageMode() == PageMode.SCROLL) { + ToastUtils.showWarring("滚动暂时不支持自动翻页"); + return; + } + mSettingDialog.dismiss(); + autoPage = !autoPage; + autoPage(); + }, v -> { + Intent intent = new Intent(this, MoreSettingActivity.class); + startActivityForResult(intent, APPCONST.REQUEST_RESET_SCREEN_TIME); + mSettingDialog.dismiss(); + }); + } + + private void showPageModeDialog(final TextView tvPageMode) { + if (mPageModeDialog != null) { + mPageModeDialog.show(); + } else { + //显示翻页模式视图 + int checkedItem; + switch (mSetting.getPageMode()) { + case COVER: + checkedItem = 0; + break; + case SIMULATION: + checkedItem = 1; + break; + case SLIDE: + checkedItem = 2; + break; + case SCROLL: + checkedItem = 3; + break; + case NONE: + checkedItem = 4; + break; + default: + checkedItem = 0; + } + mPageModeDialog = MyAlertDialog.build(this) + .setTitle("翻页模式") + .setSingleChoiceItems(pageMode, checkedItem, (dialog, which) -> { + switch (which) { + case 0: + mSetting.setPageMode(PageMode.COVER); + break; + case 1: + mSetting.setPageMode(PageMode.SIMULATION); + break; + case 2: + mSetting.setPageMode(PageMode.SLIDE); + break; + case 3: + mSetting.setPageMode(PageMode.SCROLL); + break; + case 4: + mSetting.setPageMode(PageMode.NONE); + break; + } + mPageModeDialog.dismiss(); + SysManager.saveSetting(mSetting); + MyApplication.runOnUiThread(() -> mPageLoader.setPageMode(mSetting.getPageMode())); + tvPageMode.setText(pageMode[which]); + }).show(); + } + } + + /** + * 白天夜间改变 + */ + private void changeNightAndDaySetting(boolean isNight) { + mSetting.setDayStyle(!isNight); + SysManager.saveSetting(mSetting); + MyApplication.getApplication().setNightTheme(isNight); + //mPageLoader.setPageStyle(!isCurDayStyle); + } + + /** + * 缩小字体 + */ + private void reduceTextSize() { + if (mSetting.getReadWordSize() > 1) { + mSetting.setReadWordSize(mSetting.getReadWordSize() - 1); + SysManager.saveSetting(mSetting); + mPageLoader.setTextSize((int) mSetting.getReadWordSize()); + } + } + + /** + * 增大字体 + */ + private void increaseTextSize() { + if (mSetting.getReadWordSize() < 41) { + mSetting.setReadWordSize(mSetting.getReadWordSize() + 1); + SysManager.saveSetting(mSetting); + mPageLoader.setTextSize((int) mSetting.getReadWordSize()); + } + } + + /** + * 改变阅读风格 + * + * @param readStyle + */ + private void changeStyle(ReadStyle readStyle) { + mSetting.setReadStyle(readStyle); + SysManager.saveSetting(mSetting); + if (!mSetting.isDayStyle()) { + DialogCreator.createCommonDialog(this, "提示", "是否希望切换为日间模式?", + false, "确定", "取消", (dialog, which) -> { + changeNightAndDaySetting(false); + }, null); + } + MyApplication.runOnUiThread(() -> mPageLoader.setPageStyle(true)); + } + + @OnClick({R.id.read_tv_setting, R.id.read_tv_pre_chapter + , R.id.read_tv_next_chapter, R.id.read_tv_night_mode}) + protected void onClick(View view) { + switch (view.getId()) { + case R.id.read_tv_setting: //设置 + toggleMenu(true); + mSettingDialog.show(); + break; + case R.id.read_tv_pre_chapter: //前一章 + mPageLoader.skipPreChapter(); + break; + case R.id.read_tv_next_chapter: //后一章 + mPageLoader.skipNextChapter(); + break; + case R.id.read_tv_night_mode: //夜间模式 + changeNightAndDaySetting(mSetting.isDayStyle()); + break; + } + } + + /** + * 跳转到目录 + */ + @OnClick(R.id.read_tv_category) + protected void goToCatalog() { + //切换菜单 + toggleMenu(true); + //跳转 + Intent intent = new Intent(this, CatalogActivity.class); + intent.putExtra(APPCONST.BOOK, mBook); + this.startActivityForResult(intent, APPCONST.REQUEST_CHAPTER_PAGE); + } + + @OnClick(R.id.ll_chapter_view) + protected void gotoUrl() { + if (mChapters != null && mChapters.size() != 0) { + Chapter curChapter = mChapters.get(mPageLoader.getChapterPos()); + String url = curChapter.getUrl(); + if (!"本地书籍".equals(mBook.getType()) && !StringHelper.isEmpty(url)) { + Intent intent = new Intent(Intent.ACTION_VIEW); + Uri uri = Uri.parse(url); + intent.setData(uri); + startActivity(intent); + } + } + } + + @OnClick(R.id.read_tv_download) + protected void download() { + if (!isCollected) { + addBookToCaseAndDownload(readTvDownload); + } else { + downloadBook(readTvDownload); + } + } + /****************息屏相关*****************/ + /** + * 取消亮屏保持 + */ + private void unKeepScreenOn() { + keepScreenOn(false); + } + + /** + * @param keepScreenOn 是否保持亮屏 + */ + public void keepScreenOn(boolean keepScreenOn) { + if (keepScreenOn) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } else { + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + } + + /** + * 重置黑屏时间 + */ + private void screenOffTimerStart() { + if (screenTimeOut <= 0) { + keepScreenOn(true); + return; + } + int screenOffTime = screenTimeOut * 1000 - ScreenHelper.getScreenOffTime(this); + if (screenOffTime > 0) { + mHandler.removeCallbacks(keepScreenRunnable); + keepScreenOn(true); + mHandler.postDelayed(keepScreenRunnable, screenOffTime); + } else { + keepScreenOn(false); + } + } + + /***************************缓存相关***************************/ + private int selectedIndex;//对话框选择下标 + + protected void downloadBook(final TextView tvDownloadProgress) { + if ("本地书籍".equals(mBook.getType())) { + ToastUtils.showWarring("《" + mBook.getName() + "》是本地书籍,不能缓存"); + return; + } + if (!NetworkUtils.isNetWorkAvailable()) { + ToastUtils.showWarring("无网络连接!"); + return; + } + MyApplication.runOnUiThread(() -> { + MyAlertDialog.build(this) + .setTitle("缓存书籍") + .setSingleChoiceItems(APPCONST.DIALOG_DOWNLOAD, selectedIndex, (dialog, which) -> selectedIndex = which).setNegativeButton("取消", ((dialog, which) -> dialog.dismiss())).setPositiveButton("确定", + (dialog, which) -> { + switch (selectedIndex) { + case 0: + addDownload(tvDownloadProgress, mPageLoader.getChapterPos(), mPageLoader.getChapterPos() + 50); + break; + case 1: + addDownload(tvDownloadProgress, mPageLoader.getChapterPos() - 50, mPageLoader.getChapterPos() + 50); + break; + case 2: + addDownload(tvDownloadProgress, mPageLoader.getChapterPos(), mChapters.size()); + break; + case 3: + addDownload(tvDownloadProgress, 0, mChapters.size()); + break; + } + }).show(); + }); + } + + private void addDownload(final TextView tvDownloadProgress, int begin, int end) { + /*//取消之前下载 + if (!isStopDownload) { + isStopDownload = true; + try { + Thread.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }*/ + if (SysManager.getSetting().getCatheGap() != 0) { + downloadInterval = SysManager.getSetting().getCatheGap(); + } + //计算断点章节 + final int finalBegin = Math.max(0, begin); + final int finalEnd = Math.min(end, mChapters.size()); + needCacheChapterNum = finalEnd - finalBegin; + curCacheChapterNum = 0; + isStopDownload = false; + ArrayList needDownloadChapters = new ArrayList<>(); + for (int i = finalBegin; i < finalEnd; i++) { + final Chapter chapter = mChapters.get(i); + if (StringHelper.isEmpty(chapter.getContent())) { + needDownloadChapters.add(chapter); + } + } + needCacheChapterNum = needDownloadChapters.size(); + if (needCacheChapterNum > 0) { + mHandler.sendEmptyMessage(9); + mHandler.postDelayed(sendDownloadNotification, 2 * downloadInterval); + } + MyApplication.getApplication().newThread(() -> { + for (Chapter chapter : needDownloadChapters) { + getChapterContent(chapter, new ResultCallback() { + @Override + public void onFinish(Object o, int code) { + downloadingChapter = chapter.getTitle(); + mChapterService.saveOrUpdateChapter(chapter, (String) o); + curCacheChapterNum++; + mHandler.sendMessage(mHandler.obtainMessage(3, tvDownloadProgress)); + } + + @Override + public void onError(Exception e) { + curCacheChapterNum++; + mHandler.sendMessage(mHandler.obtainMessage(3, tvDownloadProgress)); + } + }); + try { + Thread.sleep(downloadInterval); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (isStopDownload) { + break; + } + } + if (curCacheChapterNum == needCacheChapterNum) { + ToastUtils.showInfo("《" + mBook.getName() + "》" + getString(R.string.download_already_all_tips)); + } + }); + } + + + private void updateDownloadProgress(TextView tvDownloadProgress) { + try { + tvDownloadProgress.setText(curCacheChapterNum * 100 / needCacheChapterNum + " %"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 发送通知 + */ + private void sendNotification() { + if (curCacheChapterNum == needCacheChapterNum) { + notificationUtil.cancel(1001); + return; + } else { + Notification notification = notificationUtil.build(APPCONST.channelIdDownload) + .setSmallIcon(R.drawable.ic_download) + //通知栏大图标 + .setLargeIcon(BitmapFactory.decodeResource(MyApplication.getApplication().getResources(), R.mipmap.ic_launcher)) + .setOngoing(true) + //点击通知后自动清除 + .setAutoCancel(true) + .setContentTitle("正在下载:" + mBook.getName() + + "[" + curCacheChapterNum + "/" + needCacheChapterNum + "]") + .setContentText(downloadingChapter == null ? " " : downloadingChapter) + .addAction(R.drawable.ic_stop_black_24dp, "停止", + notificationUtil.getChancelPendingIntent(cancelDownloadReceiver.class)) + .build(); + notificationUtil.notify(1001, notification); + } + if (tempCacheChapterNum < curCacheChapterNum) { + tempCount = 1500 / downloadInterval; + tempCacheChapterNum = curCacheChapterNum; + } else if (tempCacheChapterNum == curCacheChapterNum) { + tempCount--; + if (tempCount == 0) { + notificationUtil.cancel(1001); + return; + } + } + mHandler.postDelayed(sendDownloadNotification, 2 * downloadInterval); + } + + public static class cancelDownloadReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + //todo 跳转之前要处理的逻辑 + if (NotificationClickReceiver.CANCEL_ACTION.equals(intent.getAction())) { + isStopDownload = true; + } + } + } + + + /*******************************自动翻页相关************************************/ + /** + * 自动翻页 + */ + private void autoPage() { + mHandler.removeCallbacks(upHpbNextPage); + mHandler.removeCallbacks(autoPageRunnable); + if (autoPage) { + pbNextPage.setVisibility(View.VISIBLE); + //每页按字数计算一次时间 + nextPageTime = mPageLoader.curPageLength() * 60 * 1000 / mSetting.getAutoScrollSpeed(); + if (0 == nextPageTime) nextPageTime = 1000; + pbNextPage.setMax(nextPageTime); + mHandler.postDelayed(autoPageRunnable, nextPageTime); + nextPageTime = nextPageTime - upHpbInterval * 10; + mHandler.postDelayed(upHpbNextPage, upHpbInterval); + } else { + pbNextPage.setVisibility(View.INVISIBLE); + } + } + + /** + * 更新自动翻页进度条 + */ + private void upHpbNextPage() { + nextPageTime = nextPageTime - upHpbInterval; + if (nextPageTime >= 0) { + pbNextPage.setProgress(nextPageTime); + } + mHandler.postDelayed(upHpbNextPage, upHpbInterval); + } + + /** + * 停止自动翻页 + */ + private void autoPageStop() { + autoPage = false; + autoPage(); } - public VerticalSeekBar getPbNextPage() { - return pbNextPage; + /** + * 下一页 + */ + private void nextPage() { + MyApplication.runOnUiThread(() -> { + screenOffTimerStart(); + if (mPageLoader != null) { + mPageLoader.skipToNextPage(); + } + autoPage(); + }); } } 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 deleted file mode 100644 index 9d2965b..0000000 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/RegisterActivity.java +++ /dev/null @@ -1,271 +0,0 @@ -package xyz.fycz.myreader.ui.activity; - -import android.annotation.SuppressLint; -import android.app.ProgressDialog; -import android.graphics.Bitmap; -import android.os.Handler; -import android.os.Message; -import android.text.Editable; -import android.text.TextWatcher; -import android.text.method.LinkMovementMethod; -import android.view.View; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.ImageView; -import android.widget.TextView; -import androidx.appcompat.widget.Toolbar; -import butterknife.BindView; -import com.google.android.material.textfield.TextInputLayout; -import xyz.fycz.myreader.R; -import xyz.fycz.myreader.model.backup.UserService; -import xyz.fycz.myreader.base.BaseActivity2; -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; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author fengyue - * @date 2020/9/18 22:37 - */ -public class RegisterActivity extends BaseActivity2 { - @BindView(R.id.et_username) - TextInputLayout etUsername; - @BindView(R.id.et_password) - TextInputLayout etPassword; - @BindView(R.id.et_rp_password) - TextInputLayout etRpPassword; - @BindView(R.id.et_captcha) - TextInputLayout etCaptcha; - @BindView(R.id.iv_captcha) - ImageView ivCaptcha; - @BindView(R.id.bt_register) - Button btRegister; - @BindView(R.id.tv_register_tip) - TextView tvRegisterTip; - @BindView(R.id.cb_agreement) - CheckBox cbAgreement; - @BindView(R.id.tv_agreement) - TextView tvAgreement; - private String code; - private String username = ""; - private String password = ""; - private String rpPassword = ""; - private String inputCode = ""; - - @SuppressLint("HandlerLeak") - private Handler mHandler = new Handler() { - @SuppressLint("HandlerLeak") - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case 1: - createCaptcha(); - break; - case 2: - showTip((String) msg.obj); - break; - case 3: - tvRegisterTip.setVisibility(View.GONE); - break; - } - } - }; - - - @Override - protected int getContentId() { - return R.layout.activity_register; - } - - @Override - protected void setUpToolbar(Toolbar toolbar) { - super.setUpToolbar(toolbar); - setStatusBarColor(R.color.colorPrimary, true); - getSupportActionBar().setTitle("注册"); - } - - @Override - protected void initWidget() { - super.initWidget(); - mHandler.sendMessage(mHandler.obtainMessage(1)); - etUsername.requestFocus(); - etUsername.getEditText().addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable s) { - StringUtils.isNotChinese(s); - username = s.toString(); - if (username.length() < 6 || username.length() >14){ - mHandler.sendMessage(mHandler.obtainMessage(2, "用户名必须在6-14位之间")); - } else if(!username.substring(0, 1).matches("^[A-Za-z]$")){ - mHandler.sendMessage(mHandler.obtainMessage(2, - "用户名只能以字母开头")); - }else if(!username.matches("^[A-Za-z0-9-_]+$")){ - mHandler.sendMessage(mHandler.obtainMessage(2, - "用户名只能由数字、字母、下划线、减号组成")); - }else { - mHandler.sendMessage(mHandler.obtainMessage(3)); - } - checkNotNone(); - } - }); - - etPassword.getEditText().addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable s) { - password = s.toString(); - if (password.length() < 8 || password.length() > 16){ - mHandler.sendMessage(mHandler.obtainMessage(2, "密码必须在8-16位之间")); - } else if(password.matches("^\\d+$")){ - mHandler.sendMessage(mHandler.obtainMessage(2, "密码不能是纯数字")); - } else { - mHandler.sendMessage(mHandler.obtainMessage(3)); - } - checkNotNone(); - } - }); - - etRpPassword.getEditText().addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable s) { - rpPassword = s.toString(); - if (!rpPassword.equals(password)){ - mHandler.sendMessage(mHandler.obtainMessage(2, "两次输入的密码不一致")); - } else { - mHandler.sendMessage(mHandler.obtainMessage(3)); - } - checkNotNone(); - } - }); - - etCaptcha.getEditText().addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable s) { - inputCode = s.toString().trim().toLowerCase(); - if (!inputCode.equals(code.toLowerCase())){ - mHandler.sendMessage(mHandler.obtainMessage(2, "验证码错误")); - } else { - mHandler.sendMessage(mHandler.obtainMessage(3)); - } - checkNotNone(); - } - }); - - tvAgreement.setMovementMethod(LinkMovementMethod.getInstance()); - - } - - @Override - protected void initClick() { - super.initClick(); - ivCaptcha.setOnClickListener(v -> mHandler.sendMessage(mHandler.obtainMessage(1))); - - btRegister.setOnClickListener(v -> { - if (!username.matches("^[A-Za-z][A-Za-z0-9]{5,13}$")){ - DialogCreator.createTipDialog(this, "用户名格式错误", - "用户名必须在6-14位之间\n用户名只能以字母开头\n用户名只能由数字、字母、下划线、减号组成"); - }else if(password.matches("^\\d+$") || !password.matches("^.{8,16}$")){ - DialogCreator.createTipDialog(this, "密码格式错误", - "密码必须在8-16位之间\n密码不能是纯数字"); - }else if(!password.equals(rpPassword)){ - DialogCreator.createTipDialog(this, "重复密码错误", - "两次输入的密码不一致"); - }else if(!inputCode.trim().toLowerCase().equals(code.toLowerCase())){ - DialogCreator.createTipDialog(this, "验证码错误"); - }else if(!cbAgreement.isChecked()){ - DialogCreator.createTipDialog(this, "请勾选同意《用户服务协议》"); - }else { - ProgressDialog dialog = DialogCreator.createProgressDialog(this, null, "正在注册..."); - Map userRegisterInfo = new HashMap<>(); - userRegisterInfo.put("username", username); - userRegisterInfo.put("password", password); - UserService.register(userRegisterInfo, new ResultCallback() { - @Override - public void onFinish(Object o, int code) { - String[] info = ((String) o).split(":"); - int result = Integer.parseInt(info[0].trim()); - if (result == 101){ - UserService.writeUsername(username); - ToastUtils.showSuccess(info[1]); - finish(); - }else { - ToastUtils.showWarring(info[1]); - } - dialog.dismiss(); - } - @Override - public void onError(Exception e) { - ToastUtils.showError("注册失败:\n" + e.getLocalizedMessage()); - dialog.dismiss(); - } - }); - } - mHandler.sendMessage(mHandler.obtainMessage(1)); - }); - - } - - public void createCaptcha() { - code = CodeUtil.getInstance().createCode(); - Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code); - ivCaptcha.setImageBitmap(codeBitmap); - } - - public void showTip(String tip) { - tvRegisterTip.setVisibility(View.VISIBLE); - tvRegisterTip.setText(tip); - } - - public void checkNotNone(){ - if ("".equals(username) || "".equals(password) || "".equals(rpPassword) || "".equals(inputCode)){ - btRegister.setEnabled(false); - }else { - btRegister.setEnabled(true); - } - } - -} 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 f0de8e5..603a760 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 @@ -22,7 +22,7 @@ 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.base.BaseActivity; import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.model.SearchEngine; @@ -44,14 +44,13 @@ 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 * @date 2020/9/18 21:58 */ -public class SearchBookActivity extends BaseActivity2 { +public class SearchBookActivity extends BaseActivity { @BindView(R.id.et_search_key) EditText etSearchKey; @BindView(R.id.tv_search_conform) diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/WebDavSettingActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/WebDavSettingActivity.java index fa4ebb8..ec0e659 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/WebDavSettingActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/WebDavSettingActivity.java @@ -2,8 +2,11 @@ package xyz.fycz.myreader.ui.activity; import android.os.Bundle; import android.text.InputType; +import android.view.Menu; +import android.view.MenuItem; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.appcompat.widget.Toolbar; import butterknife.BindView; import io.reactivex.Single; @@ -11,11 +14,12 @@ import io.reactivex.SingleOnSubscribe; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; import xyz.fycz.myreader.R; -import xyz.fycz.myreader.base.BaseActivity2; +import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.base.observer.MySingleObserver; import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.model.storage.BackupRestoreUi; import xyz.fycz.myreader.model.storage.WebDavHelp; +import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.ui.dialog.MyAlertDialog; import xyz.fycz.myreader.util.SharedPreUtils; import xyz.fycz.myreader.util.StringHelper; @@ -27,7 +31,7 @@ import java.util.ArrayList; * @author fengyue * @date 2020/10/4 20:44 */ -public class WebDavSettingActivity extends BaseActivity2 { +public class WebDavSettingActivity extends BaseActivity { @BindView(R.id.webdav_setting_webdav_url) LinearLayout llWebdavUrl; @BindView(R.id.tv_webdav_url) @@ -128,4 +132,20 @@ public class WebDavSettingActivity extends BaseActivity2 { }); }); } + + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.webdav_help, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if (item.getItemId() == R.id.action_tip){ + DialogCreator.createAssetTipDialog(this, "如何使用WebDav进行云备份?", "webdavhelp.fy"); + } + return super.onOptionsItemSelected(item); + } } 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 eaeece1..0e47e0a 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 @@ -10,21 +10,17 @@ import android.widget.TextView; import androidx.appcompat.app.AlertDialog; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.resource.bitmap.RoundedCorners; -import com.bumptech.glide.request.RequestOptions; - import java.io.IOException; 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.ui.activity.ReadActivity; 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; import xyz.fycz.myreader.ui.presenter.BookcasePresenter; import xyz.fycz.myreader.util.StringHelper; import xyz.fycz.myreader.util.ToastUtils; 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 85051d9..225cbb6 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 @@ -8,21 +8,17 @@ import android.view.ViewGroup; import androidx.appcompat.app.AlertDialog; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.resource.bitmap.RoundedCorners; -import com.bumptech.glide.request.RequestOptions; - import java.io.IOException; 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.ui.activity.ReadActivity; 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; import xyz.fycz.myreader.ui.presenter.BookcasePresenter; import xyz.fycz.myreader.util.StringHelper; import xyz.fycz.myreader.util.ToastUtils; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/dialog/CopyContentDialog.java b/app/src/main/java/xyz/fycz/myreader/ui/dialog/CopyContentDialog.java new file mode 100644 index 0000000..d1f0299 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/ui/dialog/CopyContentDialog.java @@ -0,0 +1,62 @@ +package xyz.fycz.myreader.ui.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; +import androidx.annotation.NonNull; +import butterknife.BindView; +import butterknife.ButterKnife; +import xyz.fycz.myreader.R; + +/** + * Created by Zhouas666 on 2019-04-14 + * Github: https://github.com/zas023 + *

+ * 自由复制dialog + */ + +public class CopyContentDialog extends Dialog { + + private static final String TAG = "CopyContentDialog"; + + @BindView(R.id.dialog_tv_content) + TextView dialogTvContent; + + private String content; + + /***************************************************************************/ + + public CopyContentDialog(@NonNull Context context, String content) { + super(context); + this.content = content; + } + + /*****************************Initialization********************************/ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_copy_content); + ButterKnife.bind(this); + + setUpWindow(); + + dialogTvContent.setText(content); + } + + /** + * 设置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); + } + +} diff --git a/app/src/main/java/xyz/fycz/myreader/ui/dialog/DialogCreator.java b/app/src/main/java/xyz/fycz/myreader/ui/dialog/DialogCreator.java index efab472..5b00cc6 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/dialog/DialogCreator.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/dialog/DialogCreator.java @@ -1,5 +1,6 @@ package xyz.fycz.myreader.ui.dialog; +import android.annotation.SuppressLint; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; @@ -72,9 +73,11 @@ public class DialogCreator { dialog.setContentView(view); dialog.setCancelable(true); dialog.setCanceledOnTouchOutside(true); + //触摸外部关闭 view.findViewById(R.id.ll_bottom_view).setOnClickListener(null); view.setOnTouchListener(new View.OnTouchListener() { + @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouch(View view, MotionEvent motionEvent) { dialog.dismiss(); @@ -84,7 +87,7 @@ public class DialogCreator { //设置全屏 Window window = dialog.getWindow(); window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - + window.setWindowAnimations(R.style.dialogWindowAnim); //阅读背景风格 final ImageView ivCommonStyle = (ImageView) view.findViewById(R.id.iv_common_style); final ImageView ivLeatherStyle = (ImageView) view.findViewById(R.id.iv_leather_style); @@ -306,168 +309,6 @@ public class DialogCreator { } } - - /** - * 阅读设置对话框 - * - * @param context - * @param isDayStyle - * @param chapterProgress - * @param backListener - * @param lastChapterListener - * @param nextChapterListener - * @param chapterListListener - * @param onClickNightAndDayListener - * @param settingListener - * @return - */ - public static Dialog createReadSetting(final Context context, final boolean isDayStyle, int chapterProgress, int maxProcess, final Book mBook, Chapter mChapter, - View.OnClickListener backListener, - View.OnClickListener changeSourceListener, - View.OnClickListener refreshListener, - View.OnClickListener bookMarkListener, - final OnSkipChapterListener lastChapterListener, - final OnSkipChapterListener nextChapterListener, - View.OnClickListener chapterListListener, - final OnClickNightAndDayListener onClickNightAndDayListener, - View.OnClickListener settingListener, - SeekBar.OnSeekBarChangeListener onSeekBarChangeListener, - View.OnClickListener voiceOnClickListener, - final OnClickDownloadAllChapterListener onClickDownloadAllChapterListener) { - final Dialog dialog = new Dialog(context, R.style.jmui_default_dialog_style); - final View view = LayoutInflater.from(context).inflate(R.layout.dialog_read_setting, null); - dialog.setContentView(view); - - LinearLayout llBack = (LinearLayout) view.findViewById(R.id.ll_title_back); - LinearLayout llBook = view.findViewById(R.id.ll_book_name); - TextView tvBookName = view.findViewById(R.id.tv_book_name_top); - ImageView ivChangeSource = view.findViewById(R.id.iv_change_source); - ImageView ivRefresh = view.findViewById(R.id.iv_refresh); - ImageView ivBookMark = view.findViewById(R.id.iv_book_mark); - ImageView ivMore = view.findViewById(R.id.iv_more); - LinearLayout llChapter = view.findViewById(R.id.ll_chapter_view); - final TextView tvChapterTitle = view.findViewById(R.id.tv_chapter_title_top); - final TextView tvChapterUrl = view.findViewById(R.id.tv_chapter_url); - TextView tvLastChapter = (TextView) view.findViewById(R.id.tv_last_chapter); - TextView tvNextChapter = (TextView) view.findViewById(R.id.tv_next_chapter); - final SeekBar sbChapterProgress = (SeekBar) view.findViewById(R.id.sb_read_chapter_progress); - LinearLayout llChapterList = (LinearLayout) view.findViewById(R.id.ll_chapter_list); - LinearLayout llNightAndDay = (LinearLayout) view.findViewById(R.id.ll_night_and_day); - LinearLayout llSetting = (LinearLayout) view.findViewById(R.id.ll_setting); - final ImageView ivNightAndDay = (ImageView) view.findViewById(R.id.iv_night_and_day); - final TextView tvNightAndDay = (TextView) view.findViewById(R.id.tv_night_and_day); - ImageView ivVoice = (ImageView)view.findViewById(R.id.iv_voice_read); - - view.findViewById(R.id.rl_title_view).setOnClickListener(null); - view.findViewById(R.id.ll_bottom_view).setOnClickListener(null); - - Window window = dialog.getWindow(); - window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); - if (Build.VERSION.SDK_INT >= 21) { - window.setStatusBarColor(dialog.getContext().getColor(R.color.sys_dialog_setting_bg)); - } - - view.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View view, MotionEvent motionEvent) { - dialog.dismiss(); - return false; - } - }); - - tvBookName.setText(mBook.getName()); - llBook.setOnClickListener(v -> { - /*Intent intent = new Intent(context, BookDetailedActivity.class); - intent.putExtra(APPCONST.BOOK, mBook); - context.startActivity(intent);*/ - }); - if ("本地书籍".equals(mBook.getType())){ - ivChangeSource.setVisibility(View.GONE); - } - //换源 - ivChangeSource.setOnClickListener(changeSourceListener); - - //刷新 - ivRefresh.setOnClickListener(refreshListener); - String url = mChapter.getUrl(); - if ("null".equals(mBook.getSource()) || BookSource.fynovel.equals(mBook.getSource())) { - if (!url.contains("novel.fycz.xyz")) { - url = URLCONST.nameSpace_FY + url; - } - } - - //书签 - ivBookMark.setOnClickListener(bookMarkListener); - - tvChapterTitle.setText(mChapter.getTitle()); - tvChapterUrl.setText(StringHelper.isEmpty(url) ? mChapter.getId() : url); - //跳转对应章节 - llChapter.setOnClickListener(v -> { - String url1 = tvChapterUrl.getText().toString(); - if (!"本地书籍".equals(mBook.getType()) && !StringHelper.isEmpty(url1)) { - Intent intent = new Intent(Intent.ACTION_VIEW); - Uri uri = Uri.parse(url1); - intent.setData(uri); - context.startActivity(intent); - } - }); - - - if (!isDayStyle) { - ivNightAndDay.setImageResource(R.mipmap.z4); - tvNightAndDay.setText(context.getString(R.string.day)); - } - - llBack.setOnClickListener(backListener); - tvLastChapter.setOnClickListener(v -> { - if (lastChapterListener != null){ - lastChapterListener.onClick(tvChapterTitle, tvChapterUrl, sbChapterProgress); - } - }); - tvNextChapter.setOnClickListener(v -> { - if (nextChapterListener != null){ - nextChapterListener.onClick(tvChapterTitle, tvChapterUrl, sbChapterProgress); - } - }); - sbChapterProgress.setProgress(chapterProgress); - sbChapterProgress.setMax(maxProcess); - llChapterList.setOnClickListener(chapterListListener); - llSetting.setOnClickListener(settingListener); - sbChapterProgress.setOnSeekBarChangeListener(onSeekBarChangeListener); - ivVoice.setOnClickListener(voiceOnClickListener); - //日夜切换 - llNightAndDay.setOnClickListener(view1 -> { - boolean isDay; - if (tvNightAndDay.getText().toString().equals(context.getString(R.string.day))) { - isDay = false; - ivNightAndDay.setImageResource(R.mipmap.ao); - tvNightAndDay.setText(context.getString(R.string.night)); - } else { - isDay = true; - ivNightAndDay.setImageResource(R.mipmap.z4); - tvNightAndDay.setText(context.getString(R.string.day)); - } - if (onClickNightAndDayListener != null) { - onClickNightAndDayListener.onClick(dialog, view, isDay); - } - }); - - //缓存章节 - final TextView tvDownloadProgress = view.findViewById(R.id.tv_download_progress); - LinearLayout llDonwloadCache = view.findViewById(R.id.ll_download_cache); - llDonwloadCache.setOnClickListener(v -> { - if (onClickDownloadAllChapterListener != null){ - onClickDownloadAllChapterListener.onClick(dialog,v,tvDownloadProgress); - } - }); - - dialog.setCancelable(true); - dialog.setCanceledOnTouchOutside(true); - return dialog; - } - - - /** * 创建一个普通对话框(包含确定、取消按键) * @@ -702,7 +543,7 @@ public class DialogCreator { * 从assets文件夹之中读取文件并显示提示框 * @param mContext * @param title - * @param assetName + * @param assetName 需要后缀名 */ public static void createAssetTipDialog(Context mContext, String title, String assetName){ BufferedReader br = null; 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 4404df8..a6ed8aa 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 @@ -8,65 +8,43 @@ import android.os.Message; import android.widget.RelativeLayout; import android.widget.TextView; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import butterknife.BindView; import xyz.fycz.myreader.R; import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.SysManager; -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.model.storage.Backup; import xyz.fycz.myreader.model.storage.Restore; -import xyz.fycz.myreader.ui.activity.MainActivity; 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; import xyz.fycz.myreader.ui.activity.AboutActivity; -import xyz.fycz.myreader.ui.activity.LoginActivity; import xyz.fycz.myreader.ui.activity.MoreSettingActivity; import xyz.fycz.myreader.util.SharedPreUtils; import xyz.fycz.myreader.util.ToastUtils; -import xyz.fycz.myreader.util.utils.NetworkUtils; -import xyz.fycz.myreader.webapi.callback.ResultCallback; -import java.io.File; -import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Date; - -import static android.app.Activity.RESULT_OK; /** * @author fengyue * @date 2020/9/13 13:20 */ public class MineFragment extends BaseFragment { - @BindView(R.id.mine_rl_user) - RelativeLayout mRlUser; - @BindView(R.id.tv_user) - TextView mTvUser; @BindView(R.id.mine_rl_backup) RelativeLayout mRlBackup; - @BindView(R.id.mine_rl_syn) - RelativeLayout mRlSyn; @BindView(R.id.mine_rl_setting) RelativeLayout mRlSetting; @BindView(R.id.mine_rl_theme_mode) RelativeLayout mRlThemeMode; @BindView(R.id.tv_theme_mode_select) TextView tvThemeModeSelect; - @BindView(R.id.mine_rl_feedback) - RelativeLayout mRlFeedback; @BindView(R.id.mine_rl_about) RelativeLayout mRlAbout; - private boolean isLogin; - private BackupAndRestore mBackupAndRestore; private Setting mSetting; private String[] webSynMenu; private String[] backupMenu; @@ -79,7 +57,7 @@ public class MineFragment extends BaseFragment { public void handleMessage(@NonNull Message msg) { switch (msg.what) { case 1: - mTvUser.setText("登录/注册"); + break; case 2: backup(); @@ -102,8 +80,6 @@ public class MineFragment extends BaseFragment { @Override protected void initData(Bundle savedInstanceState) { super.initData(savedInstanceState); - isLogin = UserService.isLogin(); - mBackupAndRestore = new BackupAndRestore(); mSetting = SysManager.getSetting(); webSynMenu = new String[]{ MyApplication.getmContext().getString(R.string.menu_backup_webBackup), @@ -121,35 +97,12 @@ public class MineFragment extends BaseFragment { @Override protected void initWidget(Bundle savedInstanceState) { super.initWidget(savedInstanceState); - if (isLogin) { - mTvUser.setText(UserService.readUsername()); - } tvThemeModeSelect.setText(themeModeArr[themeMode]); } @Override protected void initClick() { super.initClick(); - mRlUser.setOnClickListener(v -> { - if (isLogin) { - DialogCreator.createCommonDialog(getActivity(), "退出登录", "确定要退出登录吗?" - , true, (dialog, which) -> { - File file = MyApplication.getApplication().getFileStreamPath("userConfig.fy"); - if (file.delete()) { - ToastUtils.showSuccess("退出成功"); - isLogin = false; - mHandler.sendEmptyMessage(1); - Intent intent = new Intent(getActivity(), LoginActivity.class); - getActivity().startActivityForResult(intent, APPCONST.REQUEST_LOGIN); - } else { - ToastUtils.showError("退出失败(Error:file.delete())"); - } - }, (dialog, which) -> dialog.dismiss()); - } else { - Intent intent = new Intent(getActivity(), LoginActivity.class); - getActivity().startActivityForResult(intent, APPCONST.REQUEST_LOGIN); - } - }); mRlBackup.setOnClickListener(v -> { AlertDialog bookDialog = MyAlertDialog.build(getContext()) .setTitle(getContext().getResources().getString(R.string.menu_bookcase_backup)) @@ -168,46 +121,6 @@ public class MineFragment extends BaseFragment { .create(); bookDialog.show(); }); - mRlSyn.setOnClickListener(v -> { - if (!UserService.isLogin()) { - ToastUtils.showWarring("请先登录!"); - Intent loginIntent = new Intent(getActivity(), LoginActivity.class); - getActivity().startActivityForResult(loginIntent, APPCONST.REQUEST_LOGIN); - return; - } - if (mSetting.isAutoSyn()) { - webSynMenu[2] = MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) + "已开启"; - } else { - webSynMenu[2] = MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) + "已关闭"; - } - MyAlertDialog.build(getContext()) - .setTitle(getActivity().getString(R.string.menu_bookcase_syn)) - .setItems(webSynMenu, (dialog, which) -> { - switch (which) { - case 0: - synBookcaseToWeb(false); - break; - case 1: - webRestore(); - break; - case 2: - String tip = ""; - if (mSetting.isAutoSyn()) { - mSetting.setAutoSyn(false); - tip = "每日自动同步已关闭!"; - } else { - mSetting.setAutoSyn(true); - tip = "每日自动同步已开启!"; - } - SysManager.saveSetting(mSetting); - ToastUtils.showSuccess(tip); - break; - } - }) - .setNegativeButton(null, null) - .setPositiveButton(null, null) - .show(); - }); mRlSetting.setOnClickListener(v -> { Intent settingIntent = new Intent(getActivity(), MoreSettingActivity.class); startActivity(settingIntent); @@ -256,20 +169,6 @@ public class MineFragment extends BaseFragment { startActivity(aboutIntent); }); - mRlFeedback.setOnClickListener(v -> { - DialogCreator.createCommonDialog(getContext(), "问题反馈", "请加入QQ群(1085028304)反馈问题!", true, - "加入QQ群", "取消", (dialog, which) -> { - if (!MyApplication.joinQQGroup(getContext(), "8PIOnHFuH6A38hgxvD_Rp2Bu-Ke1ToBn")) { - ClipboardManager mClipboardManager = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE); - //数据 - ClipData mClipData = ClipData.newPlainText("Label", "1085028304"); - //把数据设置到剪切板上 - assert mClipboardManager != null; - mClipboardManager.setPrimaryClip(mClipData); - ToastUtils.showError("未安装手Q或安装的版本不支持!\n已复制QQ群号,您可自行前往QQ添加!"); - } - }, null); - }); } @Override @@ -342,112 +241,6 @@ public class MineFragment extends BaseFragment { }, (dialogInterface, i) -> dialogInterface.dismiss()); } - /** - * 同步书架 - */ - private void synBookcaseToWeb(boolean isAutoSyn) { - if (!NetworkUtils.isNetWorkAvailable()) { - if (!isAutoSyn) { - ToastUtils.showWarring("无网络连接!"); - } - return; - } - ArrayList mBooks = (ArrayList) BookService.getInstance().getAllBooks(); - if (mBooks.size() == 0) { - if (!isAutoSyn) { - ToastUtils.showWarring("当前书架无任何书籍,无法同步!"); - } - return; - } - Date nowTime = new Date(); - SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd"); - String nowTimeStr = sdf.format(nowTime); - SharedPreUtils spb = SharedPreUtils.getInstance(); - String synTime = spb.getString(getString(R.string.synTime)); - if (!nowTimeStr.equals(synTime) || !isAutoSyn) { - UserService.webBackup(new ResultCallback() { - @Override - public void onFinish(Object o, int code) { - if ((boolean) o) { - spb.putString(getString(R.string.synTime), nowTimeStr); - if (!isAutoSyn) { - DialogCreator.createTipDialog(getContext(), "成功将书架同步至网络!"); - } - } else { - if (!isAutoSyn) { - DialogCreator.createTipDialog(getContext(), "同步失败,请重试!"); - } - } - } - - @Override - public void onError(Exception e) { - if (!isAutoSyn) { - DialogCreator.createTipDialog(getContext(), "同步失败,请重试!\n" + e.getLocalizedMessage()); - } - } - }); - } - } - - /** - * 恢复 - */ - private void webRestore() { - if (!NetworkUtils.isNetWorkAvailable()) { - ToastUtils.showWarring("无网络连接!"); - return; - } - DialogCreator.createCommonDialog(getContext(), "确认同步吗?", "将书架从网络同步至本地会覆盖原有书架!", true, - (dialogInterface, i) -> { - dialogInterface.dismiss(); - MyApplication.getApplication().newThread(() -> { - /*if (UserService.webRestore()) { - mHandler.sendMessage(mHandler.obtainMessage(7)); -// DialogCreator.createTipDialog(mMainActivity, -// "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!");、 - mSetting = SysManager.getSetting(); - ToastUtils.showSuccess("成功将书架从网络同步至本地!"); - } else { - DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!"); - }*/ - UserService.webRestore(new ResultCallback() { - @Override - public void onFinish(Object o, int code) { - if ((boolean) o) { - mHandler.sendMessage(mHandler.obtainMessage(7)); -// DialogCreator.createTipDialog(mMainActivity, -// "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!");、 - mSetting = SysManager.getSetting(); - ToastUtils.showSuccess("成功将书架从网络同步至本地!"); - } else { - DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!"); - } - } - - @Override - public void onError(Exception e) { - DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!\n" + e.getLocalizedMessage()); - } - }); - }); - }, (dialogInterface, i) -> dialogInterface.dismiss()); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - if (resultCode == RESULT_OK) { - switch (requestCode) { - case APPCONST.REQUEST_LOGIN: - assert data != null; - isLogin = data.getBooleanExtra("isLogin", false); - if (isLogin) { - mTvUser.setText(UserService.readUsername()); - } - break; - } - } - } public boolean isRecreate() { return unbinder == null; 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 fb3ae2e..d7402b3 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 @@ -23,9 +23,7 @@ import android.widget.PopupMenu; import androidx.appcompat.app.AlertDialog; import androidx.core.app.ActivityCompat; -import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Date; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -41,8 +39,6 @@ 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.base.ReadCrawler; import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; @@ -83,7 +79,6 @@ public class BookcasePresenter implements BasePresenter { private Setting mSetting; private final List errorLoadingBooks = new ArrayList<>(); private int finishLoadBookCount = 0; - private final BackupAndRestore mBackupAndRestore; // private int notifyId = 11; private ExecutorService es = Executors.newFixedThreadPool(1);//更新/下载线程池 @@ -179,7 +174,6 @@ public class BookcasePresenter implements BasePresenter { mMainActivity = (MainActivity) (mBookcaseFragment.getActivity()); // mChapterService = new ChapterService(); mSetting = SysManager.getSetting(); - mBackupAndRestore = new BackupAndRestore(); } //启动 @@ -195,10 +189,6 @@ public class BookcasePresenter implements BasePresenter { getData(); - if (mSetting.isAutoSyn() && UserService.isLogin()) { - synBookcaseToWeb(true); - } - //是否启用下拉刷新(默认启用) if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { mBookcaseFragment.getSrlContent().setEnableRefresh(false); @@ -956,35 +946,6 @@ public class BookcasePresenter implements BasePresenter { } return; } - Date nowTime = new Date(); - SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd"); - String nowTimeStr = sdf.format(nowTime); - SharedPreUtils spb = SharedPreUtils.getInstance(); - String synTime = spb.getString(mMainActivity.getString(R.string.synTime)); - if (!nowTimeStr.equals(synTime) || !isAutoSyn) { - UserService.webBackup(new ResultCallback() { - @Override - public void onFinish(Object o, int code) { - if ((boolean) o){ - spb.putString(mMainActivity.getString(R.string.synTime), nowTimeStr); - if (!isAutoSyn) { - DialogCreator.createTipDialog(mMainActivity, "成功将书架同步至网络!"); - } - }else { - if (!isAutoSyn) { - DialogCreator.createTipDialog(mMainActivity, "同步失败,请重试!"); - } - } - } - - @Override - public void onError(Exception e) { - if (!isAutoSyn) { - DialogCreator.createTipDialog(mMainActivity, "同步失败,请重试!\n" + e.getLocalizedMessage()); - } - } - }); - } } /*****************************************用于返回按钮判断*************************************/ 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 deleted file mode 100644 index 10873dc..0000000 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/ReadPresenter.java +++ /dev/null @@ -1,1314 +0,0 @@ -package xyz.fycz.myreader.ui.presenter; - -import android.annotation.SuppressLint; -import android.app.Dialog; -import android.app.Notification; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentFilter; -import android.graphics.BitmapFactory; -import android.net.Uri; -import android.os.Handler; -import android.os.Message; -import android.view.View; -import android.view.WindowManager; -import android.widget.SeekBar; -import android.widget.TextView; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -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.webapi.callback.ResultCallback; -import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.common.URLCONST; -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.base.ReadCrawler; -import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; -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; -import xyz.fycz.myreader.enums.ReadStyle; -import xyz.fycz.myreader.greendao.entity.Book; -import xyz.fycz.myreader.greendao.entity.BookMark; -import xyz.fycz.myreader.greendao.entity.Chapter; -import xyz.fycz.myreader.greendao.service.BookMarkService; -import xyz.fycz.myreader.greendao.service.BookService; -import xyz.fycz.myreader.greendao.service.ChapterService; -import xyz.fycz.myreader.util.notification.NotificationClickReceiver; -import xyz.fycz.myreader.util.notification.NotificationUtil; -import xyz.fycz.myreader.util.utils.NetworkUtils; -import xyz.fycz.myreader.webapi.CommonApi; -import xyz.fycz.myreader.widget.page.LocalPageLoader; -import xyz.fycz.myreader.widget.page.PageLoader; -import xyz.fycz.myreader.widget.page.PageMode; -import xyz.fycz.myreader.widget.page.PageView; - -import static androidx.appcompat.app.AppCompatActivity.RESULT_OK; -import static xyz.fycz.myreader.util.UriFileUtil.getPath; - - -public class ReadPresenter implements BasePresenter { - - - private ReadActivity mReadActivity; - private Book mBook; - private ArrayList mChapters = new ArrayList<>(); - private ChapterService mChapterService; - private BookService mBookService; - private BookMarkService mBookMarkService; - private NotificationUtil notificationUtil; - private Setting mSetting; - - private boolean settingChange;//是否是设置改变 - - private boolean chapterChange;//章节是否改变 - - private boolean isCollected = true;//是否在书架中 - - private boolean isPrev;//是否向前翻页 - - private boolean autoPage = false;//是否自动翻页 - - private Dialog mSettingDialog;//设置视图 - private Dialog mSettingDetailDialog;//详细设置视图 - private Dialog mPageModeDialog;//翻页模式实体 - - private int curCacheChapterNum = 0;//缓存章节数 - - private int needCacheChapterNum;//需要缓存的章节 - - private PageLoader mPageLoader;//页面加载器 - - private int screenTimeOut;//息屏时间(单位:秒),dengy零表示常亮 - - private Runnable keepScreenRunnable;//息屏线程 - private Runnable autoPageRunnable;//自动翻页 - private Runnable upHpbNextPage;//更新自动翻页进度条 - private Runnable sendDownloadNotification; - private static boolean isStopDownload = true; - - private int tempCacheChapterNum; - private int tempCount; - private String downloadingChapter; - - private ReadCrawler mReadCrawler; - - private int endPageTipCount = 3; - - private int nextPageTime;//下次翻页时间 - - private int upHpbInterval = 30;//更新翻页进度速度 - - private int downloadInterval = 150; - - private final CharSequence[] pageMode = { - "覆盖", "仿真", "滑动", "滚动", "无动画" - }; - - private SourceExchangeDialog mSourceDialog; - - private boolean hasChangeSource; - - @SuppressLint("HandlerLeak") - private Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case 1: - init(); - break; - case 2: - int chapterPos = msg.arg1; - int pagePos = msg.arg2; - mPageLoader.skipToChapter(chapterPos); - mPageLoader.skipToPage(pagePos); - mReadActivity.getPbLoading().setVisibility(View.GONE); - break; - case 3: - updateDownloadProgress((TextView) msg.obj); - break; - case 4: - saveLastChapterReadPosition(); - screenOffTimerStart(); - break; - case 5: - if (endPageTipCount > 0) { - endPageTipCount--; - mHandler.sendEmptyMessageDelayed(5, 1000); - } else { - mReadActivity.getTvEndPageTip().setVisibility(View.GONE); - endPageTipCount = 3; - } - break; - case 6: - mPageLoader.openChapter(); - if (isPrev) {//判断是否向前翻页打开章节,如果是则打开自己后跳转到最后一页,否则不跳转 - try {//概率性异常(空指针异常) - mPageLoader.skipToPage(mPageLoader.getAllPagePos() - 1); - } catch (Exception e) { - e.printStackTrace(); - } - } - break; - case 7: - ToastUtils.showWarring("无网络连接!"); - mPageLoader.chapterError(); - break; - case 8: - mReadActivity.getPbLoading().setVisibility(View.GONE); - break; - case 9: - ToastUtils.showInfo("正在后台缓存书籍,具体进度可查看通知栏!"); - notificationUtil.requestNotificationPermissionDialog(mReadActivity); - break; - case 10: - if (mPageLoader != null) { - mPageLoader.chapterError(); - } - } - } - }; - - // 接收电池信息和时间更新的广播 - private BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { - int level = intent.getIntExtra("level", 0); - try { - mPageLoader.updateBattery(level); - } catch (Exception e) { - e.printStackTrace(); - } - } - // 监听分钟的变化 - else if (Intent.ACTION_TIME_TICK.equals(intent.getAction())) { - try { - mPageLoader.updateTime(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - }; - - - public ReadPresenter(ReadActivity readActivity) { - mReadActivity = readActivity; - mBookService = BookService.getInstance(); - mChapterService = ChapterService.getInstance(); - mBookMarkService = BookMarkService.getInstance(); - mSetting = SysManager.getSetting(); - } - - - @Override - public void start() { - if (SharedPreUtils.getInstance().getBoolean(mReadActivity.getString(R.string.isNightFS), false)) { - mSetting.setDayStyle(!ColorUtil.isColorLight(mReadActivity.getColor(R.color.textPrimary))); - } - - //息屏时间 - screenTimeOut = mSetting.getResetScreen() * 60; - - //保持屏幕常亮 - keepScreenRunnable = this::unKeepScreenOn; - - autoPageRunnable = this::nextPage; - - upHpbNextPage = this::upHpbNextPage; - - sendDownloadNotification = this::sendNotification; - - notificationUtil = NotificationUtil.getInstance(); - - //注册广播 - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); - intentFilter.addAction(Intent.ACTION_TIME_TICK); - mReadActivity.registerReceiver(mReceiver, intentFilter); - - if (!mSetting.isBrightFollowSystem()) { - BrightUtil.setBrightness(mReadActivity, BrightUtil.progressToBright(mSetting.getBrightProgress())); - } - - 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(mReadActivity.getString(R.string.lastRead), mBook.getId()); - } - - - mReadCrawler = ReadCrawlerUtil.getReadCrawler(mBook.getSource()); - - mPageLoader = mReadActivity.getSrlContent().getPageLoader(mBook, mReadCrawler, mSetting); - - 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、从快捷图标打开上次阅读书籍 - * - * @return 是否加载成功 - */ - private boolean loadBook() { - //是否直接打开本地txt文件 - String path = null; - if (Intent.ACTION_VIEW.equals(mReadActivity.getIntent().getAction())) { - Uri uri = mReadActivity.getIntent().getData(); - if (uri != null) { - path = getPath(mReadActivity, uri); - } - } - if (!StringHelper.isEmpty(path)) { - //本地txt文件路径不为空,添加书籍 - addLocalBook(path); - } else { - //路径为空,说明不是直接打开txt文件 - mBook = (Book) mReadActivity.getIntent().getSerializableExtra(APPCONST.BOOK); - //mBook为空,说明是从快捷方式启动 - if (mBook == null) { - String bookId = SharedPreUtils.getInstance().getString(mReadActivity.getString(R.string.lastRead), ""); - if ("".equals(bookId)) {//没有上次阅读信息 - ToastUtils.showWarring("当前没有阅读任何书籍,无法加载上次阅读书籍!"); - mReadActivity.finish(); - return false; - } else {//有信息 - mBook = mBookService.getBookById(bookId); - if (mBook == null) {//上次阅读的书籍不存在 - ToastUtils.showWarring("上次阅读书籍已不存在/移除书架,无法加载!"); - mReadActivity.finish(); - return false; - }//存在就继续执行 - } - } - } - return true; - } - - /** - * 保存最后阅读章节的进度 - */ - public void saveLastChapterReadPosition() { - if (!StringHelper.isEmpty(mBook.getId()) && mPageLoader.getPageStatus() == PageLoader.STATUS_FINISH) { - mBook.setLastReadPosition(mPageLoader.getPagePos()); - mBook.setHisttoryChapterNum(mPageLoader.getChapterPos()); - mBookService.updateEntity(mBook); - } - } - - /** - * 创建设置视图 - */ - private void createSettingView() { - mSettingDialog = DialogCreator.createReadSetting(mReadActivity, mSetting.isDayStyle(), - mPageLoader.getPagePos(), Math.max(0, mPageLoader.getAllPagePos() - 1), - mBook, mChapters.get(mPageLoader.getChapterPos()), - view -> {//返回 - mSettingDialog.dismiss(); - mReadActivity.onBackPressed(); - }, v -> {//换源 - mSourceDialog.show(); - }, v -> {//刷新 - isPrev = false; - if (!"本地书籍".equals(mBook.getType())) { - mChapterService.deleteChapterCacheFile(mChapters.get(mPageLoader.getChapterPos())); - } - mPageLoader.refreshChapter(mChapters.get(mPageLoader.getChapterPos())); - }, v -> {//添加书签 - Chapter curChapter = mChapters.get(mPageLoader.getChapterPos()); - BookMark bookMark = new BookMark(); - bookMark.setBookId(mBook.getId()); - bookMark.setTitle(curChapter.getTitle()); - bookMark.setBookMarkChapterNum(mPageLoader.getChapterPos()); - bookMark.setBookMarkReadPosition(mPageLoader.getPagePos()); - mBookMarkService.addOrUpdateBookMark(bookMark); - DialogCreator.createTipDialog(mReadActivity, "《" + mBook.getName() + - "》:" + bookMark.getTitle() + "[" + (bookMark.getBookMarkReadPosition() + 1) + - "]\n书签添加成功,书签列表可在目录界面查看!"); - }, (chapterTitle, chapterUrl, sbReadChapterProgress) -> {//上一章 - isPrev = false; - mPageLoader.skipPreChapter(); - String url = mChapters.get(mPageLoader.getChapterPos()).getUrl(); - if ("null".equals(mBook.getSource()) || BookSource.fynovel.equals(mBook.getSource())) { - if (!url.contains("novel.fycz.xyz")) { - url = URLCONST.nameSpace_FY + url; - } - } - chapterTitle.setText(mChapters.get(mPageLoader.getChapterPos()).getTitle()); - chapterUrl.setText(StringHelper.isEmpty(url) ? mChapters. - get(mPageLoader.getChapterPos()).getId() : url); - sbReadChapterProgress.setProgress(0); - sbReadChapterProgress.setMax(Math.max(0, mPageLoader.getAllPagePos() - 1)); - chapterChange = false; - }, (chapterTitle, chapterUrl, sbReadChapterProgress) -> {//下一章 - isPrev = false; - mPageLoader.skipNextChapter(); - String url = mChapters.get(mPageLoader.getChapterPos()).getUrl(); - if ("null".equals(mBook.getSource()) || BookSource.fynovel.equals(mBook.getSource())) { - if (!url.contains("novel.fycz.xyz")) { - url = URLCONST.nameSpace_FY + url; - } - } - chapterTitle.setText(mChapters.get(mPageLoader.getChapterPos()).getTitle()); - chapterUrl.setText(StringHelper.isEmpty(url) ? mChapters. - get(mPageLoader.getChapterPos()).getId() : url); - sbReadChapterProgress.setProgress(0); - sbReadChapterProgress.setMax(Math.max(0, mPageLoader.getAllPagePos() - 1)); - chapterChange = false; - }, view -> {//目录 - /*initChapterTitleList(); - mReadActivity.getDlReadActivity().openDrawer(GravityCompat.START);*/ - mSettingDialog.dismiss(); - Intent intent = new Intent(mReadActivity, CatalogActivity.class); - intent.putExtra(APPCONST.BOOK, mBook); - mReadActivity.startActivityForResult(intent, APPCONST.REQUEST_CHAPTER_PAGE); - }, (dialog, view, isDayStyle) -> {//日夜切换 - dialog.dismiss(); - changeNightAndDaySetting(isDayStyle); - }, view -> {//设置 - showSettingDetailView(); - }, new SeekBar.OnSeekBarChangeListener() {//阅读进度 - @Override - public void onProgressChanged(SeekBar seekBar, int i, boolean b) { - - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - //进行切换 - int pagePos = seekBar.getProgress(); - if (pagePos != mPageLoader.getPagePos() && pagePos < mPageLoader.getAllPagePos()) { - mPageLoader.skipToPage(pagePos); - } - } - } - , null, (dialog, view, tvDownloadProgress) -> { - if (!isCollected) { - addBookToCaseAndDownload(tvDownloadProgress); - } else { - downloadBook(tvDownloadProgress); - } - - }); - } - - /** - * 显示设置视图 - */ - private void showSettingView() { - if (mSettingDialog != null && !chapterChange) { - mSettingDialog.show(); - } else { - if (mPageLoader.getPageStatus() == PageLoader.STATUS_FINISH) { - createSettingView(); - chapterChange = false; - } - mSettingDialog.show(); - } - - } - - /** - * 添加到书架并缓存书籍 - * - * @param tvDownloadProgress - */ - private void addBookToCaseAndDownload(final TextView tvDownloadProgress) { - DialogCreator.createCommonDialog(mReadActivity, mReadActivity.getString(R.string.tip), mReadActivity.getString(R.string.download_no_add_tips), true, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - downloadBook(tvDownloadProgress); - isCollected = true; - } - }, (dialog, which) -> dialog.dismiss()); - } - - /** - * 创建详细设置视图 - */ - private void createSettingDetailView() { - mSettingDetailDialog = DialogCreator.createReadDetailSetting(mReadActivity, mSetting, - this::changeStyle, v -> reduceTextSize(), v -> increaseTextSize(), v -> { - if (mSetting.isVolumeTurnPage()) { - mSetting.setVolumeTurnPage(false); - ToastUtils.showSuccess("音量键翻页已关闭!"); - } else { - mSetting.setVolumeTurnPage(true); - ToastUtils.showSuccess("音量键翻页已开启!"); - } - SysManager.saveSetting(mSetting); - }, v -> { - Intent intent = new Intent(mReadActivity, FontsActivity.class); - mReadActivity.startActivityForResult(intent, APPCONST.REQUEST_FONT); - mSettingDetailDialog.dismiss(); - }, this::showPageModeDialog, v -> { - if (mSetting.getPageMode() == PageMode.SCROLL) { - ToastUtils.showWarring("滚动暂时不支持自动翻页"); - return; - } - mSettingDetailDialog.dismiss(); - autoPage = !autoPage; - autoPage(); - }, v -> { - Intent intent = new Intent(mReadActivity, MoreSettingActivity.class); - mReadActivity.startActivityForResult(intent, APPCONST.REQUEST_RESET_SCREEN_TIME); - mSettingDetailDialog.dismiss(); - }); - } - - /** - * 显示详细设置视图 - */ - private void showSettingDetailView() { - mSettingDialog.dismiss(); - if (mSettingDetailDialog != null) { - mSettingDetailDialog.show(); - } else { - createSettingDetailView(); - mSettingDetailDialog.show(); - } - } - - private void showPageModeDialog(final TextView tvPageMode) { - if (mPageModeDialog != null) { - mPageModeDialog.show(); - } else { - //显示翻页模式视图 - int checkedItem; - switch (mSetting.getPageMode()) { - case COVER: - checkedItem = 0; - break; - case SIMULATION: - checkedItem = 1; - break; - case SLIDE: - checkedItem = 2; - break; - case SCROLL: - checkedItem = 3; - break; - case NONE: - checkedItem = 4; - break; - default: - checkedItem = 0; - } - mPageModeDialog = MyAlertDialog.build(mReadActivity) - .setTitle("翻页模式") - .setSingleChoiceItems(pageMode, checkedItem, (dialog, which) -> { - switch (which) { - case 0: - mSetting.setPageMode(PageMode.COVER); - break; - case 1: - mSetting.setPageMode(PageMode.SIMULATION); - break; - case 2: - mSetting.setPageMode(PageMode.SLIDE); - break; - case 3: - mSetting.setPageMode(PageMode.SCROLL); - break; - case 4: - mSetting.setPageMode(PageMode.NONE); - break; - } - mPageModeDialog.dismiss(); - SysManager.saveSetting(mSetting); - MyApplication.runOnUiThread(() -> mPageLoader.setPageMode(mSetting.getPageMode())); - tvPageMode.setText(pageMode[which]); - }).show(); - } - } - - /** - * 字体结果回调 - * - * @param requestCode - * @param resultCode - * @param data - */ - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == RESULT_OK) { - switch (requestCode) { - case APPCONST.REQUEST_FONT: - Font font = (Font) data.getSerializableExtra(APPCONST.FONT); - mSetting.setFont(font); - settingChange = true; -// init(); - MyApplication.runOnUiThread(() -> mPageLoader.setFont(font)); - break; - case APPCONST.REQUEST_CHAPTER_PAGE: - int[] chapterAndPage = data.getIntArrayExtra(APPCONST.CHAPTER_PAGE); - assert chapterAndPage != null; - skipToChapterAndPage(chapterAndPage[0], chapterAndPage[1]); - break; - case APPCONST.REQUEST_RESET_SCREEN_TIME: - int resetScreen = data.getIntExtra(APPCONST.RESULT_RESET_SCREEN, 0); - screenTimeOut = resetScreen * 60; - screenOffTimerStart(); - break; - } - } - } - - - /** - * 初始化 - */ - private void init() { - screenOffTimerStart(); - mPageLoader.init(); - mPageLoader.refreshChapterList(); - mHandler.sendMessage(mHandler.obtainMessage(8)); - } - - /** - * 初始化监听器 - */ - private void initListener() { - - mReadActivity.getSrlContent().setTouchListener(new PageView.TouchListener() { - @Override - public boolean onTouch() { - screenOffTimerStart(); - return true; - } - - @Override - public void center() { - if (mPageLoader.getPageStatus() == PageLoader.STATUS_FINISH) { - showSettingView(); - } - if (autoPage) { - autoPageStop(); - } - } - - @Override - public void prePage() { - isPrev = true; - } - - @Override - public void nextPage(boolean hasNextPage) { - isPrev = false; - if (!hasNextPage && endPageTipCount == 3) { - mReadActivity.getTvEndPageTip().setVisibility(View.VISIBLE); - mHandler.sendMessage(mHandler.obtainMessage(5)); - if (autoPage) { - autoPageStop(); - } - } - } - - @Override - public void cancel() { - } - }); - - mPageLoader.setOnPageChangeListener( - new PageLoader.OnPageChangeListener() { - @Override - public void onChapterChange(int pos) { - chapterChange = true; - lastLoad(pos); - for (int i = 0; i < 5; i++) { - preLoad(pos - 1 + i); - } - mBook.setHistoryChapterId(mChapters.get(pos).getTitle()); - mHandler.sendMessage(mHandler.obtainMessage(4)); - MyApplication.getApplication().newThread(() -> { - if (mPageLoader.getPageStatus() == PageLoader.STATUS_LOADING) { - if (!NetworkUtils.isNetWorkAvailable()) { - mHandler.sendMessage(mHandler.obtainMessage(7)); - } else { - mHandler.sendMessage(mHandler.obtainMessage(6)); - } - } - }); - - } - - @Override - public void requestChapters(List requestChapters) { - /*for (final Chapter chapter : requestChapters){ - getChapterContent(chapter, null); - }*/ - } - - @Override - public void onCategoryFinish(List chapters) { - } - - @Override - public void onPageCountChange(int count) { - - } - - @Override - public void onPageChange(int pos) { - mHandler.sendMessage(mHandler.obtainMessage(4)); - } - - @Override - public void preLoading() { - - } - } - ); - - } - - - /** - * 章节数据网络同步 - */ - private void getData() { - mChapters = (ArrayList) mChapterService.findBookAllChapterByBookId(mBook.getId()); - if (!isCollected || mChapters.size() == 0 || ("本地书籍".equals(mBook.getType()) && - !ChapterService.isChapterCached(mBook.getId(), mChapters.get(0).getTitle()))) { - if ("本地书籍".equals(mBook.getType())) { - if (!new File(mBook.getChapterUrl()).exists()) { - ToastUtils.showWarring("书籍缓存为空且源文件不存在,书籍加载失败!"); - mReadActivity.finish(); - return; - } - ((LocalPageLoader) mPageLoader).loadChapters(new ResultCallback() { - @Override - public void onFinish(Object o, int code) { - ArrayList chapters = (ArrayList) o; - mBook.setChapterTotalNum(chapters.size()); - mBook.setNewestChapterTitle(chapters.get(chapters.size() - 1).getTitle()); - mBookService.updateEntity(mBook); - if (mChapters.size() == 0) { - updateAllOldChapterData(chapters); - } - initChapters(); - mHandler.sendMessage(mHandler.obtainMessage(1)); - } - - @Override - public void onError(Exception e) { - mChapters.clear(); - initChapters(); - mHandler.sendMessage(mHandler.obtainMessage(1)); - } - }); - } else { - CommonApi.getBookChapters(mBook.getChapterUrl(), mReadCrawler,false, new ResultCallback() { - @Override - public void onFinish(Object o, int code) { - ArrayList chapters = (ArrayList) o; - updateAllOldChapterData(chapters); - initChapters(); - } - - @Override - public void onError(Exception e) { -// settingChange = true; - initChapters(); - mHandler.sendMessage(mHandler.obtainMessage(1)); - } - }); - } - } else { - initChapters(); - } - } - - /** - * 初始化章节 - */ - private void initChapters() { - mBook.setNoReadNum(0); - mBook.setChapterTotalNum(mChapters.size()); - if (!StringHelper.isEmpty(mBook.getId())) { - mBookService.updateEntity(mBook); - } - if (mChapters.size() == 0) { - ToastUtils.showWarring("该书查询不到任何章节"); - mHandler.sendMessage(mHandler.obtainMessage(8)); - settingChange = false; - } else { - if (mBook.getHisttoryChapterNum() < 0) { - mBook.setHisttoryChapterNum(0); - } else if (mBook.getHisttoryChapterNum() >= mChapters.size()) { - mBook.setHisttoryChapterNum(mChapters.size() - 1); - } - if ("本地书籍".equals(mBook.getType())) { - 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) { -// mChapters.get(mBook.getHisttoryChapterNum()).setContent((String) o); - mChapterService.saveOrUpdateChapter(mChapters.get(mBook.getHisttoryChapterNum()), (String) o); - mHandler.sendMessage(mHandler.obtainMessage(1)); -// getAllChapterData(); - } - - @Override - public void onError(Exception e) { - mHandler.sendMessage(mHandler.obtainMessage(1)); - } - }); - } - } - - /** - * 更新所有章节 - * - * @param newChapters - */ - private void updateAllOldChapterData(ArrayList newChapters) { - for (Chapter newChapter : newChapters) { - newChapter.setId(StringHelper.getStringRandom(25)); - newChapter.setBookId(mBook.getId()); - mChapters.add(newChapter); -// mChapterService.addChapter(newChapters.get(j)); - } - mChapterService.addChapters(mChapters); - } - - - /****************************************** 缓存章节***************************************************************/ - private int selectedIndex;//对话框选择下标 - - protected void downloadBook(final TextView tvDownloadProgress) { - if ("本地书籍".equals(mBook.getType())) { - ToastUtils.showWarring("《" + mBook.getName() + "》是本地书籍,不能缓存"); - return; - } - if (!NetworkUtils.isNetWorkAvailable()) { - ToastUtils.showWarring("无网络连接!"); - return; - } - MyApplication.runOnUiThread(() -> { - MyAlertDialog.build(mReadActivity) - .setTitle("缓存书籍") - .setSingleChoiceItems(APPCONST.DIALOG_DOWNLOAD, selectedIndex, (dialog, which) -> selectedIndex = which).setNegativeButton("取消", ((dialog, which) -> dialog.dismiss())).setPositiveButton("确定", - (dialog, which) -> { - switch (selectedIndex) { - case 0: - addDownload(tvDownloadProgress, mPageLoader.getChapterPos(), mPageLoader.getChapterPos() + 50); - break; - case 1: - addDownload(tvDownloadProgress, mPageLoader.getChapterPos() - 50, mPageLoader.getChapterPos() + 50); - break; - case 2: - addDownload(tvDownloadProgress, mPageLoader.getChapterPos(), mChapters.size()); - break; - case 3: - addDownload(tvDownloadProgress, 0, mChapters.size()); - break; - } - }).show(); - }); - } - - private void addDownload(final TextView tvDownloadProgress, int begin, int end) { - /*//取消之前下载 - if (!isStopDownload) { - isStopDownload = true; - try { - Thread.sleep(200); - } catch (InterruptedException e) { - e.printStackTrace(); - } - }*/ - if (SysManager.getSetting().getCatheGap() != 0) { - downloadInterval = SysManager.getSetting().getCatheGap(); - } - //计算断点章节 - final int finalBegin = Math.max(0, begin); - final int finalEnd = Math.min(end, mChapters.size()); - needCacheChapterNum = finalEnd - finalBegin; - curCacheChapterNum = 0; - isStopDownload = false; - ArrayList needDownloadChapters = new ArrayList<>(); - for (int i = finalBegin; i < finalEnd; i++) { - final Chapter chapter = mChapters.get(i); - if (StringHelper.isEmpty(chapter.getContent())) { - needDownloadChapters.add(chapter); - } - } - needCacheChapterNum = needDownloadChapters.size(); - if (needCacheChapterNum > 0) { - mHandler.sendEmptyMessage(9); - mHandler.postDelayed(sendDownloadNotification, 2 * downloadInterval); - } - MyApplication.getApplication().newThread(() -> { - for (Chapter chapter : needDownloadChapters) { - getChapterContent(chapter, new ResultCallback() { - @Override - public void onFinish(Object o, int code) { - downloadingChapter = chapter.getTitle(); - mChapterService.saveOrUpdateChapter(chapter, (String) o); - curCacheChapterNum++; - mHandler.sendMessage(mHandler.obtainMessage(3, tvDownloadProgress)); - } - - @Override - public void onError(Exception e) { - curCacheChapterNum++; - mHandler.sendMessage(mHandler.obtainMessage(3, tvDownloadProgress)); - } - }); - try { - Thread.sleep(downloadInterval); - } catch (InterruptedException e) { - e.printStackTrace(); - } - if (isStopDownload) { - break; - } - } - if (curCacheChapterNum == needCacheChapterNum) { - ToastUtils.showInfo("《" + mBook.getName() + "》" + mReadActivity.getString(R.string.download_already_all_tips)); - } - }); - } - - - private void updateDownloadProgress(TextView tvDownloadProgress) { - try { - tvDownloadProgress.setText(curCacheChapterNum * 100 / needCacheChapterNum + " %"); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * 发送通知 - */ - private void sendNotification() { - if (curCacheChapterNum == needCacheChapterNum) { - notificationUtil.cancel(1001); - return; - } else { - Notification notification = notificationUtil.build(APPCONST.channelIdDownload) - .setSmallIcon(R.drawable.ic_download) - //通知栏大图标 - .setLargeIcon(BitmapFactory.decodeResource(MyApplication.getApplication().getResources(), R.mipmap.ic_launcher)) - .setOngoing(true) - //点击通知后自动清除 - .setAutoCancel(true) - .setContentTitle("正在下载:" + mBook.getName() + - "[" + curCacheChapterNum + "/" + needCacheChapterNum + "]") - .setContentText(downloadingChapter == null ? " " : downloadingChapter) - .addAction(R.drawable.ic_stop_black_24dp, "停止", - notificationUtil.getChancelPendingIntent(cancelDownloadReceiver.class)) - .build(); - notificationUtil.notify(1001, notification); - } - if (tempCacheChapterNum < curCacheChapterNum) { - tempCount = 1500 / downloadInterval; - tempCacheChapterNum = curCacheChapterNum; - } else if (tempCacheChapterNum == curCacheChapterNum) { - tempCount--; - if (tempCount == 0) { - notificationUtil.cancel(1001); - return; - } - } - mHandler.postDelayed(sendDownloadNotification, 2 * downloadInterval); - } - - public static class cancelDownloadReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - //todo 跳转之前要处理的逻辑 - if (NotificationClickReceiver.CANCEL_ACTION.equals(intent.getAction())) { - isStopDownload = true; - } - } - } - - /** - * 获取章节内容 - * - * @param chapter - * @param resultCallback - */ - private void getChapterContent(final Chapter chapter, ResultCallback resultCallback) { - if (StringHelper.isEmpty(chapter.getBookId())) { - chapter.setId(mBook.getId()); - } - if (!StringHelper.isEmpty(chapter.getContent())) { - if (resultCallback != null) { - resultCallback.onFinish(mChapterService.getChapterCatheContent(chapter), 0); - } - } else { - if ("本地书籍".equals(mBook.getType())) { - return; - } - if (resultCallback != null) { - CommonApi.getChapterContent(chapter.getUrl(), mReadCrawler, resultCallback); - } else { - CommonApi.getChapterContent(chapter.getUrl(), mReadCrawler, new ResultCallback() { - @Override - public void onFinish(final Object o, int code) { -// chapter.setContent((String) o); - mChapterService.saveOrUpdateChapter(chapter, (String) o); - } - - @Override - public void onError(Exception e) { - - } - - }); - } - } - } - - - /** - * 白天夜间改变 - * - * @param isCurDayStyle - */ - private void changeNightAndDaySetting(boolean isCurDayStyle) { - mSetting.setDayStyle(!isCurDayStyle); - SysManager.saveSetting(mSetting); - MyApplication.getApplication().setNightTheme(isCurDayStyle); - settingChange = true; - //mPageLoader.setPageStyle(!isCurDayStyle); - } - - /** - * 缩小字体 - */ - private void reduceTextSize() { - if (mSetting.getReadWordSize() > 1) { - mSetting.setReadWordSize(mSetting.getReadWordSize() - 1); - SysManager.saveSetting(mSetting); - settingChange = true; - mPageLoader.setTextSize((int) mSetting.getReadWordSize()); - } - } - - /** - * 增大字体 - */ - private void increaseTextSize() { - if (mSetting.getReadWordSize() < 41) { - mSetting.setReadWordSize(mSetting.getReadWordSize() + 1); - SysManager.saveSetting(mSetting); - settingChange = true; - mPageLoader.setTextSize((int) mSetting.getReadWordSize()); - } - } - - /** - * 改变阅读风格 - * - * @param readStyle - */ - private void changeStyle(ReadStyle readStyle) { - settingChange = true; - mSetting.setReadStyle(readStyle); - SysManager.saveSetting(mSetting); - if (!mSetting.isDayStyle()) { - DialogCreator.createCommonDialog(mReadActivity, "提示", "是否希望切换为日间模式?", - false, "确定", "取消", (dialog, which) -> { - changeNightAndDaySetting(false); - }, null); - } - MyApplication.runOnUiThread(() -> mPageLoader.setPageStyle(true)); - } - - - /** - * 取消亮屏保持 - */ - private void unKeepScreenOn() { - keepScreenOn(false); - } - - /** - * @param keepScreenOn 是否保持亮屏 - */ - public void keepScreenOn(boolean keepScreenOn) { - if (keepScreenOn) { - mReadActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } else { - mReadActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } - } - - /** - * 重置黑屏时间 - */ - private void screenOffTimerStart() { - if (screenTimeOut <= 0) { - keepScreenOn(true); - return; - } - int screenOffTime = screenTimeOut * 1000 - ScreenHelper.getScreenOffTime(mReadActivity); - if (screenOffTime > 0) { - mHandler.removeCallbacks(keepScreenRunnable); - keepScreenOn(true); - mHandler.postDelayed(keepScreenRunnable, screenOffTime); - } else { - keepScreenOn(false); - } - } - - /** - * 预加载下一章 - */ - private void preLoad(int position) { - if (position + 1 < mChapters.size()) { - Chapter chapter = mChapters.get(position + 1); - if (StringHelper.isEmpty(chapter.getContent())) { - mPageLoader.getChapterContent(chapter); - } - } - } - - /** - * 预加载上一章 - * - * @param position - */ - private void lastLoad(int position) { - if (position > 0) { - Chapter chapter = mChapters.get(position - 1); - if (StringHelper.isEmpty(chapter.getContent())) { - mPageLoader.getChapterContent(chapter); - } - } - } - - /** - * 添加本地书籍 - * - * @param path - */ - private void addLocalBook(String path) { - File file = new File(path); - if (!file.exists()) { - return; - } - Book book = new Book(); - book.setName(file.getName().replace(".txt", "")); - book.setChapterUrl(path); - book.setType("本地书籍"); - book.setHistoryChapterId("未开始阅读"); - book.setNewestChapterTitle("未拆分章节"); - book.setAuthor("本地书籍"); - book.setSource(BookSource.local.toString()); - book.setDesc("无"); - book.setIsCloseUpdate(true); - //判断书籍是否已经添加 - Book existsBook = mBookService.findBookByAuthorAndName(book.getName(), book.getAuthor()); - if (book.equals(existsBook)) { - mBook = existsBook; - return; - } - - mBookService.addBook(book); - mBook = book; - } - - /** - * 跳转到指定章节的指定页面 - * - * @param chapterPos - * @param pagePos - */ - private void skipToChapterAndPage(final int chapterPos, final int pagePos) { - isPrev = false; - if (StringHelper.isEmpty(mChapters.get(chapterPos).getContent())) { - if ("本地书籍".equals(mBook.getType())) { - ToastUtils.showWarring("该章节无内容!"); - return; - } - mReadActivity.getPbLoading().setVisibility(View.VISIBLE); - CommonApi.getChapterContent(mChapters.get(chapterPos).getUrl(), mReadCrawler, new ResultCallback() { - @Override - public void onFinish(Object o, int code) { -// mChapters.get(position).setContent((String) o); - mChapterService.saveOrUpdateChapter(mChapters.get(chapterPos), (String) o); - mHandler.sendMessage(mHandler.obtainMessage(2, chapterPos, pagePos)); - } - - @Override - public void onError(Exception e) { - mHandler.sendMessage(mHandler.obtainMessage(2, chapterPos, pagePos)); - mHandler.sendEmptyMessage(10); - } - }); - } else { - mHandler.sendMessage(mHandler.obtainMessage(2, chapterPos, pagePos)); - } - } - - /** - * 自动翻页 - */ - private void autoPage() { - mHandler.removeCallbacks(upHpbNextPage); - mHandler.removeCallbacks(autoPageRunnable); - if (autoPage) { - mReadActivity.getPbNextPage().setVisibility(View.VISIBLE); - //每页按字数计算一次时间 - nextPageTime = mPageLoader.curPageLength() * 60 * 1000 / mSetting.getAutoScrollSpeed(); - if (0 == nextPageTime) nextPageTime = 1000; - mReadActivity.getPbNextPage().setMax(nextPageTime); - mHandler.postDelayed(autoPageRunnable, nextPageTime); - nextPageTime = nextPageTime - upHpbInterval * 10; - mHandler.postDelayed(upHpbNextPage, upHpbInterval); - } else { - mReadActivity.getPbNextPage().setVisibility(View.INVISIBLE); - } - } - - /** - * 更新自动翻页进度条 - */ - private void upHpbNextPage() { - nextPageTime = nextPageTime - upHpbInterval; - if (nextPageTime >= 0) { - mReadActivity.getPbNextPage().setProgress(nextPageTime); - } - mHandler.postDelayed(upHpbNextPage, upHpbInterval); - } - - /** - * 停止自动翻页 - */ - private void autoPageStop() { - autoPage = false; - autoPage(); - } - - /** - * 下一页 - */ - private void nextPage() { - MyApplication.runOnUiThread(() -> { - screenOffTimerStart(); - if (mPageLoader != null) { - mPageLoader.skipToNextPage(); - } - autoPage(); - }); - } - - - /** - * setter和getter方法 - */ - public boolean isCollected() { - return isCollected; - } - - public PageLoader getmPageLoader() { - return mPageLoader; - } - - public void setCollected(boolean collected) { - isCollected = collected; - } - - /** - * ReadActivity调用 - */ - public void deleteBook() { - mBookService.deleteBookById(mBook.getId()); - } - - /** - * ReadActivity调用 - */ - public void onDestroy() { - mReadActivity.unregisterReceiver(mReceiver); - mHandler.removeCallbacks(keepScreenRunnable); - mHandler.removeCallbacks(upHpbNextPage); - mHandler.removeCallbacks(autoPageRunnable); - /*mHandler.removeCallbacks(sendDownloadNotification); - notificationUtil.cancelAll(); - MyApplication.getApplication().shutdownThreadPool();*/ - if (autoPage) { - autoPageStop(); - } - for (int i = 0; i < 9; i++) { - mHandler.removeMessages(i + 1); - } - if (mPageLoader != null) { - mPageLoader.closeBook(); - mPageLoader = null; - } - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/AlarmHelper.java b/app/src/main/java/xyz/fycz/myreader/util/AlarmHelper.java deleted file mode 100644 index 7dfb5f5..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/AlarmHelper.java +++ /dev/null @@ -1,72 +0,0 @@ -package xyz.fycz.myreader.util; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.os.Build; - -import xyz.fycz.myreader.common.APPCONST; - -import java.util.Date; - -import static android.content.Context.ALARM_SERVICE; -import static android.content.Intent.FLAG_INCLUDE_STOPPED_PACKAGES; - - - -public class AlarmHelper { - - private static String alarmActicon = "xyz.fycz.kl.gxdw"; - private static String AntiHijackingActicon = "xyz.fycz.kl.gxdw.AntiHijacking"; - - public static void addOneShotAlarm(Context context, long time, String msg, int id){ - Date date = new Date(); - if(time <= date.getTime()){ - return; - } - Intent intent = new Intent(alarmActicon); - intent.putExtra(APPCONST.ALARM_SCHEDULE_MSG,msg); - intent.setFlags(FLAG_INCLUDE_STOPPED_PACKAGES); - PendingIntent pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_CANCEL_CURRENT); - AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - alarmManager.setExact(AlarmManager.RTC_WAKEUP,time,pi); - }else { - alarmManager.set(AlarmManager.RTC_WAKEUP,time,pi); - } - } - - public static void removeOneShotAlarm(Context context, int id){ - Intent intent = new Intent(alarmActicon); - intent.setFlags(FLAG_INCLUDE_STOPPED_PACKAGES); - PendingIntent pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_CANCEL_CURRENT); - AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE); - alarmManager.cancel(pi); - } - - public static void addAlarm(Context context, long time, int id){ -// Date date = new Date(); - /* if(time <= date.getTime()){ - return; - }*/ - Intent intent = new Intent(AntiHijackingActicon); - - intent.setFlags(FLAG_INCLUDE_STOPPED_PACKAGES); - PendingIntent pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_CANCEL_CURRENT); - AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - alarmManager.setExact(AlarmManager.RTC_WAKEUP,new Date().getTime() + time,pi); - }else { - alarmManager.set(AlarmManager.RTC_WAKEUP,new Date().getTime() + time,pi); - } - } - - public static void removeAlarm(Context context, int id){ - Intent intent = new Intent(AntiHijackingActicon); - intent.setFlags(FLAG_INCLUDE_STOPPED_PACKAGES); - PendingIntent pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_CANCEL_CURRENT); - AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE); - alarmManager.cancel(pi); - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/Anti_hijackingUtils.java b/app/src/main/java/xyz/fycz/myreader/util/Anti_hijackingUtils.java deleted file mode 100644 index 06ebdc3..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/Anti_hijackingUtils.java +++ /dev/null @@ -1,125 +0,0 @@ -package xyz.fycz.myreader.util; - -import android.widget.Toast; - -import androidx.appcompat.app.AppCompatActivity; - -import java.util.ArrayList; -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; - -import xyz.fycz.myreader.R; - -/** - * 防界面劫持提示 - */ -public class Anti_hijackingUtils { - -// private int id = 12345678;//记录定时ID - - private static boolean home; - private static boolean back; - - - /** - * 用于执行定时任务 - */ - private Timer timer = null; - - /** - * 用于保存当前任务 - */ - private List tasks = null; - - /** - * 唯一实例 - */ - private static Anti_hijackingUtils anti_hijackingUtils; - - private Anti_hijackingUtils() { - // 初始化 - tasks = new ArrayList(); - timer = new Timer(); - } - - /** - * 获取唯一实例 - * - * @return 唯一实例 - */ - public static Anti_hijackingUtils getinstance() { - if (anti_hijackingUtils == null) { - anti_hijackingUtils = new Anti_hijackingUtils(); - } - return anti_hijackingUtils; - } - - /** - * 在activity的onPause()方法中调用 - * - * @param activity - */ - public void onPause(final AppCompatActivity activity) { - MyTimerTask task = new MyTimerTask(activity); - tasks.add(task); - timer.schedule(task, 2000); -// AlarmHelper.addAlarm(activity,2000,id); - } - - /** - * 在activity的onResume()方法中调用 - */ - public void onResume(final AppCompatActivity activity) { - if (tasks.size() > 0) { - tasks.get(tasks.size() - 1).setCanRun(false); - tasks.remove(tasks.size() - 1); - } -// AlarmHelper.removeAlarm(activity,id); - } - - /** - * 自定义TimerTask类 - */ - class MyTimerTask extends TimerTask { - /** - * 任务是否有效 - */ - private boolean canRun = true; - private AppCompatActivity activity; - - private void setCanRun(boolean canRun) { - this.canRun = canRun; - } - - public MyTimerTask(AppCompatActivity activity) { - this.activity = activity; - } - - @Override - public void run() { - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - if (canRun) { - // 程序退到后台,进行风险警告 - if (home || back){ - Toast.makeText(activity, activity.getString(R.string.anti_hijacking_tips_home), Toast.LENGTH_LONG).show(); - - tasks.remove(MyTimerTask.this); - home = false; - }else { - Toast.makeText(activity, activity.getString(R.string.anti_hijacking_tips), Toast.LENGTH_LONG).show(); -// TextHelper.showLongText(MyApplication.getApplication().getString(R.string.anti_hijacking_tips)); - tasks.remove(MyTimerTask.this); - } - } - } - }); - } - - } - - -} - diff --git a/app/src/main/java/xyz/fycz/myreader/util/BeanPropertiesUtil.java b/app/src/main/java/xyz/fycz/myreader/util/BeanPropertiesUtil.java deleted file mode 100644 index 7fc2bae..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/BeanPropertiesUtil.java +++ /dev/null @@ -1,125 +0,0 @@ -package xyz.fycz.myreader.util; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -/** - * Created by Kodulf - */ -public class BeanPropertiesUtil { - /** - * 利用反射实现对象之间属性复制 - * @param from - * @param to - */ - public static void copyProperties(Object from, Object to) throws Exception { - copyPropertiesExclude(from, to, null); - } - - /** - * 复制对象属性 - * @param from - * @param to - * @param excludsArray 排除属性列表 - * @throws Exception - */ - @SuppressWarnings("unchecked") - public static void copyPropertiesExclude(Object from, Object to, String[] excludsArray) throws Exception { - List excludesList = null; - if(excludsArray != null && excludsArray.length > 0) { - excludesList = Arrays.asList(excludsArray); //构造列表对象 - } - Method[] fromMethods = from.getClass().getDeclaredMethods(); - Method[] toMethods = to.getClass().getDeclaredMethods(); - Method fromMethod = null, toMethod = null; - String fromMethodName = null, toMethodName = null; - for (int i = 0; i < fromMethods.length; i++) { - fromMethod = fromMethods[i]; - fromMethodName = fromMethod.getName(); - if (!fromMethodName.contains("get") || fromMethodName.contains("getId")) - continue; - //排除列表检测 - if(excludesList != null && excludesList.contains(fromMethodName.substring(3).toLowerCase())) { - continue; - } - toMethodName = "set" + fromMethodName.substring(3); - toMethod = findMethodByName(toMethods, toMethodName); - if (toMethod == null) - continue; - Object value = fromMethod.invoke(from); - if(value == null) - continue; - //集合类判空处理 - if(value instanceof Collection) { - Collection newValue = (Collection)value; - if(newValue.size() <= 0) - continue; - } - toMethod.invoke(to, value); - } - } - - /** - * 对象属性值复制,仅复制指定名称的属性值 - * @param from - * @param to - * @param includsArray - * @throws Exception - */ - @SuppressWarnings("unchecked") - public static void copyPropertiesInclude(Object from, Object to, String[] includsArray) throws Exception { - List includesList = null; - if(includsArray != null && includsArray.length > 0) { - includesList = Arrays.asList(includsArray); //构造列表对象 - } else { - return; - } - Method[] fromMethods = from.getClass().getDeclaredMethods(); - Method[] toMethods = to.getClass().getDeclaredMethods(); - Method fromMethod = null, toMethod = null; - String fromMethodName = null, toMethodName = null; - for (int i = 0; i < fromMethods.length; i++) { - fromMethod = fromMethods[i]; - fromMethodName = fromMethod.getName(); - if (!fromMethodName.contains("get")) - continue; - //排除列表检测 - String str = fromMethodName.substring(3); - if(!includesList.contains(str.substring(0,1).toLowerCase() + str.substring(1))) { - continue; - } - toMethodName = "set" + fromMethodName.substring(3); - toMethod = findMethodByName(toMethods, toMethodName); - if (toMethod == null) - continue; - Object value = fromMethod.invoke(from); - if(value == null) - continue; - //集合类判空处理 - if(value instanceof Collection) { - Collection newValue = (Collection)value; - if(newValue.size() <= 0) - continue; - } - toMethod.invoke(to, value); - } - } - - - - /** - * 从方法数组中获取指定名称的方法 - * - * @param methods - * @param name - * @return - */ - public static Method findMethodByName(Method[] methods, String name) { - for (int j = 0; j < methods.length; j++) { - if (methods[j].getName().equals(name)) - return methods[j]; - } - return null; - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/DownloadMangerUtils.java b/app/src/main/java/xyz/fycz/myreader/util/DownloadMangerUtils.java deleted file mode 100644 index f8f65f1..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/DownloadMangerUtils.java +++ /dev/null @@ -1,431 +0,0 @@ -package xyz.fycz.myreader.util; - -import android.Manifest; -import android.app.DownloadManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.util.Log; - -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; - -import java.util.HashMap; -import java.util.Map; - -import xyz.fycz.myreader.common.APPCONST; -import xyz.fycz.myreader.ui.dialog.DialogCreator; - -import static android.app.DownloadManager.Request.VISIBILITY_HIDDEN; - - - -public class DownloadMangerUtils { - - public static final String FILE_DIR = "gxdw"; - private static Map mBroadcastReceiverMap = new HashMap<>(); - - /** - * 文件下载 - * - * @param context - * @param fileDir - * @param url - * @param fileName - */ - public static void downloadFile(Context context, String fileDir, String url, String fileName) { - - try { - Log.d("http download:", url); - //String Url = "10.10.123.16:8080/gxqdw_ubap/mEmailController.thumb?getAttachmentStream&fileId=1&fileName=自我探索——我是谁.ppt&emailId=36&token=d1828248-cc71-4719-8218-adc31ffc9cca&type=inbox&fileSize=14696446"; - - DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); - // DownloadManager.Request.setDestinationInExternalPublicDir(); - - request.setDescription(fileName); - request.setTitle("附件"); - // in order for this if to run, you must use the android 3.2 to compile your app - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - request.allowScanningByMediaScanner(); - request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); - // request.setNotificationVisibility(VISIBILITY_HIDDEN); - } - // int i = Build.VERSION.SDK_INT; - if (Build.VERSION.SDK_INT > 17) { - request.setDestinationInExternalPublicDir(fileDir, fileName); - } else { - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - request.setDestinationInExternalPublicDir(fileDir, fileName); - } else { - Log.d("download", "android版本过低,不存在外部存储,下载路径无法指定,默认路径:/data/data/com.android.providers.downloads/cache/"); - DialogCreator.createCommonDialog(context, "文件下载", "android版本过低或系统兼容性问题,不存在外部存储,无法指定下载路径,文件下载到系统默认路径,请到文件管理搜索文件名", true, - "关闭", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }); - - } - } - // get download service and enqueue file - DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - manager.enqueue(request); - } catch (Exception e) { - e.printStackTrace(); - lowVersionNoSDDownload(context, url, fileName); - } - } - - /** - * 低版本无外置存储下载 - * - * @param context - * @param url - * @param fileName - */ - private static void lowVersionNoSDDownload(Context context, String url, String fileName) { - try { - Log.d("http download:", url); - //String Url = "10.10.123.16:8080/gxqdw_ubap/mEmailController.thumb?getAttachmentStream&fileId=1&fileName=自我探索——我是谁.ppt&emailId=36&token=d1828248-cc71-4719-8218-adc31ffc9cca&type=inbox&fileSize=14696446"; - - DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); - // DownloadManager.Request.setDestinationInExternalPublicDir(); - - request.setDescription(fileName); - request.setTitle("附件"); - // in order for this if to run, you must use the android 3.2 to compile your app - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - request.allowScanningByMediaScanner(); - request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); - // request.setNotificationVisibility(VISIBILITY_HIDDEN); - } - // int i = Build.VERSION.SDK_INT; - - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - request.setDestinationInExternalPublicDir(APPCONST.FILE_DIR, fileName); - } else { - Log.d("download", "android版本过低,不存在外部存储,下载路径无法指定,默认路径:/data/data/com.android.providers.downloads/cache/"); - DialogCreator.createCommonDialog(context, "文件下载", "android版本过低或系统兼容性问题,不存在外部存储,无法指定下载路径,文件下载到系统默认路径,请到文件管理搜索文件名", true, - "关闭", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }); - } - // get download service and enqueue file - DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - manager.enqueue(request); - } catch (Exception e) { - e.printStackTrace(); - ToastUtils.showError("下载错误:" + e.getLocalizedMessage()); - } - - } - - - /** - * 文件下载(有回调,无通知) - * - * @param context - * @param fileDir - * @param fileName - * @param url - * @param listener - */ - public static void downloadFileByFinishListener(Context context, String fileDir, String fileName, String url, - final DownloadCompleteListener listener) { - try { - if (isPermission(context)) { - Log.d("http download:", url); -// String Url = "10.10.123.16:8080/gxqdw_ubap/mEmailController.thumb?getAttachmentStream&fileId=1&fileName=自我探索——我是谁.ppt&emailId=36&token=d1828248-cc71-4719-8218-adc31ffc9cca&type=inbox&fileSize=14696446"; - - DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); -// DownloadManager.Request.setDestinationInExternalPublicDir(); - - /* request.setDescription(fileName); - request.setTitle("附件");*/ -// in order for this if to run, you must use the android 3.2 to compile your app - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - request.allowScanningByMediaScanner(); -// request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); - request.setNotificationVisibility(VISIBILITY_HIDDEN); - } -// int i = Build.VERSION.SDK_INT; - if (Build.VERSION.SDK_INT > 17) { - request.setDestinationInExternalPublicDir(fileDir, fileName); - } else { - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - request.setDestinationInExternalPublicDir(fileDir, fileName); - } else { - Log.i("download", "android版本过低,不存在外部存储,下载路径无法指定,默认路径:/data/data/com.android.providers.downloads/cache/"); - } - } -// get download service and enqueue file - final DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - - final long id = manager.enqueue(request); - // 注册广播监听系统的下载完成事件。 - IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); - - final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - long ID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); - if (ID == id) { - listener.onFinish(manager.getUriForDownloadedFile(id)); - context.unregisterReceiver(mBroadcastReceiverMap.get(id)); - mBroadcastReceiverMap.remove(id); - /* Toast.makeText(getApplicationContext(), "任务:" + Id + " 下载完成!", Toast.LENGTH_LONG).show();*/ - } - } - }; - context.registerReceiver(broadcastReceiver, intentFilter); - mBroadcastReceiverMap.put(id, broadcastReceiver); - } - } catch (Exception e) { - lowVersionNoSDDownloadFileByFinishListener(context, fileDir, fileName, url, listener); -// listener.onError(e.toString()); - } - - } - - /** - * 低版本无外置存储文件下载(有回调,无通知) - * - * @param context - * @param fileDir - * @param fileName - * @param url - * @param listener - */ - private static void lowVersionNoSDDownloadFileByFinishListener(Context context, String fileDir, String fileName, String url, - final DownloadCompleteListener listener) { - try { - - Log.d("http download:", url); -// String Url = "10.10.123.16:8080/gxqdw_ubap/mEmailController.thumb?getAttachmentStream&fileId=1&fileName=自我探索——我是谁.ppt&emailId=36&token=d1828248-cc71-4719-8218-adc31ffc9cca&type=inbox&fileSize=14696446"; - - DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); -// DownloadManager.Request.setDestinationInExternalPublicDir(); - - /* request.setDescription(fileName); - request.setTitle("附件");*/ -// in order for this if to run, you must use the android 3.2 to compile your app - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - request.allowScanningByMediaScanner(); -// request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); - request.setNotificationVisibility(VISIBILITY_HIDDEN); - } -// int i = Build.VERSION.SDK_INT; - - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - request.setDestinationInExternalPublicDir(APPCONST.FILE_DIR, fileName); - } else { - Log.d("download", "android版本过低,不存在外部存储,下载路径无法指定,默认路径:/data/data/com.android.providers.downloads/cache/"); - } - -// get download service and enqueue file - final DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - - final long id = manager.enqueue(request); - // 注册广播监听系统的下载完成事件。 - IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); - - final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - long ID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); - if (ID == id) { - listener.onFinish(manager.getUriForDownloadedFile(id)); - context.unregisterReceiver(mBroadcastReceiverMap.get(id)); - mBroadcastReceiverMap.remove(id); - /* Toast.makeText(getApplicationContext(), "任务:" + Id + " 下载完成!", Toast.LENGTH_LONG).show();*/ - } - } - }; - context.registerReceiver(broadcastReceiver, intentFilter); - mBroadcastReceiverMap.put(id, broadcastReceiver); - - } catch (Exception e) { - listener.onError(e.toString()); - } - - } - - /** - * 文件下载(有回调,有通知) - * - * @param context - * @param fileDir - * @param fileName - * @param url - * @param title - * @param listener - */ - public static void downloadFileOnNotificationByFinishListener(final Context context, final String fileDir, final String fileName, final String url, - final String title, final DownloadCompleteListener listener) { - try { - if (isPermission(context)) { - Log.d("http download:", url); - - DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); - request.setTitle(title); - - // in order for this if to run, you must use the android 3.2 to compile your app - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - request.allowScanningByMediaScanner(); - request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE); - } - - if (Build.VERSION.SDK_INT > 17) { - /* File file = new File(Environment.getExternalStorageDirectory() + "/gxdw/apk/app_gxdw_186.apk"); - if (!file.exists()){ - boolean flag = file.createNewFile(); - }*/ - request.setDestinationInExternalPublicDir(fileDir, fileName); - - } else { - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - request.setDestinationInExternalPublicDir(fileDir, fileName); - } else { - Log.d("download", "android版本过低,不存在外部存储,下载路径无法指定,默认路径:/data/data/com.android.providers.downloads/cache/"); - } - } - -// get download service and enqueue file - final DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - - final long id = manager.enqueue(request); - // 注册广播监听系统的下载完成事件。 - IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); - - final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - long ID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); - if (ID == id) { - listener.onFinish(manager.getUriForDownloadedFile(id)); - context.unregisterReceiver(mBroadcastReceiverMap.get(id)); - mBroadcastReceiverMap.remove(id); - /* Toast.makeText(getApplicationContext(), "任务:" + Id + " 下载完成!", Toast.LENGTH_LONG).show();*/ - } - } - }; - context.registerReceiver(broadcastReceiver, intentFilter); - mBroadcastReceiverMap.put(id, broadcastReceiver); - } - } catch (Exception e) { - e.printStackTrace(); - lowVersionDownloadFileOnNotificationByFinishListener(context, fileDir, fileName, url, title, listener); - } - } - - /** - * 低版本文件下载(有回调,有通知) - * - * @param context - * @param fileDir - * @param fileName - * @param url - * @param title - * @param listener - */ - private static void lowVersionDownloadFileOnNotificationByFinishListener(final Context context, final String fileDir, final String fileName, final String url, - final String title, final DownloadCompleteListener listener) { - - - try { - - Log.d("http download:", url); - - DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); - request.setTitle(title); - -// in order for this if to run, you must use the android 3.2 to compile your app - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - request.allowScanningByMediaScanner(); - request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE); - - } - - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - request.setDestinationInExternalPublicDir(APPCONST.FILE_DIR, fileName); - } else { - Log.d("download", "android版本过低,不存在外部存储,下载路径无法指定,默认路径:/data/data/com.android.providers.downloads/cache/"); - } - - - // get download service and enqueue file - final DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - - final long id = manager.enqueue(request); - // 注册广播监听系统的下载完成事件。 - IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); - - final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - long ID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); - if (ID == id) { - listener.onFinish(manager.getUriForDownloadedFile(id)); - context.unregisterReceiver(mBroadcastReceiverMap.get(id)); - mBroadcastReceiverMap.remove(id); - } - } - }; - context.registerReceiver(broadcastReceiver, intentFilter); - mBroadcastReceiverMap.put(id, broadcastReceiver); - - } catch (Exception e) { - e.printStackTrace(); - listener.onError(e.toString()); - } - - - } - - - /** - * 读写权限判断 - * - * @param context - * @return - */ - public static boolean isPermission(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; - } - - public interface DownloadCompleteListener { - void onFinish(Uri uri); - - void onError(String s); - } - - -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/IdHelper.java b/app/src/main/java/xyz/fycz/myreader/util/IdHelper.java deleted file mode 100644 index 9999d19..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/IdHelper.java +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.fycz.myreader.util; - - - -public class IdHelper { - - public static String getId(){ - java.util.Date date = new java.util.Date(); - int rand = (int)(1+ Math.random()*(25-0+1)); -// char c = (char) ('a' + rand); - return String.valueOf(date.getTime()%100000000); - - } -} diff --git a/app/src/main/java/xyz/fycz/myreader/util/Lunar.java b/app/src/main/java/xyz/fycz/myreader/util/Lunar.java deleted file mode 100644 index 138b6c8..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/Lunar.java +++ /dev/null @@ -1,266 +0,0 @@ -package xyz.fycz.myreader.util; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; - - - -public class Lunar -{ - private int year; - private int month; - private int day; - private boolean leap; - final static String chineseNumber[] = - { "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二" }; - final static String Big_Or_Small[] = - { "大", "小", "大", "小", "大", "小", "大", "大", "小", "大", "小", "大" }; - private String[] LunarHolDayName = - { "小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", - "小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", - "冬至" }; - - static SimpleDateFormat chineseDateFormat = new SimpleDateFormat(" yyyy年MM月dd日 "); - final static long[] lunarInfo = new long[] - { 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, - 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, - 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, - 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, - 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, - 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, - 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, - 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, - 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, - 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, - 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, - 0x0b5a0, 0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, - 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, - 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, - 0x092e0, 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, - 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, - 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, - 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, - 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, - 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, - 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, - 0x06d20, 0x0ada0 }; - - // ====== 传回农历 y年的总天数 - final private static int yearDays(int y) - { - int i, sum = 348; - for (i = 0x8000; i > 0x8; i >>= 1) - { - if ((lunarInfo[y - 1900] & i) != 0) - sum += 1; - } - return (sum + leapDays(y)); - } - - // ====== 传回农历 y年闰月的天数 - final private static int leapDays(int y) - { - if (leapMonth(y) != 0) - { - if ((lunarInfo[y - 1900] & 0x10000) != 0) - return 30; - else - return 29; - } - else - return 0; - } - - // ====== 传回农历 y年闰哪个月 1-12 , 没闰传回 0 - final private static int leapMonth(int y) - { - return (int) (lunarInfo[y - 1900] & 0xf); - } - - // ====== 传回农历 y年m月的总天数 - final private static int monthDays(int y, int m) - { - if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0) - return 29; - else - return 30; - } - - // ====== 传回农历 y年的生肖 - final public String animalsYear() - { - final String[] Animals = new String[] - { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" }; - return Animals[(year - 4) % 12]; - } - - // ====== 传入 月日的offset 传回干支, 0=甲子 - final private static String cyclicalm(int num) - { - final String[] Gan = new String[] - { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" }; - final String[] Zhi = new String[] - { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" }; - return (Gan[num % 10] + Zhi[num % 12]); - } - - // ====== 传入 offset 传回干支, 0=甲子 - final public String cyclical() - { - int num = year - 1900 + 36; - return (cyclicalm(num)); - } - - /** */ - /** - * 传出y年m月d日对应的农历. yearCyl3:农历年与1864的相差数 ? monCyl4:从1900年1月31日以来,闰月数 - * dayCyl5:与1900年1月31日相差的天数,再加40 ? - * - * @param cal - * @return - */ - public Lunar(Calendar cal) - { - // cal.add(cal.get(Calendar.DAY_OF_MONTH),1); - @SuppressWarnings(" unused ") - int yearCyl, monCyl, dayCyl; - int leapMonth = 0; - Date baseDate = null; - try - { - baseDate = chineseDateFormat.parse(" 1900年1月31日 "); - } - catch (ParseException e) - { - e.printStackTrace(); // To change body of catch statement use - // Options | File Templates. - } - - // 求出和1900年1月31日相差的天数 - int offset = (int) ((cal.getTime().getTime() - baseDate.getTime()) / 86400000L); - dayCyl = offset + 40; - monCyl = 14; - - // 用offset减去每农历年的天数 - // 计算当天是农历第几天 - // i最终结果是农历的年份 - // offset是当年的第几天 - int iYear, daysOfYear = 0; - for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) - { - daysOfYear = yearDays(iYear); - offset -= daysOfYear; - monCyl += 12; - } - if (offset < 0) - { - offset += daysOfYear; - iYear--; - monCyl -= 12; - } - // 农历年份 - year = iYear; - - yearCyl = iYear - 1864; - leapMonth = leapMonth(iYear); // 闰哪个月,1-12 - leap = false; - - // 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天 - int iMonth, daysOfMonth = 0; - for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) - { - // 闰月 - if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap) - { - --iMonth; - leap = true; - daysOfMonth = leapDays(year); - } - else - daysOfMonth = monthDays(year, iMonth); - - offset -= daysOfMonth; - // 解除闰月 - if (leap && iMonth == (leapMonth + 1)) - leap = false; - if (!leap) - monCyl++; - } - // offset为0时,并且刚才计算的月份是闰月,要校正 - if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) - { - if (leap) - { - leap = false; - } - else - { - leap = true; - --iMonth; - --monCyl; - } - } - // offset小于0时,也要校正 - if (offset < 0) - { - offset += daysOfMonth; - --iMonth; - --monCyl; - } - month = iMonth; - day = offset + 1; - } - - public static String getChinaDayString(int day) - { - String chineseTen[] = - { "初", "十", "廿", "卅" }; - int n = day % 10 == 0 ? 9 : day % 10 - 1; - if (day > 30) - return ""; - if (day == 10) - return "初十"; - else - return chineseTen[day / 10] + chineseNumber[n]; - } - - public String toString() - { - return /* cyclical() + "年" + */(leap ? "闰" : "") - + chineseNumber[month - 1] + "月" + getChinaDayString(day); - } - - public String numeric_md() - {// 返回阿拉伯数字的阴历日期 - String temp_day; - String temp_mon; - temp_mon = month < 10 ? "0" + month : "" + month; - temp_day = day < 10 ? "0" + day : "" + day; - - return temp_mon + temp_day; - } - - public String get_month() - {// 返回阴历的月份 - return chineseNumber[month - 1]; - } - - public String get_date(int year, int month, int date) - { - /* // 返回阴历的天 - LunarCalendar lunarCalendar = LunarCalendar.getInstance(); - String str = lunarCalendar.CalculateLunarCalendar(year,month,date); - if(StringHelper.isEmpty(str)){ - str = getChinaDayString(day); - }*/ - return getChinaDayString(day); - } - - public String get_Big_Or_Small() - {// 返回的月份的大或小 - return Big_Or_Small[month - 1]; - } - -} \ No newline at end of file diff --git a/app/src/main/java/xyz/fycz/myreader/util/LunarCalendar.java b/app/src/main/java/xyz/fycz/myreader/util/LunarCalendar.java deleted file mode 100644 index 995427d..0000000 --- a/app/src/main/java/xyz/fycz/myreader/util/LunarCalendar.java +++ /dev/null @@ -1,326 +0,0 @@ -package xyz.fycz.myreader.util; - - - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; - -public class LunarCalendar { - - private int lyear; - - private int lmonth; - - private int lday; - - private boolean leap; - - private String solarTerms = ""; - - private int yearCyl, monCyl, dayCyl; - - private String solarFestival = ""; - - private String lunarFestival = ""; - - private Calendar baseDate = Calendar.getInstance(); - - private Calendar offDate = Calendar.getInstance(); - - private SimpleDateFormat chineseDateFormat = new SimpleDateFormat( - "yyyy年MM月dd日"); - - final static long[] lunarInfo = new long[]{0x04bd8, 0x04ae0, 0x0a570, - 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, - 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, - 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, - 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, - 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, - 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, - 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, - 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, - 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, - 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, - 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6, - 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, - 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, - 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960, - 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, - 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, - 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, - 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, - 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, - 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, - 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0}; - - final static String[] Gan = new String[]{"甲", "乙", "丙", "丁", "戊", "己", - "庚", "辛", "壬", "癸"}; - - final static String[] Zhi = new String[]{"子", "丑", "寅", "卯", "辰", "巳", - "午", "未", "申", "酉", "戌", "亥"}; - - final static String[] Animals = new String[]{"鼠", "牛", "虎", "兔", "龙", - "蛇", "马", "羊", "猴", "鸡", "狗", "猪"}; - - final static String[] SolarTerm = new String[]{"小寒", "大寒", "立春", "雨水", - "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", - "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"}; - final static long[] STermInfo = new long[]{0, 21208, 42467, 63836, 85337, - 107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343, - 285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795, - 462224, 483532, 504758}; - - final static String chineseMonthNumber[] = {"正", "二", "三", "四", "五", "六", - "七", "八", "九", "十", "冬", "腊"}; - - final static String[] sFtv = new String[]{"0101*元旦", "0214 情人节", - "0308 妇女节", "0312 植树节", /*"0314 国际警察日", "0315 消费者权益日", "0323 世界气象日",*/ - "0401 愚人节", /*"0407 世界卫生日",*/ "0501*劳动节", "0504 青年节", /*"0508 红十字日",*/ - "0512 护士节", /*"0515 国际家庭日", "0517 世界电信日", "0519 全国助残日", "0531 世界无烟日",*/ - "0601 儿童节", /*"0605 世界环境日", "0606 全国爱眼日", "0623 奥林匹克日", "0625 全国土地日",*/ - /*"0626 反毒品日",*/ "0701 建党节", /*"0707 抗战纪念日", "0711 世界人口日",*/ "0801 建军节", - /* "0908 国际扫盲日", "0909 毛xx逝世纪念",*/ "0910 教师节", /*"0917 国际和平日",*/ - /* "0920 国际爱牙日", "0922 国际聋人节", "0927 世界旅游日", "0928 孔子诞辰",*/ "1001*国庆节", - /* "1004 世界动物日", "1006 老人节", "1007 国际住房日", "1009 世界邮政日", "1015 国际盲人节",*/ - /* "1016 世界粮食日", "1024 联合国日", */"1031 万圣节",/* "1108 中国记者日", "1109 消防宣传日",*/ - /* "1112 孙中山诞辰", "1114 世界糖尿病日", "1117 国际大学生节",*/ "1128 感恩节", - /* "1201 世界艾滋病日", "1203 世界残疾人日", "1209 世界足球日", "1220 澳门回归",*/ - "1225 圣诞节", /*"1226 毛xx诞辰"*/}; - - final static String[] lFtv = {"0101*春节", "0115 元宵", "0505 端午", - "0707 七夕", "0815 中秋", "0909 重阳", "1208 腊八", "1223 小年", - "0100*除夕"}; - - final static String[] wFtv = {"0521 母亲节", "0631 父亲节"};//每年6月第3个星期日是父亲节,5月的第2个星期日是母亲节 - - //星期日是一个周的第1天第3个星期日也就是第3个完整周的第一天 - - // - private LunarCalendar() { - baseDate.setMinimalDaysInFirstWeek(7);//设置一个月的第一个周是一个完整周 - - } - - final private static int lYearDays(int y)//====== 传回农历 y年的总天数 - { - int i, sum = 348; - for (i = 0x8000; i > 0x8; i >>= 1) { - if ((lunarInfo[y - 1900] & i) != 0) - sum += 1; - } - return (sum + leapDays(y)); - } - - final private static int leapDays(int y)//====== 传回农历 y年闰月的天数 - { - if (leapMonth(y) != 0) { - if ((lunarInfo[y - 1900] & 0x10000) != 0) - return 30; - else - return 29; - } else - return 0; - } - - final private static int leapMonth(int y)//====== 传回农历 y年闰哪个月 1-12 , 没闰传回 0 - { - return (int) (lunarInfo[y - 1900] & 0xf); - } - - final public static int monthDays(int y, int m)//====== 传回农历 y年m月的总天数 - { - if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0) - return 29; - else - return 30; - } - - final private static String AnimalsYear(int y)//====== 传回农历 y年的生肖 - { - - return Animals[(y - 4) % 12]; - } - - final private static String cyclical(int num)//====== 传入 的offset 传回干支, - // 0=甲子 - { - - return (Gan[num % 10] + Zhi[num % 12]); - } - - // ===== 某年的第n个节气为几日(从0小寒起算) - final private int sTerm(int y, int n) { - - offDate.set(1900, 0, 6, 2, 5, 0); - long temp = offDate.getTime().getTime(); - offDate - .setTime(new Date( - (long) ((31556925974.7 * (y - 1900) + STermInfo[n] * 60000L) + temp))); - - return offDate.get(Calendar.DAY_OF_MONTH); - } - - /** - * 传出y年m月d日对应的农历. - */ - public String CalculateLunarCalendar(int y, int m, int d) { - - int leapMonth = 0; - - try { - baseDate.setTime(chineseDateFormat.parse("1900年1月31日")); - - } catch (ParseException e) { - e.printStackTrace(); - } - long base = baseDate.getTimeInMillis(); - try { - baseDate.setTime(chineseDateFormat.parse(y + "年" + m + "月" + d - + "日")); - - } catch (ParseException e) { - e.printStackTrace(); - } - long obj = baseDate.getTimeInMillis(); - - - int offset = (int) ((obj - base) / 86400000L); - //System.out.println(offset); - //求出和1900年1月31日相差的天数 - - dayCyl = offset + 40;//干支天 - monCyl = 14;//干支月 - - //用offset减去每农历年的天数 - // 计算当天是农历第几天 - //i最终结果是农历的年份 - //offset是当年的第几天 - int iYear, daysOfYear = 0; - for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) { - daysOfYear = lYearDays(iYear); - offset -= daysOfYear; - monCyl += 12; - } - if (offset < 0) { - offset += daysOfYear; - iYear--; - monCyl -= 12; - } - //农历年份 - lyear = iYear; - - yearCyl = iYear - 1864;//***********干支年**********// - - leapMonth = leapMonth(iYear); //闰哪个月,1-12 - leap = false; - - //用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天 - int iMonth, daysOfMonth = 0; - for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) { - //闰月 - if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap) { - --iMonth; - leap = true; - daysOfMonth = leapDays(iYear); - } else - daysOfMonth = monthDays(iYear, iMonth); - - offset -= daysOfMonth; - //解除闰月 - if (leap && iMonth == (leapMonth + 1)) - leap = false; - if (!leap) - monCyl++; - } - //offset为0时,并且刚才计算的月份是闰月,要校正 - if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) { - if (leap) { - leap = false; - } else { - leap = true; - --iMonth; - --monCyl; - } - } - //offset小于0时,也要校正 - if (offset < 0) { - offset += daysOfMonth; - --iMonth; - --monCyl; - } - lmonth = iMonth; - lday = offset + 1; - - //******************计算节气**********// - - if (d == sTerm(y, (m - 1) * 2)) - solarTerms = SolarTerm[(m - 1) * 2]; - else if (d == sTerm(y, (m - 1) * 2 + 1)) - solarTerms = SolarTerm[(m - 1) * 2 + 1]; - else - solarTerms = ""; - - //计算公历节日 - this.solarFestival = ""; - for (int i = 0; i < sFtv.length; i++) { - if (Integer.parseInt(sFtv[i].substring(0, 2)) == m - && Integer.parseInt(sFtv[i].substring(2, 4)) == d) { - solarFestival = sFtv[i].substring(5); - break; - } - } - //计算农历节日 - this.lunarFestival = ""; - for (int i = 0; i < lFtv.length; i++) { - if (Integer.parseInt(lFtv[i].substring(0, 2)) == lmonth - && Integer.parseInt(lFtv[i].substring(2, 4)) == lday) { - lunarFestival = lFtv[i].substring(5); - break; - } - } - //计算月周节日 - - // System.out.println(baseDate.get(Calendar.WEEK_OF_MONTH) + "" - // + baseDate.get(Calendar.DAY_OF_WEEK)); - - for (int i = 0; i < wFtv.length; i++) { - if (Integer.parseInt(wFtv[i].substring(0, 2)) == m - && Integer.parseInt(wFtv[i].substring(2, 3)) == baseDate - .get(Calendar.WEEK_OF_MONTH) - && Integer.parseInt(wFtv[i].substring(3, 4)) == baseDate - .get(Calendar.DAY_OF_WEEK)) { - solarFestival += wFtv[i].substring(5); - } - } - if(!StringHelper.isEmpty(lunarFestival)){ - return lunarFestival; - } - if(!StringHelper.isEmpty(solarFestival)){ - return solarFestival; - } - if(!StringHelper.isEmpty(solarTerms)){ - return solarTerms; - } - return ""; - - } - - //set方法 - public void set(int y, int m, int d) { - - CalculateLunarCalendar(y, m, d); - } - - public void set(Calendar cal) { - - CalculateLunarCalendar(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH)); - } - - // //get方法组 - public static LunarCalendar getInstance() { - - return new LunarCalendar(); - } -} \ No newline at end of file diff --git a/app/src/main/java/xyz/fycz/myreader/util/ToastUtils.java b/app/src/main/java/xyz/fycz/myreader/util/ToastUtils.java index 4458487..ac4d836 100644 --- a/app/src/main/java/xyz/fycz/myreader/util/ToastUtils.java +++ b/app/src/main/java/xyz/fycz/myreader/util/ToastUtils.java @@ -1,5 +1,7 @@ package xyz.fycz.myreader.util; +import android.os.Build; +import android.widget.Toast; import androidx.annotation.NonNull; import es.dmoral.toasty.Toasty; import xyz.fycz.myreader.R; @@ -16,50 +18,76 @@ public class ToastUtils { } public static void show(@NonNull String msg) { - MyApplication.runOnUiThread(() -> Toasty.custom(MyApplication.getmContext(), msg, - MyApplication.getmContext().getDrawable(R.drawable.ic_smile_face), - MyApplication.getmContext().getColor(R.color.toast_default), - MyApplication.getmContext().getColor(R.color.white), - Toasty.LENGTH_SHORT, true, true).show()); + MyApplication.runOnUiThread(() -> { + if (showOld(msg)) return; + Toasty.custom(MyApplication.getmContext(), msg, + MyApplication.getmContext().getDrawable(R.drawable.ic_smile_face), + MyApplication.getmContext().getColor(R.color.toast_default), + MyApplication.getmContext().getColor(R.color.white), + Toasty.LENGTH_SHORT, true, true).show(); + }); } //红色 public static void showError(@NonNull String msg) { - MyApplication.runOnUiThread(() -> Toasty.custom(MyApplication.getmContext(), msg, - MyApplication.getmContext().getDrawable(R.drawable.ic_error), - MyApplication.getmContext().getColor(R.color.toast_red), - MyApplication.getmContext().getColor(R.color.white), - Toasty.LENGTH_SHORT, true, true).show()); + MyApplication.runOnUiThread(() -> { + if (showOld(msg)) return; + Toasty.custom(MyApplication.getmContext(), msg, + MyApplication.getmContext().getDrawable(R.drawable.ic_error), + MyApplication.getmContext().getColor(R.color.toast_red), + MyApplication.getmContext().getColor(R.color.white), + Toasty.LENGTH_SHORT, true, true).show(); + }); } //绿色 public static void showSuccess(@NonNull String msg) { - MyApplication.runOnUiThread(() -> Toasty.custom(MyApplication.getmContext(), msg, - MyApplication.getmContext().getDrawable(R.drawable.ic_success), - MyApplication.getmContext().getColor(R.color.toast_green), - MyApplication.getmContext().getColor(R.color.white), - Toasty.LENGTH_SHORT, true, true).show()); + MyApplication.runOnUiThread(() -> { + if (showOld(msg)) return; + Toasty.custom(MyApplication.getmContext(), msg, + MyApplication.getmContext().getDrawable(R.drawable.ic_success), + MyApplication.getmContext().getColor(R.color.toast_green), + MyApplication.getmContext().getColor(R.color.white), + Toasty.LENGTH_SHORT, true, true).show(); + }); } //蓝色 public static void showInfo(@NonNull String msg) { - MyApplication.runOnUiThread(() -> Toasty.custom(MyApplication.getmContext(), msg, - MyApplication.getmContext().getDrawable(R.drawable.ic_smile_face), - MyApplication.getmContext().getColor(R.color.toast_blue), - MyApplication.getmContext().getColor(R.color.white), - Toasty.LENGTH_SHORT, true, true).show()); + MyApplication.runOnUiThread(() -> { + if (showOld(msg)) return; + Toasty.custom(MyApplication.getmContext(), msg, + MyApplication.getmContext().getDrawable(R.drawable.ic_smile_face), + MyApplication.getmContext().getColor(R.color.toast_blue), + MyApplication.getmContext().getColor(R.color.white), + Toasty.LENGTH_SHORT, true, true).show(); + }); } //黄色 public static void showWarring(@NonNull String msg) { - MyApplication.runOnUiThread(() -> Toasty.warning(MyApplication.getmContext(), msg, Toasty.LENGTH_SHORT, true).show()); + MyApplication.runOnUiThread(() -> { + if (showOld(msg)) return; + Toasty.warning(MyApplication.getmContext(), msg, Toasty.LENGTH_SHORT, true).show(); + }); } public static void showExit(@NonNull String msg) { - MyApplication.runOnUiThread(() -> Toasty.custom(MyApplication.getmContext(), msg, - MyApplication.getmContext().getDrawable(R.drawable.ic_cry_face), - MyApplication.getmContext().getColor(R.color.toast_blue), - MyApplication.getmContext().getColor(R.color.white), - Toasty.LENGTH_SHORT, true, true).show()); + MyApplication.runOnUiThread(() -> { + if (showOld(msg)) return; + Toasty.custom(MyApplication.getmContext(), msg, + MyApplication.getmContext().getDrawable(R.drawable.ic_cry_face), + MyApplication.getmContext().getColor(R.color.toast_blue), + MyApplication.getmContext().getColor(R.color.white), + Toasty.LENGTH_SHORT, true, true).show(); + }); + } + + private static boolean showOld(@NonNull String msg){ + if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + Toast.makeText(MyApplication.getmContext(), msg, Toast.LENGTH_SHORT).show(); + return true; + } + return false; } } diff --git a/app/src/main/java/xyz/fycz/myreader/util/utils/SnackbarUtils.java b/app/src/main/java/xyz/fycz/myreader/util/utils/SnackbarUtils.java new file mode 100644 index 0000000..f0d883c --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/util/utils/SnackbarUtils.java @@ -0,0 +1,68 @@ +package xyz.fycz.myreader.util.utils; + +import android.graphics.drawable.Drawable; +import android.view.View; +import android.widget.TextView; +import androidx.annotation.NonNull; +import com.google.android.material.snackbar.Snackbar; +import xyz.fycz.myreader.R; +import xyz.fycz.myreader.application.MyApplication; + + +/** + * Created by zhouas666 on 2017/12/28. + * Snackbar工具类 + */ +public class SnackbarUtils { + + + public static void show(@NonNull View view, @NonNull String msg) { + show(view, msg, true, null, null); + } + + /** + * 展示snackBar + * + * @param view view + * @param msg 消息 + * @param isDismiss 是否自动消失 + * @param action 事件名 + * @param iSnackBarClickEvent 事件处理接口 + */ + public static void show(@NonNull View view, @NonNull String msg, boolean isDismiss, String action, final ISnackBarClickEvent iSnackBarClickEvent) { + //snackBar默认显示时间为LENGTH_LONG + int duringTime = Snackbar.LENGTH_LONG; + if (!isDismiss) { + duringTime = Snackbar.LENGTH_INDEFINITE; + } + Snackbar snackbar; + snackbar = Snackbar.make(view, msg, duringTime); + if (action != null) + snackbar.setAction(action, view1 -> { + //以接口方式发送出去,便于使用者处理自己的业务逻辑 + iSnackBarClickEvent.clickEvent(); + }); + //设置snackBar和titleBar颜色一致 + snackbar.getView().setBackgroundColor(MyApplication.getmContext().getColor(R.color.textPrimary)); + //设置action文字的颜色 + snackbar.setActionTextColor(MyApplication.getmContext().getColor(R.color.md_white_1000)); + //设置snackBar图标 这里是获取到snackBar的textView 然后给textView增加左边图标的方式来实现的 + View snackBarView = snackbar.getView(); + TextView textView = snackBarView.findViewById(R.id.snackbar_text); + /*Drawable drawable = getResources().getDrawable(R.mipmap.ic_notification);//图片自己选择 + drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight()); + textView.setCompoundDrawables(drawable, null, null, null);*/ + //增加文字和图标的距离 + textView.setCompoundDrawablePadding(20); + //展示snackBar + snackbar.show(); + } + + /** + * snackBar的action事件 + */ + public interface ISnackBarClickEvent { + void clickEvent(); + } + +} diff --git a/app/src/main/java/xyz/fycz/myreader/util/utils/SystemBarUtils.java b/app/src/main/java/xyz/fycz/myreader/util/utils/SystemBarUtils.java new file mode 100644 index 0000000..4c0ed52 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/util/utils/SystemBarUtils.java @@ -0,0 +1,161 @@ +package xyz.fycz.myreader.util.utils; + +import android.app.Activity; +import android.os.Build; +import android.view.View; +import android.view.WindowManager; + +/** + * 基于 Android 4.4 + * + * 主要参数说明: + * + * SYSTEM_UI_FLAG_FULLSCREEN : 隐藏StatusBar + * SYSTEM_UI_FLAG_HIDE_NAVIGATION : 隐藏NavigationBar + * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN: 视图扩展到StatusBar的位置,并且StatusBar不消失。 + * 这里需要一些处理,一般是将StatusBar设置为全透明或者半透明。之后还需要使用fitSystemWindows=防止视图扩展到Status + * Bar上面(会在StatusBar上加一层View,该View可被移动) + * SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION: 视图扩展到NavigationBar的位置 + * SYSTEM_UI_FLAG_LAYOUT_STABLE:稳定效果 + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY:保证点击任意位置不会退出 + * + * 可设置特效说明: + * 1. 全屏特效 + * 2. 全屏点击不退出特效 + * 3. 注意在19 <=sdk <=21 时候,必须通过Window设置透明栏 + */ + +public class SystemBarUtils { + + private static final int UNSTABLE_STATUS = View.SYSTEM_UI_FLAG_FULLSCREEN; + private static final int UNSTABLE_NAV = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + private static final int STABLE_STATUS = View.SYSTEM_UI_FLAG_FULLSCREEN | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + private static final int STABLE_NAV = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + private static final int EXPAND_STATUS = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; + private static final int EXPAND_NAV = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; + + + //设置隐藏StatusBar(点击任意地方会恢复) + public static void hideUnStableStatusBar(Activity activity){ + //App全屏,隐藏StatusBar + setFlag(activity, UNSTABLE_STATUS); + } + + public static void showUnStableStatusBar(Activity activity){ + clearFlag(activity, UNSTABLE_STATUS); + } + + //隐藏NavigationBar(点击任意地方会恢复) + public static void hideUnStableNavBar(Activity activity){ + setFlag(activity,UNSTABLE_NAV); + } + + public static void showUnStableNavBar(Activity activity){ + clearFlag(activity,UNSTABLE_NAV); + } + + public static void hideStableStatusBar(Activity activity){ + //App全屏,隐藏StatusBar + setFlag(activity,STABLE_STATUS); + } + + public static void showStableStatusBar(Activity activity){ + clearFlag(activity,STABLE_STATUS); + } + + public static void hideStableNavBar(Activity activity){ + //App全屏,隐藏StatusBar + setFlag(activity,STABLE_NAV); + } + + public static void showStableNavBar(Activity activity){ + clearFlag(activity,STABLE_NAV); + } + + /** + * 视图扩充到StatusBar + */ + public static void expandStatusBar(Activity activity){ + setFlag(activity, EXPAND_STATUS); + } + + /** + * 视图扩充到NavBar + * @param activity + */ + public static void expandNavBar(Activity activity){ + setFlag(activity, EXPAND_NAV); + } + + public static void transparentStatusBar(Activity activity){ + if (Build.VERSION.SDK_INT >= 21){ + expandStatusBar(activity); + activity.getWindow() + .setStatusBarColor(activity.getResources().getColor(android.R.color.transparent)); + } + else if (Build.VERSION.SDK_INT >= 19){ + WindowManager.LayoutParams attrs = activity.getWindow().getAttributes(); + attrs.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | attrs.flags); + activity.getWindow().setAttributes(attrs); + } + } + + public static void transparentNavBar(Activity activity){ + if (Build.VERSION.SDK_INT >= 21){ + expandNavBar(activity); + //下面这个方法在sdk:21以上才有 + activity.getWindow() + .setNavigationBarColor(activity.getResources().getColor(android.R.color.transparent)); + } + } + + public static void setFlag(Activity activity, int flag){ + if (Build.VERSION.SDK_INT >= 19){ + View decorView = activity.getWindow().getDecorView(); + int option = decorView.getSystemUiVisibility() | flag; + decorView.setSystemUiVisibility(option); + } + } + + //取消flag + public static void clearFlag(Activity activity, int flag){ + if (Build.VERSION.SDK_INT >= 19){ + View decorView = activity.getWindow().getDecorView(); + int option = decorView.getSystemUiVisibility() & (~flag); + decorView.setSystemUiVisibility(option); + } + } + + public static void setToggleFlag(Activity activity, int option){ + if (Build.VERSION.SDK_INT >= 19){ + if (isFlagUsed(activity,option)){ + clearFlag(activity,option); + } + else { + setFlag(activity,option); + } + } + } + + /** + * @param activity + * @return flag是否已被使用 + */ + public static boolean isFlagUsed(Activity activity, int flag) { + int currentFlag = activity.getWindow().getDecorView().getSystemUiVisibility(); + if((currentFlag & flag) + == flag) { + return true; + }else { + return false; + } + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/ReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/ReadCrawler.java index a857e1b..9f0de47 100644 --- a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/ReadCrawler.java +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/base/ReadCrawler.java @@ -13,12 +13,12 @@ import java.util.ArrayList; */ public interface ReadCrawler { - String getSearchLink(); - String getCharset(); - String getSearchCharset(); - String getNameSpace(); - Boolean isPost(); - String getContentFormHtml(String html); - ArrayList getChaptersFromHtml(String html); - ConcurrentMultiValueMap getBooksFromSearchHtml(String html); + String getSearchLink(); // 书源的搜索url + String getCharset(); // 书源的字符编码 + String getSearchCharset(); // 书源搜索关键字的字符编码,和书源的字符编码就行 + String getNameSpace(); // 书源主页地址 + Boolean isPost(); // 是否以post请求搜索 + String getContentFormHtml(String html); // 获取书籍内容规则 + ArrayList getChaptersFromHtml(String html); // 获取书籍章节列表规则 + ConcurrentMultiValueMap getBooksFromSearchHtml(String html); // 搜索书籍规则 } 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 7068be1..8f6436d 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 @@ -21,6 +21,7 @@ import xyz.fycz.myreader.util.ToastUtils; import xyz.fycz.myreader.util.utils.RxUtils; import xyz.fycz.myreader.util.utils.ScreenUtils; import xyz.fycz.myreader.util.utils.StringUtils; +import xyz.fycz.myreader.widget.animation.PageAnimation; import java.io.BufferedReader; import java.io.File; @@ -1036,7 +1037,6 @@ public abstract class PageLoader { //对内容进行绘制 for (int i = mCurPage.titleLines; i < mCurPage.lines.size(); ++i) { str = mCurPage.lines.get(i); - canvas.drawText(str, mMarginWidth, top, mTextPaint); if (str.endsWith("\n")) { top += para; @@ -1592,7 +1592,22 @@ public abstract class PageLoader { } return strLength; } - + /** + * @return 本页内容 + */ + public String getContent() { + if (mCurPageList == null) return null; + if (mCurPageList.size() == 0) return null; + TxtPage txtPage = mCurPage; + StringBuilder s = new StringBuilder(); + int size = txtPage.lines.size(); + //int start = mPageMode == PageMode.SCROLL ? Math.min(Math.max(0, linePos), size - 1) : 0; + int start = 0; + for (int i = start; i < size; i++) { + s.append(txtPage.lines.get(i)); + } + return s.toString(); + } /*****************************************interface*****************************************/ public interface OnPageChangeListener { @@ -1631,7 +1646,5 @@ public abstract class PageLoader { */ void onPageChange(int pos); - void preLoading(); - } } 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 24f26be..f9142c8 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,6 +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.util.utils.SnackbarUtils; import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import xyz.fycz.myreader.widget.animation.*; @@ -251,7 +252,11 @@ public class PageView extends View { */ private boolean hasPrevPage() { mTouchListener.prePage(); - return mPageLoader.prev(); + boolean hasPrevPage = mPageLoader.prev(); + if (!hasPrevPage){ + showSnackBar("已经是第一页了"); + } + return hasPrevPage; } /** @@ -262,6 +267,9 @@ public class PageView extends View { private boolean hasNextPage() { boolean hasNextPage = mPageLoader.next(); mTouchListener.nextPage(hasNextPage); + if (!hasNextPage){ + showSnackBar("已经是最后一页了"); + } return hasNextPage; } @@ -270,6 +278,16 @@ public class PageView extends View { mPageLoader.pageCancel(); } + /** + * 显示tips + * + * @param msg + */ + public void showSnackBar(String msg) { + SnackbarUtils.show(this, msg); + } + + @Override public void computeScroll() { //进行滑动 diff --git a/app/src/main/res/anim/slide_bottom_in.xml b/app/src/main/res/anim/slide_bottom_in.xml new file mode 100644 index 0000000..dc96ec4 --- /dev/null +++ b/app/src/main/res/anim/slide_bottom_in.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_bottom_out.xml b/app/src/main/res/anim/slide_bottom_out.xml new file mode 100644 index 0000000..7b0d50e --- /dev/null +++ b/app/src/main/res/anim/slide_bottom_out.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_top_in.xml b/app/src/main/res/anim/slide_top_in.xml new file mode 100644 index 0000000..3b70ebe --- /dev/null +++ b/app/src/main/res/anim/slide_top_in.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_top_out.xml b/app/src/main/res/anim/slide_top_out.xml new file mode 100644 index 0000000..ec14f76 --- /dev/null +++ b/app/src/main/res/anim/slide_top_out.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/ic_keyboard_arrow_left_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_keyboard_arrow_left_black_24dp.png deleted file mode 100644 index 4c91cfa..0000000 Binary files a/app/src/main/res/drawable-hdpi/ic_keyboard_arrow_left_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_refresh_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_refresh_black_24dp.png deleted file mode 100644 index 6998e9f..0000000 Binary files a/app/src/main/res/drawable-hdpi/ic_refresh_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_search_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_search_black_24dp.png deleted file mode 100644 index 5e28ca5..0000000 Binary files a/app/src/main/res/drawable-hdpi/ic_search_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_keyboard_arrow_left_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_keyboard_arrow_left_black_24dp.png deleted file mode 100644 index 001be7e..0000000 Binary files a/app/src/main/res/drawable-mdpi/ic_keyboard_arrow_left_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_refresh_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_refresh_black_24dp.png deleted file mode 100644 index 8a8d85d..0000000 Binary files a/app/src/main/res/drawable-mdpi/ic_refresh_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_search_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_search_black_24dp.png deleted file mode 100644 index e3312b6..0000000 Binary files a/app/src/main/res/drawable-mdpi/ic_search_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/arm_left.png b/app/src/main/res/drawable-xhdpi/arm_left.png deleted file mode 100644 index 24369fe..0000000 Binary files a/app/src/main/res/drawable-xhdpi/arm_left.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/arm_right.png b/app/src/main/res/drawable-xhdpi/arm_right.png deleted file mode 100644 index b237b84..0000000 Binary files a/app/src/main/res/drawable-xhdpi/arm_right.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/bg.jpeg b/app/src/main/res/drawable-xhdpi/bg.jpeg deleted file mode 100644 index e3461f1..0000000 Binary files a/app/src/main/res/drawable-xhdpi/bg.jpeg and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_keyboard_arrow_left_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_keyboard_arrow_left_black_24dp.png deleted file mode 100644 index 782eebf..0000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_keyboard_arrow_left_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_refresh_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_refresh_black_24dp.png deleted file mode 100644 index d42027e..0000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_refresh_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_search_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_search_black_24dp.png deleted file mode 100644 index 5386c0a..0000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_search_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/icon_hand.png b/app/src/main/res/drawable-xhdpi/icon_hand.png deleted file mode 100644 index bf1db64..0000000 Binary files a/app/src/main/res/drawable-xhdpi/icon_hand.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/iconfont_password.png b/app/src/main/res/drawable-xhdpi/iconfont_password.png deleted file mode 100644 index 2cc8fd9..0000000 Binary files a/app/src/main/res/drawable-xhdpi/iconfont_password.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/iconfont_user.png b/app/src/main/res/drawable-xhdpi/iconfont_user.png deleted file mode 100644 index 8dfb2ee..0000000 Binary files a/app/src/main/res/drawable-xhdpi/iconfont_user.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/owl_head.png b/app/src/main/res/drawable-xhdpi/owl_head.png deleted file mode 100644 index efacadd..0000000 Binary files a/app/src/main/res/drawable-xhdpi/owl_head.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_keyboard_arrow_left_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_keyboard_arrow_left_black_24dp.png deleted file mode 100644 index 63bfd2d..0000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_keyboard_arrow_left_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_menu_overflow.png b/app/src/main/res/drawable-xxhdpi/ic_menu_overflow.png deleted file mode 100644 index c382aa6..0000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_menu_overflow.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_menu_setting.png b/app/src/main/res/drawable-xxhdpi/ic_menu_setting.png deleted file mode 100644 index 4f9c0b4..0000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_menu_setting.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_refresh_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_refresh_black_24dp.png deleted file mode 100644 index 79aebbe..0000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_refresh_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_search_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_search_black_24dp.png deleted file mode 100644 index 90581a9..0000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_search_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_keyboard_arrow_left_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_keyboard_arrow_left_black_24dp.png deleted file mode 100644 index 6818b9b..0000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_keyboard_arrow_left_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_refresh_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_refresh_black_24dp.png deleted file mode 100644 index 766b4a4..0000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_refresh_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_search_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_search_black_24dp.png deleted file mode 100644 index d16e423..0000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_search_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable/ic_bookmark.xml b/app/src/main/res/drawable/ic_bookmark.xml index 22fe21c..79cec7d 100644 --- a/app/src/main/res/drawable/ic_bookmark.xml +++ b/app/src/main/res/drawable/ic_bookmark.xml @@ -1,11 +1,12 @@ - - - - \ No newline at end of file + android:viewportWidth="1024" + android:viewportHeight="1024"> + + + diff --git a/app/src/main/res/drawable/ic_copy.xml b/app/src/main/res/drawable/ic_copy.xml new file mode 100644 index 0000000..c19c966 --- /dev/null +++ b/app/src/main/res/drawable/ic_copy.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_link.xml b/app/src/main/res/drawable/ic_link.xml index 8d56ed1..5951a45 100644 --- a/app/src/main/res/drawable/ic_link.xml +++ b/app/src/main/res/drawable/ic_link.xml @@ -1,14 +1,12 @@ - - - - - \ No newline at end of file + android:viewportWidth="1024" + android:viewportHeight="1024"> + + + diff --git a/app/src/main/res/drawable/ic_search2.xml b/app/src/main/res/drawable/ic_search2.xml new file mode 100644 index 0000000..2572d53 --- /dev/null +++ b/app/src/main/res/drawable/ic_search2.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_catalog.xml b/app/src/main/res/layout/activity_catalog.xml index 2119b2b..4755a24 100644 --- a/app/src/main/res/layout/activity_catalog.xml +++ b/app/src/main/res/layout/activity_catalog.xml @@ -18,7 +18,7 @@ android:fitsSystemWindows="true" app:titleTextAppearance="@style/toolbar_title_textStyle" app:subtitleTextAppearance="@style/toolbar_subtitle_textStyle" - android:theme="@style/Theme.ToolBar.Dark.Menu"> + android:theme="?attr/actionBarStyle"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -