package com.yzx.webebook.activity; import android.app.Activity; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.ContentObserver; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.PowerManager; import android.provider.Settings; import android.util.Log; import android.view.Gravity; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.SeekBar; import android.widget.TextView; import androidx.core.content.ContextCompat; import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; import com.blankj.utilcode.util.NumberUtils; import com.google.android.material.appbar.AppBarLayout; import com.yzx.webebook.R; import com.yzx.webebook.activity.base.BaseActivity; import com.yzx.webebook.adapter.CategoryAdapter; import com.yzx.webebook.model.bean.BookChapterBean; import com.yzx.webebook.model.bean.CollBookBean; import com.yzx.webebook.model.local.BookRepository; import com.yzx.webebook.model.local.ReadSettingManager; import com.yzx.webebook.presenter.ReadPresenter; import com.yzx.webebook.presenter.ReadView; import com.yzx.webebook.utils.BrightnessUtils; import com.yzx.webebook.utils.Constant; import com.yzx.webebook.utils.LogUtils; import com.yzx.webebook.utils.RxUtils; import com.yzx.webebook.utils.ScreenUtils; import com.yzx.webebook.utils.StringUtils; import com.yzx.webebook.utils.SystemBarUtils; import com.yzx.webebook.widget.ReadSettingDialog; import com.yzx.webebook.widget.page.PageLoader; import com.yzx.webebook.widget.page.PageView; import com.yzx.webebook.widget.page.TxtChapter; import org.jetbrains.annotations.Nullable; import java.util.List; import io.reactivex.disposables.Disposable; import static android.view.View.GONE; import static android.view.View.VISIBLE; public class ReadActivity extends BaseActivity implements ReadView { private static final String TAG = "ReadActivity"; public static final int REQUEST_MORE_SETTING = 1; public static final String EXTRA_COLL_BOOK = "extra_coll_book"; public static final String EXTRA_IS_COLLECTED = "extra_is_collected"; // 注册 Brightness 的 uri private final Uri BRIGHTNESS_MODE_URI = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE); private final Uri BRIGHTNESS_URI = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS); private final Uri BRIGHTNESS_ADJ_URI = Settings.System.getUriFor("screen_auto_brightness_adj"); private static final int WHAT_CATEGORY = 1; private static final int WHAT_CHAPTER = 2; DrawerLayout mDlSlide; /*************top_menu_view*******************/ // AppBarLayout mAblTopMenu; // TextView mTvCommunity; // TextView mTvBrief; /***************content_view******************/ PageView mPvPage; /***************bottom_menu_view***************************/ TextView mTvPageTip; LinearLayout mLlBottomMenu; TextView mTvPreChapter; SeekBar mSbChapterProgress; TextView mTvNextChapter; TextView mTvCategory; TextView mTvNightMode; TextView mTvSetting; /***************left slide*******************************/ ListView mLvCategory; /*****************view******************/ private ReadSettingDialog mSettingDialog; private PageLoader mPageLoader; private Animation mTopInAnim; private Animation mTopOutAnim; private Animation mBottomInAnim; private Animation mBottomOutAnim; private CategoryAdapter mCategoryAdapter; private CollBookBean mCollBook; //控制屏幕常亮 private PowerManager.WakeLock mWakeLock; /***************params*****************/ private boolean isCollected = false; // isFromSDCard private boolean isNightMode = false; private boolean isFullScreen = false; private boolean isRegistered = false; private String mBookId; private String mRealBookId; private String mReadTaskId; private float lastProgress = 0f; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case WHAT_CATEGORY: mLvCategory.setSelection(mPageLoader.getChapterPos()); break; case WHAT_CHAPTER: mPageLoader.openChapter(); break; } } }; // 接收电池信息和时间更新的广播 private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) { int level = intent.getIntExtra("level", 0); if (mPageLoader != null) { mPageLoader.updateBattery(level); } } // 监听分钟的变化 else if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) { if (mPageLoader != null) { mPageLoader.updateTime(); } } } }; // 亮度调节监听 // 由于亮度调节没有 Broadcast 而是直接修改 ContentProvider 的。所以需要创建一个 Observer 来监听 ContentProvider 的变化情况。 private ContentObserver mBrightObserver = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { onChange(selfChange, null); } @Override public void onChange(boolean selfChange, Uri uri) { super.onChange(selfChange); // 判断当前是否跟随屏幕亮度,如果不是则返回 if (selfChange || !mSettingDialog.isBrightFollowSystem()) return; // 如果系统亮度改变,则修改当前 Activity 亮度 if (BRIGHTNESS_MODE_URI.equals(uri)) { Log.d(TAG, "亮度模式改变"); } else if (BRIGHTNESS_URI.equals(uri) && !BrightnessUtils.isAutoBrightness(ReadActivity.this)) { Log.d(TAG, "亮度模式为手动模式 值改变"); BrightnessUtils.setBrightness(ReadActivity.this, BrightnessUtils.getScreenBrightness(ReadActivity.this)); } else if (BRIGHTNESS_ADJ_URI.equals(uri) && BrightnessUtils.isAutoBrightness(ReadActivity.this)) { Log.d(TAG, "亮度模式为自动模式 值改变"); BrightnessUtils.setDefaultBrightness(ReadActivity.this); } else { Log.d(TAG, "亮度调整 其他"); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public int getInflateId() { return R.layout.activity_read; } @Override public void initView() { mDlSlide = findViewById(R.id.read_dl_slide); // mTvCommunity = findViewById(R.id.read_tv_community); // mTvBrief = findViewById(R.id.read_tv_brief); mPvPage = findViewById(R.id.read_pv_page); mTvPageTip = findViewById(R.id.read_tv_page_tip); mLlBottomMenu = findViewById(R.id.read_ll_bottom_menu); mTvPreChapter = findViewById(R.id.read_tv_pre_chapter); mSbChapterProgress = findViewById(R.id.read_sb_chapter_progress); mTvNextChapter = findViewById(R.id.read_tv_next_chapter); mTvCategory = findViewById(R.id.read_tv_category); mTvNightMode = findViewById(R.id.read_tv_night_mode); mTvSetting = findViewById(R.id.read_tv_setting); mLvCategory = findViewById(R.id.read_iv_category); } @Override public void initData() { String id = getIntent().getStringExtra("book_id"); mReadTaskId = getIntent().getStringExtra("read_task_id"); mRealBookId = getIntent().getStringExtra("real_book_id"); loadBookData(id); getMPresenter().getReadProgress(mRealBookId, mReadTaskId); } private void loadBookData(String id) { mCollBook = BookRepository.getInstance().getCollBook(id); isNightMode = ReadSettingManager.getInstance().isNightMode(); isFullScreen = ReadSettingManager.getInstance().isFullScreen(); mBookId = mCollBook.get_id(); Log.d(TAG, "initData: " + mCollBook.toString()); //获取页面加载器 mPageLoader = mPvPage.getPageLoader(mCollBook); //禁止滑动展示DrawerLayout mDlSlide.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); //侧边打开后,返回键能够起作用 mDlSlide.setFocusableInTouchMode(false); mSettingDialog = new ReadSettingDialog(this, mPageLoader); setUpAdapter(); //夜间模式按钮的状态 toggleNightMode(); //注册广播 IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); intentFilter.addAction(Intent.ACTION_TIME_TICK); registerReceiver(mReceiver, intentFilter); //设置当前Activity的Brightness if (ReadSettingManager.getInstance().isBrightnessAuto()) { BrightnessUtils.setDefaultBrightness(this); } else { BrightnessUtils.setBrightness(this, ReadSettingManager.getInstance().getBrightness()); } //初始化屏幕常亮类 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "ireader:keep bright"); //初始化BottomMenu initBottomMenu(); Disposable disposable = BookRepository.getInstance() .getBookChaptersInRx(mBookId) .compose(RxUtils::toSimpleSingle) .subscribe( (bookChapterBeen, throwable) -> { // 设置 CollBook mPageLoader.getCollBook().setBookChapters(bookChapterBeen); // 刷新章节列表 mPageLoader.refreshChapterList(); LogUtils.e(throwable); } ); addDisposable(disposable); initClick(); } private void saveBookInfo() { if (mCollBook != null) { mCollBook.setLastRead(StringUtils. dateConvert(System.currentTimeMillis(), Constant.FORMAT_BOOK_DATE)); BookRepository.getInstance() .saveCollBookWithAsync(mCollBook); } } private void initClick() { mPageLoader.setOnPageChangeListener( new PageLoader.OnPageChangeListener() { @Override public void onChapterChange(int pos) { mCategoryAdapter.setChapter(pos); } @Override public void requestChapters(List requestChapters) { getMPresenter().loadChapter(mBookId, requestChapters); mHandler.sendEmptyMessage(WHAT_CATEGORY); //隐藏提示 mTvPageTip.setVisibility(GONE); } @Override public void onCategoryFinish(List chapters) { for (TxtChapter chapter : chapters) { chapter.setTitle(StringUtils.convertCC(chapter.getTitle(), mPvPage.getContext())); } mCategoryAdapter.refreshItems(chapters); } @Override public void onPageCountChange(int count) { mSbChapterProgress.setMax(Math.max(0, count - 1)); mSbChapterProgress.setProgress(0); // 如果处于错误状态,那么就冻结使用 if (mPageLoader.getPageStatus() == PageLoader.STATUS_LOADING || mPageLoader.getPageStatus() == PageLoader.STATUS_ERROR) { mSbChapterProgress.setEnabled(false); } else { mSbChapterProgress.setEnabled(true); } } @Override public void onPageChange(int pos) { mSbChapterProgress.post( () -> { mSbChapterProgress.setProgress(pos); } ); } } ); mSbChapterProgress.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (mLlBottomMenu.getVisibility() == VISIBLE) { //显示标题 mTvPageTip.setText((progress + 1) + "/" + (mSbChapterProgress.getMax() + 1)); mTvPageTip.setVisibility(VISIBLE); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { //进行切换 int pagePos = mSbChapterProgress.getProgress(); if (pagePos != mPageLoader.getPagePos()) { mPageLoader.skipToPage(pagePos); } //隐藏提示 mTvPageTip.setVisibility(GONE); } } ); mPvPage.setTouchListener(new PageView.TouchListener() { @Override public boolean onTouch() { return !hideReadMenu(); } @Override public void center() { toggleMenu(true); } @Override public void prePage() { } @Override public void nextPage() { } @Override public void cancel() { } }); mLvCategory.setOnItemClickListener( (parent, view, position, id) -> { mDlSlide.closeDrawer(GravityCompat.START); mPageLoader.skipToChapter(position); } ); mTvCategory.setOnClickListener( (v) -> { //移动到指定位置 if (mCategoryAdapter.getCount() > 0) { mLvCategory.setSelection(mPageLoader.getChapterPos()); } //切换菜单 toggleMenu(true); //打开侧滑动栏 mDlSlide.openDrawer(GravityCompat.START); } ); mTvSetting.setOnClickListener( (v) -> { toggleMenu(false); mSettingDialog.show(); } ); mTvPreChapter.setOnClickListener( (v) -> { if (mPageLoader.skipPreChapter()) { mCategoryAdapter.setChapter(mPageLoader.getChapterPos()); } } ); mTvNextChapter.setOnClickListener( (v) -> { if (mPageLoader.skipNextChapter()) { mCategoryAdapter.setChapter(mPageLoader.getChapterPos()); } } ); mTvNightMode.setOnClickListener( (v) -> { if (isNightMode) { isNightMode = false; } else { isNightMode = true; } mPageLoader.setNightMode(isNightMode); toggleNightMode(); } ); } @Nullable @Override public ReadPresenter initPresenter() { return new ReadPresenter(this); } @Override public void showCategory(String localId) { loadBookData(localId); } @Override public void finishChapter() { } @Override public void errorChapter() { } private void initBottomMenu() { //判断是否全屏 if (ReadSettingManager.getInstance().isFullScreen()) { //还需要设置mBottomMenu的底部高度 ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mLlBottomMenu.getLayoutParams(); params.bottomMargin = ScreenUtils.getNavigationBarHeight(); mLlBottomMenu.setLayoutParams(params); } else { //设置mBottomMenu的底部距离 ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mLlBottomMenu.getLayoutParams(); params.bottomMargin = 0; mLlBottomMenu.setLayoutParams(params); } } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); } private void toggleNightMode() { if (isNightMode) { mTvNightMode.setText("日间"); Drawable drawable = ContextCompat.getDrawable(this, R.mipmap.ic_read_menu_morning); mTvNightMode.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null); } else { mTvNightMode.setText("夜间"); Drawable drawable = ContextCompat.getDrawable(this, R.mipmap.ic_read_menu_night); mTvNightMode.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null); } } private void setUpAdapter() { mCategoryAdapter = new CategoryAdapter(); mLvCategory.setAdapter(mCategoryAdapter); mLvCategory.setFastScrollEnabled(true); } // 注册亮度观察者 private void registerBrightObserver() { try { if (mBrightObserver != null) { if (!isRegistered) { final ContentResolver cr = getContentResolver(); cr.unregisterContentObserver(mBrightObserver); cr.registerContentObserver(BRIGHTNESS_MODE_URI, false, mBrightObserver); cr.registerContentObserver(BRIGHTNESS_URI, false, mBrightObserver); cr.registerContentObserver(BRIGHTNESS_ADJ_URI, false, mBrightObserver); isRegistered = true; } } } catch (Throwable throwable) { LogUtils.e(TAG, "register mBrightObserver error! " + throwable); } } //解注册 private void unregisterBrightObserver() { try { if (mBrightObserver != null) { if (isRegistered) { getContentResolver().unregisterContentObserver(mBrightObserver); isRegistered = false; } } } catch (Throwable throwable) { LogUtils.e(TAG, "unregister BrightnessObserver error! " + throwable); } } /** * 隐藏阅读界面的菜单显示 * * @return 是否隐藏成功 */ private boolean hideReadMenu() { if (mLlBottomMenu.getVisibility() == VISIBLE) { toggleMenu(true); return true; } else if (mSettingDialog.isShowing()) { mSettingDialog.dismiss(); return true; } return false; } /** * 切换菜单栏的可视状态 * 默认是隐藏的 */ private void toggleMenu(boolean hideStatusBar) { initMenuAnim(); if (mLlBottomMenu.getVisibility() == View.VISIBLE) { //关闭 mLlBottomMenu.setVisibility(GONE); mTvPageTip.setVisibility(GONE); } else { mLlBottomMenu.setVisibility(View.VISIBLE); } } //初始化菜单动画 private void initMenuAnim() { if (mTopInAnim != null) return; mTopInAnim = AnimationUtils.loadAnimation(this, R.anim.slide_top_in); mTopOutAnim = AnimationUtils.loadAnimation(this, R.anim.slide_top_out); mBottomInAnim = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_in); mBottomOutAnim = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_out); //退出的速度要快 mTopOutAnim.setDuration(200); mBottomOutAnim.setDuration(200); } @Override public void onBackPressed() { if (mLlBottomMenu.getVisibility() == View.VISIBLE) { // 非全屏下才收缩,全屏下直接退出 if (!ReadSettingManager.getInstance().isFullScreen()) { toggleMenu(true); return; } } else if (mSettingDialog.isShowing()) { mSettingDialog.dismiss(); return; } else if (mDlSlide.isDrawerOpen(GravityCompat.START)) { mDlSlide.closeDrawer(GravityCompat.START); return; } if (!mCollBook.isLocal() && !isCollected && !mCollBook.getBookChapters().isEmpty() && false) { AlertDialog alertDialog = new AlertDialog.Builder(this) .setTitle("加入书架") .setMessage("喜欢本书就加入书架吧") .setPositiveButton("确定", (dialog, which) -> { //设置为已收藏 isCollected = true; //设置阅读时间 mCollBook.setLastRead(StringUtils. dateConvert(System.currentTimeMillis(), Constant.FORMAT_BOOK_DATE)); BookRepository.getInstance() .saveCollBookWithAsync(mCollBook); exit(); }) .setNegativeButton("取消", (dialog, which) -> { exit(); }).create(); alertDialog.show(); } else { exit(); } } // 退出 private void exit() { // 退出 super.onBackPressed(); } @Override protected void onStart() { super.onStart(); registerBrightObserver(); } @Override protected void onResume() { super.onResume(); if (mWakeLock != null) { mWakeLock.acquire(); } } @Override protected void onPause() { super.onPause(); if (mWakeLock != null) { mWakeLock.release(); } if (mPageLoader != null) { saveBookInfo(); mPageLoader.saveRecord(); } if (getMPresenter() != null && mPageLoader != null) { float currProgress = Float.parseFloat(mPageLoader.getPercent()); if (currProgress > lastProgress) { getMPresenter().updateReadProgress(mRealBookId, mReadTaskId, String.valueOf(mPageLoader.getPercent())); } } } @Override protected void onStop() { super.onStop(); unregisterBrightObserver(); } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(mReceiver); mHandler.removeMessages(WHAT_CATEGORY); mHandler.removeMessages(WHAT_CHAPTER); mPageLoader.closeBook(); mPageLoader = null; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { boolean isVolumeTurnPage = ReadSettingManager .getInstance().isVolumeTurnPage(); switch (keyCode) { case KeyEvent.KEYCODE_VOLUME_UP: if (isVolumeTurnPage) { return mPageLoader.skipToPrePage(); } break; case KeyEvent.KEYCODE_VOLUME_DOWN: if (isVolumeTurnPage) { return mPageLoader.skipToNextPage(); } break; } return super.onKeyDown(keyCode, event); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_MORE_SETTING) { boolean fullScreen = ReadSettingManager.getInstance().isFullScreen(); if (isFullScreen != fullScreen) { isFullScreen = fullScreen; // 刷新BottomMenu initBottomMenu(); } } } @Override public void onProgressSuccess(float progress) { lastProgress = progress; } }