diff --git a/.idea/markdown-navigator-enh.xml b/.idea/markdown-navigator-enh.xml
new file mode 100644
index 0000000..a8fcc84
--- /dev/null
+++ b/.idea/markdown-navigator-enh.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/markdown-navigator.xml b/.idea/markdown-navigator.xml
new file mode 100644
index 0000000..a2fc086
--- /dev/null
+++ b/.idea/markdown-navigator.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/androidTest/java/xyz/fycz/myreader/ExampleInstrumentedTest.java b/app/src/androidTest/java/xyz/fycz/myreader/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..db8d9cc
--- /dev/null
+++ b/app/src/androidTest/java/xyz/fycz/myreader/ExampleInstrumentedTest.java
@@ -0,0 +1,37 @@
+package xyz.fycz.myreader;
+
+import android.content.Context;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+import xyz.fycz.myreader.model.audio.ReadService;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("xyz.fycz.myreader", appContext.getPackageName());
+ }
+
+ @Test
+ public void test() {
+ ReadService readService = new ReadService();
+ readService.initSynthesizer();
+ readService.startSynthesizer("科幻电影是我们从小就爱看的电影题材,我们也都梦想过生活在那样的科幻世界里。科幻片,顾名思义即“科学幻想片”,是“以科学幻想为内容的故事片,其基本特点是从今天已知的科学原理和科学成就出发,对未来的世界或遥远的过去的情景作幻想式的描述。”");
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/androidTest/java/xyz/fycz/myreader/TestAudioPlay.java b/app/src/androidTest/java/xyz/fycz/myreader/TestAudioPlay.java
new file mode 100644
index 0000000..f5a5e55
--- /dev/null
+++ b/app/src/androidTest/java/xyz/fycz/myreader/TestAudioPlay.java
@@ -0,0 +1,19 @@
+package xyz.fycz.myreader;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.runner.RunWith;
+
+import xyz.fycz.myreader.model.audio.ReadService;
+
+@RunWith(AndroidJUnit4.class)
+public class TestAudioPlay {
+
+ public void test() {
+ ReadService readService = new ReadService();
+ readService.initSynthesizer();
+ readService.startSynthesizer("科幻电影是我们从小就爱看的电影题材,我们也都梦想过生活在那样的科幻世界里。科幻片,顾名思义即“科学幻想片”,是“以科学幻想为内容的故事片,其基本特点是从今天已知的科学原理和科学成就出发,对未来的世界或遥远的过去的情景作幻想式的描述。”");
+ }
+
+}
+
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/dialog/AudioPlayerDialog.java b/app/src/main/java/xyz/fycz/myreader/ui/dialog/AudioPlayerDialog.java
index 5b89137..f555175 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/dialog/AudioPlayerDialog.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/dialog/AudioPlayerDialog.java
@@ -12,6 +12,7 @@ import android.view.Window;
import android.view.WindowManager;
import android.widget.NumberPicker;
import android.widget.SeekBar;
+import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageView;
@@ -33,8 +34,8 @@ import xyz.fycz.myreader.widget.page.PageLoader;
import static xyz.fycz.myreader.util.utils.StringUtils.getString;
-public class AudioPlayerDialog extends Dialog{
- private static final String TAG="AudioPlayerDialog";
+public class AudioPlayerDialog extends Dialog {
+ private static final String TAG = "AudioPlayerDialog";
private PageLoader mPageLoader;
private ReadActivity mReadActivity;
private boolean aloudNextPage;
@@ -45,6 +46,8 @@ public class AudioPlayerDialog extends Dialog{
private int speechRate;
private int timer;
+ @BindView(R.id.iv_reset_setting)
+ TextView tvResetSetting;
@BindView(R.id.sb_volume_progress)
SeekBar sbVolume;
@BindView(R.id.sb_pitch_progress)
@@ -122,6 +125,18 @@ public class AudioPlayerDialog extends Dialog{
sbVolume.setOnSeekBarChangeListener(seekBarChangeListener);
sbPitch.setOnSeekBarChangeListener(seekBarChangeListener);
sbSpeechRate.setOnSeekBarChangeListener(seekBarChangeListener);
+ tvResetSetting.setOnClickListener(v ->{
+ pitch = 10;
+ speechRate = 10;
+ sbPitch.setProgress(pitch);
+ sbSpeechRate.setProgress(speechRate);
+ SharedPreUtils.getInstance().putInt("pitch", pitch);
+ SharedPreUtils.getInstance().putInt("speechRate", speechRate);
+ if (ReadAloudService.running) {
+ ReadAloudService.pause(mReadActivity);
+ ReadAloudService.resume(mReadActivity);
+ }
+ });
}
private class SeekBarChangeListener implements SeekBar.OnSeekBarChangeListener{
@@ -206,7 +221,7 @@ public class AudioPlayerDialog extends Dialog{
NumberPicker hourPicker = timer.findViewById(R.id.hour_picker);
int hour = this.timer / 60;
int minute = this.timer % 60;
- hourPicker.setMaxValue(24);
+ hourPicker.setMaxValue(5);
hourPicker.setMinValue(0);
hourPicker.setValue(hour);
NumberPicker minutePicker = timer.findViewById(R.id.minute_picker);
diff --git a/app/src/main/java/xyz/fycz/myreader/util/SystemUtil.java b/app/src/main/java/xyz/fycz/myreader/util/SystemUtil.java
new file mode 100644
index 0000000..3d16ec5
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/util/SystemUtil.java
@@ -0,0 +1,54 @@
+package xyz.fycz.myreader.util;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.util.DisplayMetrics;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import static android.content.Context.POWER_SERVICE;
+
+/**
+ */
+
+public class SystemUtil {
+
+ public static double getScreenPhysicalSize(AppCompatActivity ctx) {
+ DisplayMetrics dm = new DisplayMetrics();
+ ctx.getWindowManager().getDefaultDisplay().getMetrics(dm);
+ double diagonalPixels = Math.sqrt(Math.pow(dm.widthPixels, 2) + Math.pow(dm.heightPixels, 2));
+ return diagonalPixels / (160 * dm.density);
+ }
+ public static int getScreenOffTime(Context context) {
+ int screenOffTime = 0;
+ try {
+ screenOffTime = Settings.System.getInt(context.getContentResolver(),
+ Settings.System.SCREEN_OFF_TIMEOUT);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return screenOffTime;
+ }
+
+ public static void ignoreBatteryOptimization(Activity activity) {
+ if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) return;
+
+ PowerManager powerManager = (PowerManager) activity.getSystemService(POWER_SERVICE);
+ boolean hasIgnored = powerManager.isIgnoringBatteryOptimizations(activity.getPackageName());
+ // 判断当前APP是否有加入电池优化的白名单,如果没有,弹出加入电池优化的白名单的设置对话框。
+ if (!hasIgnored) {
+ try {
+ @SuppressLint("BatteryLife")
+ Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
+ intent.setData(Uri.parse("package:" + activity.getPackageName()));
+ activity.startActivity(intent);
+ } catch (Throwable ignored) {
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/util/utils/AudioMngHelper.java b/app/src/main/java/xyz/fycz/myreader/util/utils/AudioMngHelper.java
new file mode 100644
index 0000000..c1e8e32
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/util/utils/AudioMngHelper.java
@@ -0,0 +1,170 @@
+package xyz.fycz.myreader.util.utils;
+
+import android.content.Context;
+import android.media.AudioManager;
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import xyz.fycz.myreader.application.MyApplication;
+import xyz.fycz.myreader.util.SharedPreUtils;
+
+/**
+ *
+ * author: Chestnut
+ * blog : http://www.jianshu.com/u/a0206b5f4526
+ * time : 2017/6/17 16:11
+ * desc : 集成音量控制
+ * thanks To: http://blog.csdn.net/hufeng882412/article/details/7310131
+ * dependent on:
+ * update log:
+ *
+ */
+
+public class AudioMngHelper {
+
+ private final String TAG = "AudioMngHelper";
+ private final boolean OpenLog = true;
+ private static volatile AudioMngHelper sInstance;
+
+
+ private AudioManager audioManager;
+ private int NOW_AUDIO_TYPE = TYPE_MUSIC;
+ private int NOW_FLAG = FLAG_NOTHING;
+ private int VOICE_STEP_100 = 2; //0-100的步进。
+
+ /**
+ * 封装:STREAM_类型
+ */
+ public final static int TYPE_MUSIC = AudioManager.STREAM_MUSIC;
+ public final static int TYPE_ALARM = AudioManager.STREAM_ALARM;
+ public final static int TYPE_RING = AudioManager.STREAM_RING;
+ @IntDef({TYPE_MUSIC, TYPE_ALARM, TYPE_RING})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TYPE {}
+
+ /**
+ * 封装:FLAG
+ */
+ public final static int FLAG_SHOW_UI = AudioManager.FLAG_SHOW_UI;
+ public final static int FLAG_PLAY_SOUND = AudioManager.FLAG_PLAY_SOUND;
+ public final static int FLAG_NOTHING = 0;
+ @IntDef({FLAG_SHOW_UI, FLAG_PLAY_SOUND, FLAG_NOTHING})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FLAG {}
+
+ public static AudioMngHelper getInstance(){
+ if(sInstance == null){
+ synchronized (SharedPreUtils.class){
+ if (sInstance == null){
+ sInstance = new AudioMngHelper(MyApplication.getmContext());
+ }
+ }
+ }
+ return sInstance;
+ }
+ /**
+ * 初始化,获取音量管理者
+ * @param context 上下文
+ */
+ public AudioMngHelper(Context context) {
+ audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ }
+
+ public int getSystemMaxVolume() {
+ return audioManager.getStreamMaxVolume(NOW_AUDIO_TYPE);
+ }
+
+ public int getSystemCurrentVolume() {
+ return audioManager.getStreamVolume(NOW_AUDIO_TYPE);
+ }
+
+ /**
+ * 以0-100为范围,获取当前的音量值
+ * @return 获取当前的音量值
+ */
+ public int get100CurrentVolume() {
+ return 100*getSystemCurrentVolume()/getSystemMaxVolume();
+ }
+
+ /**
+ * 修改步进值
+ * @param step step
+ * @return this
+ */
+ public AudioMngHelper setVoiceStep100(int step) {
+ VOICE_STEP_100 = step;
+ return this;
+ }
+
+ /**
+ * 改变当前的模式,对全局API生效
+ * @param type
+ * @return
+ */
+ public AudioMngHelper setAudioType(@TYPE int type) {
+ NOW_AUDIO_TYPE = type;
+ return this;
+ }
+
+ /**
+ * 改变当前FLAG,对全局API生效
+ * @param flag
+ * @return
+ */
+ public AudioMngHelper setFlag(@FLAG int flag) {
+ NOW_FLAG = flag;
+ return this;
+ }
+
+ public AudioMngHelper addVoiceSystem() {
+ audioManager.adjustStreamVolume(NOW_AUDIO_TYPE,AudioManager.ADJUST_RAISE,NOW_FLAG);
+ return this;
+ }
+
+ public AudioMngHelper subVoiceSystem() {
+ audioManager.adjustStreamVolume(NOW_AUDIO_TYPE,AudioManager.ADJUST_LOWER,NOW_FLAG);
+ return this;
+ }
+
+ /**
+ * 调整音量,自定义
+ * @param num 0-100
+ * @return 改完后的音量值
+ */
+ public int setVoice100(int num) {
+ int a = (int) Math.ceil((num)*getSystemMaxVolume()*0.01);
+ a = a<=0 ? 0 : a;
+ a = a>=100 ? 100 : a;
+ audioManager.setStreamVolume(NOW_AUDIO_TYPE,a,0);
+ return get100CurrentVolume();
+ }
+
+ /**
+ * 步进加,步进值可修改
+ * 0——100
+ * @return 改完后的音量值
+ */
+ public int addVoice100() {
+ int a = (int) Math.ceil((VOICE_STEP_100 + get100CurrentVolume())*getSystemMaxVolume()*0.01);
+ a = a<=0 ? 0 : a;
+ a = a>=100 ? 100 : a;
+ audioManager.setStreamVolume(NOW_AUDIO_TYPE,a,NOW_FLAG);
+ return get100CurrentVolume();
+ }
+
+ /**
+ * 步进减,步进值可修改
+ * 0——100
+ * @return 改完后的音量值
+ */
+ public int subVoice100() {
+ int a = (int) Math.floor((get100CurrentVolume() - VOICE_STEP_100)*getSystemMaxVolume()*0.01);
+ a = a<=0 ? 0 : a;
+ a = a>=100 ? 100 : a;
+ audioManager.setStreamVolume(NOW_AUDIO_TYPE,a,NOW_FLAG);
+ return get100CurrentVolume();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/widget/page/BookChapterBean.java b/app/src/main/java/xyz/fycz/myreader/widget/page/BookChapterBean.java
new file mode 100644
index 0000000..239dd5c
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/widget/page/BookChapterBean.java
@@ -0,0 +1,56 @@
+package xyz.fycz.myreader.widget.page;
+
+
+public class BookChapterBean {
+
+ //章节所属的小说(网络)
+ String bookId;
+ //章节名
+ String title;
+
+ //章节内容在文章中的起始位置(本地)
+ long start;
+ //章节内容在文章中的终止位置(本地)
+ long end;
+
+ public String getBookId() {
+ return bookId;
+ }
+
+ public void setBookId(String id) {
+ this.bookId = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public long getStart() {
+ return start;
+ }
+
+ public void setStart(long start) {
+ this.start = start;
+ }
+
+ public long getEnd() {
+ return end;
+ }
+
+ public void setEnd(long end) {
+ this.end = end;
+ }
+
+ @Override
+ public String toString() {
+ return "BookChapterBean{" +
+ "title='" + title + '\'' +
+ ", start=" + start +
+ ", end=" + end +
+ '}';
+ }
+}
diff --git a/app/src/main/res/drawable/ic_exit.xml b/app/src/main/res/drawable/ic_exit.xml
new file mode 100644
index 0000000..d94b81e
--- /dev/null
+++ b/app/src/main/res/drawable/ic_exit.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_home.xml b/app/src/main/res/drawable/ic_home.xml
new file mode 100644
index 0000000..0520e3a
--- /dev/null
+++ b/app/src/main/res/drawable/ic_home.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_last.xml b/app/src/main/res/drawable/ic_last.xml
new file mode 100644
index 0000000..905a856
--- /dev/null
+++ b/app/src/main/res/drawable/ic_last.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_listen_book.xml b/app/src/main/res/drawable/ic_listen_book.xml
new file mode 100644
index 0000000..8663f4a
--- /dev/null
+++ b/app/src/main/res/drawable/ic_listen_book.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_next.xml b/app/src/main/res/drawable/ic_next.xml
new file mode 100644
index 0000000..ccccc29
--- /dev/null
+++ b/app/src/main/res/drawable/ic_next.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_pause_24dp.xml b/app/src/main/res/drawable/ic_pause_24dp.xml
new file mode 100644
index 0000000..8356ff5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_pause_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_play.xml b/app/src/main/res/drawable/ic_play.xml
new file mode 100644
index 0000000..42326cd
--- /dev/null
+++ b/app/src/main/res/drawable/ic_play.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_play_24dp.xml b/app/src/main/res/drawable/ic_play_24dp.xml
new file mode 100644
index 0000000..81a8f74
--- /dev/null
+++ b/app/src/main/res/drawable/ic_play_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_stop.xml b/app/src/main/res/drawable/ic_stop.xml
new file mode 100644
index 0000000..86e2a25
--- /dev/null
+++ b/app/src/main/res/drawable/ic_stop.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_timer.xml b/app/src/main/res/drawable/ic_timer.xml
new file mode 100644
index 0000000..5a39ddf
--- /dev/null
+++ b/app/src/main/res/drawable/ic_timer.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_volume_up.xml b/app/src/main/res/drawable/ic_volume_up.xml
new file mode 100644
index 0000000..5e5cb11
--- /dev/null
+++ b/app/src/main/res/drawable/ic_volume_up.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/layout/diallog_audio_player.xml b/app/src/main/res/layout/diallog_audio_player.xml
new file mode 100644
index 0000000..cc55279
--- /dev/null
+++ b/app/src/main/res/layout/diallog_audio_player.xml
@@ -0,0 +1,207 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_hour_minute_picker.xml b/app/src/main/res/layout/dialog_hour_minute_picker.xml
new file mode 100644
index 0000000..238cf15
--- /dev/null
+++ b/app/src/main/res/layout/dialog_hour_minute_picker.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-xhdpi/ic_avatar_fycz.jpg b/app/src/main/res/mipmap-xhdpi/ic_avatar_fycz.jpg
new file mode 100644
index 0000000..d8233e8
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_avatar_fycz.jpg differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_read.png b/app/src/main/res/mipmap-xhdpi/ic_read.png
new file mode 100644
index 0000000..e74c6ee
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_read.png differ
diff --git a/app/src/main/res/raw/silent_sound.mp3 b/app/src/main/res/raw/silent_sound.mp3
new file mode 100644
index 0000000..ce236a2
Binary files /dev/null and b/app/src/main/res/raw/silent_sound.mp3 differ
diff --git a/release/output.json b/release/output.json
new file mode 100644
index 0000000..809e66c
--- /dev/null
+++ b/release/output.json
@@ -0,0 +1 @@
+[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":157,"versionName":"1.20.111211","enabled":true,"outputFile":"风月读书v1.20.111211.apk","fullName":"release","baseName":"release","dirName":""},"path":"风月读书v1.20.111211.apk","properties":{}}]
\ No newline at end of file
diff --git a/release/风月读书v1.20.111211.apk b/release/风月读书v1.20.111211.apk
new file mode 100644
index 0000000..ec65957
Binary files /dev/null and b/release/风月读书v1.20.111211.apk differ
diff --git a/splash/default_cover.jpg b/splash/default_cover.jpg
new file mode 100644
index 0000000..3515f68
Binary files /dev/null and b/splash/default_cover.jpg differ
diff --git a/splash/ic_launcher.png b/splash/ic_launcher.png
new file mode 100644
index 0000000..1c174be
Binary files /dev/null and b/splash/ic_launcher.png differ
diff --git a/splash/splash-new.jpg b/splash/splash-new.jpg
new file mode 100644
index 0000000..1d1e403
Binary files /dev/null and b/splash/splash-new.jpg differ
diff --git a/splash/splash-new.png b/splash/splash-new.png
new file mode 100644
index 0000000..d2b5ea0
Binary files /dev/null and b/splash/splash-new.png differ
diff --git a/splash/splash-感恩节.png b/splash/splash-感恩节.png
new file mode 100644
index 0000000..90c0379
Binary files /dev/null and b/splash/splash-感恩节.png differ
diff --git a/splash/splash-立冬.png b/splash/splash-立冬.png
new file mode 100644
index 0000000..2ac3d08
Binary files /dev/null and b/splash/splash-立冬.png differ