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 4c91cfa18d39a26fea967e81afc0450239b1b2b7..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 169
zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB3OrpLLn>~)y|$6JK|#bdP>5U7
z>3gDvd4Z&KZ*@dh^^KS23l&7R*__>b^0oihgO*B*{)=8pF-VUJI2e;Tdu`ysH{1MJ
zg%9pYs1iNHsFr=o;QX;$-;dqC#$?*S#JY+pYu(RV(^nk5wyNgR9-+357oYDMS2+E>
Tqq6t{&~64#S3j3^P6}&f
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 6998e9f0328885bd3d653591a3f15d56121d8941..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 463
zcmV;=0WkiFP)w00r4*&{sY9%fp`y8P7#m(Mrt_(WXWnE{tLwa31E<#4~TCfnKOryUg-9CHv!|2rU-pfv8I(MniQNLdmYO*he6kp9%l
zaV1!a{vALZ2gJ%i%nmK9l%Zlfu{7v1s9g+1L7StbHeo*iaWJjQCOK%sotQ>Gs28#b
zh^6UKXv#y|*`TO-48%X7_%XE1Dg|QM(ca=H7zKk7005Ek*bEZTPH_ML002ovPDHLk
FV1iMLw08gi
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 5e28ca5e55d4a3bcaa596647bea035fd8a93875c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 460
zcmV;-0W{;Bbf~iRZ=?a^PDe|IO#k%{gjWWtEk0U4af50vGf_3)p#!+yNi#z&?gg;DMTH
zk#jITAQ8t0a7@a)iW`1|B^c9={K~GxHD91@LP+k+6KKR-cLus3WY=y$Q~S(tnTG_K
zItWtyg=;&P*d^{*ehyG=w^A!DWWL!}4z$LPNITI77ZB4)@XJ
zvIV^id0VuJqpQyroMy;hvwWx_)M5*+sL!OS9?LH@glw8k(W2dy*>{#5X!RjaY=muMAdJetXHXY!ecudh3sF)bAZR#ca
z6a?Z>SGA>@VzwP(O^>M}K7TPGWznFV&^Xvo(+g=A2I2rOgw))WRGJ@mg_Ek%mdKI;Vst0KtPU4gdfE
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 8a8d85d12a4a0453be6b911a5e48ace851a40444..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 308
zcmV-40n7f0P)@exi7usEY1ODe5xlfkod&fnchW}GKsfk!@!im6Fwm(
z#{t)bXARm_dtve>x#F=4`96IuQR4{gc;bxXNV7+ceyk_{zhL-NbbG@90000YI?OEeHd|8h}HrHUD9~04Z5i%;H7@h5!Hn07*qoM6N<$f=iEZ;{X5v
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 24369fefd07ba47892b1ba8f00ca66f392710c5c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 8098
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
MmVY8wDPtb`KZpl(ZU6uP
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 e3461f163381e5ff8caee1f88490045c7a88f581..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 438130
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