diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..c6cbe562a4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000000..c45be16cc8
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+MonkeyBook
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000000..96cc43efa6
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
new file mode 100644
index 0000000000..e7bedf3377
--- /dev/null
+++ b/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000000..97626ba454
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000000..444164129a
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000000..7158618b85
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.8
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000000..814aec0dce
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000000..7f68460d8b
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000000..796b96d1c4
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000000..98a9bfd53a
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,111 @@
+apply plugin: 'com.android.application'
+apply plugin: 'org.greenrobot.greendao'
+
+android {
+ compileSdkVersion 25
+ buildToolsVersion '25.0.0'
+
+ defaultConfig {
+ applicationId "com.monke.monkeybook"
+ minSdkVersion 17
+ targetSdkVersion 25
+ versionCode 6
+ versionName "1.2.1"
+ manifestPlaceholders = [UMENG_CHANNEL_VALUE: "debug"]
+ }
+
+ productFlavors{
+ baidu {
+ manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"]
+ }
+ pyger{
+ manifestPlaceholders = [UMENG_CHANNEL_VALUE: "pyger"]
+ }
+ }
+
+ signingConfigs {
+ config {
+ keyAlias 'monkeybook'
+ keyPassword 'zqh19931118'
+ storeFile file('D:/WorkSpace/Android/PersonalKey/Monke_keystore.jks')
+ storePassword 'zqh19931118'
+ }
+ }
+ lintOptions {
+ abortOnError false
+ }
+ buildTypes {
+ release {
+ buildConfigField "boolean", "IS_RELEASE", "true"
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ applicationVariants.all { variant ->
+ variant.outputs.each { output ->
+ def outputFile = output.outputFile
+ if (outputFile != null && outputFile.name.endsWith('.apk')) {
+ //这里修改apk文件名
+ def fileName = APP_NAME +"_"+"${variant.productFlavors[0].name}"+ "_v" + defaultConfig.versionName + "(" + defaultConfig.versionCode + ").apk"
+ output.outputFile = new File(outputFile.parent, fileName)
+ }
+ }
+ }
+ }
+ debug {
+ buildConfigField "boolean", "IS_RELEASE", "false"
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+// signingConfig signingConfigs.config
+ }
+ }
+}
+
+repositories{
+ flatDir{
+ dirs 'libs'
+ }
+}
+
+
+dependencies {
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+ testCompile 'junit:junit:4.12'
+ compile(name: 'autoupdatesdk-release', ext: 'aar')
+ compile 'com.android.support:appcompat-v7:25.1.0'
+ compile 'com.android.support:design:25.1.0'
+ compile 'com.android.support:cardview-v7:25.1.0'
+ compile 'com.android.support:support-compat:25.1.0'
+ compile project(':basemvplib')
+ //GreenDao
+ compile 'org.greenrobot:greendao:3.0.1'
+ compile 'org.greenrobot:greendao-generator:3.0.0'
+ //JSOUP
+ compile 'org.jsoup:jsoup:1.10.2'
+ //沉浸式状态栏
+ compile 'com.zhangmonke:ImmerseLayout:1.1.1'
+ //ProgressBar
+ compile 'com.zhangmonke:MProgressBar:1.0.1'
+ //Glide
+ compile 'com.github.bumptech.glide:glide:3.7.0'
+ //AutofitTextView
+ compile 'me.grantland:autofittextview:0.2.1'
+ //删除粒子效果
+ compile 'tyrantgit:explosionfield:1.0.1'
+ //View简易动画
+ compile 'com.daimajia.easing:library:2.0@aar'
+ compile 'com.daimajia.androidanimations:library:2.2@aar'
+ //CircleImageView
+ compile 'de.hdodenhof:circleimageview:2.1.0'
+ //SwitchButton
+ compile 'com.kyleduo.switchbutton:library:1.4.4'
+ compile 'com.victor:lib:1.0.4'
+ compile files('libs/commons-codec-1.10-sources.jar')
+ compile files('libs/juniversalchardet-1.0.3.jar')
+ compile files('libs/umeng-analytics-v6.1.1.jar')
+ compile files('libs/utdid4all-1.0.4.jar')
+}
+
+greendao {
+ schemaVersion 1
+ daoPackage 'com.monke.monkeybook.dao'
+ targetGenDir 'src/main/java'
+}
diff --git a/app/libs/autoupdatesdk-release.aar b/app/libs/autoupdatesdk-release.aar
new file mode 100644
index 0000000000..e6ae996d2f
Binary files /dev/null and b/app/libs/autoupdatesdk-release.aar differ
diff --git a/app/libs/commons-codec-1.10-sources.jar b/app/libs/commons-codec-1.10-sources.jar
new file mode 100644
index 0000000000..d7971c6bfe
Binary files /dev/null and b/app/libs/commons-codec-1.10-sources.jar differ
diff --git a/app/libs/juniversalchardet-1.0.3.jar b/app/libs/juniversalchardet-1.0.3.jar
new file mode 100644
index 0000000000..1af703fec5
Binary files /dev/null and b/app/libs/juniversalchardet-1.0.3.jar differ
diff --git a/app/libs/umeng-analytics-v6.1.1.jar b/app/libs/umeng-analytics-v6.1.1.jar
new file mode 100644
index 0000000000..76e618c23d
Binary files /dev/null and b/app/libs/umeng-analytics-v6.1.1.jar differ
diff --git a/app/libs/utdid4all-1.0.4.jar b/app/libs/utdid4all-1.0.4.jar
new file mode 100644
index 0000000000..34815c3497
Binary files /dev/null and b/app/libs/utdid4all-1.0.4.jar differ
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000000..d9aaa87b4c
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,206 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in D:\CodeTool\Android\Android_SDK/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+#
+# 对于一些基本指令的添加
+#
+#############################################
+# 代码混淆压缩比,在0~7之间,默认为5,一般不做修改
+-optimizationpasses 5
+
+# 混合时不使用大小写混合,混合后的类名为小写
+-dontusemixedcaseclassnames
+
+# 指定不去忽略非公共库的类
+-dontskipnonpubliclibraryclasses
+
+# 这句话能够使我们的项目混淆后产生映射文件
+# 包含有类名->混淆后类名的映射关系
+-verbose
+
+# 指定不去忽略非公共库的类成员
+-dontskipnonpubliclibraryclassmembers
+
+# 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。
+-dontpreverify
+
+# 保留Annotation不混淆
+-keepattributes *Annotation*,InnerClasses
+
+# 避免混淆泛型
+-keepattributes Signature
+
+# 抛出异常时保留代码行号
+-keepattributes SourceFile,LineNumberTable
+
+# 指定混淆是采用的算法,后面的参数是一个过滤器
+# 这个过滤器是谷歌推荐的算法,一般不做更改
+-optimizations !code/simplification/cast,!field/*,!class/merging/*
+
+
+#############################################
+#
+# Android开发中一些需要保留的公共部分
+#
+#############################################
+
+# 保留我们使用的四大组件,自定义的Application等等这些类不被混淆
+# 因为这些子类都有可能被外部调用
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Appliction
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class * extends android.view.View
+-keep public class com.android.vending.licensing.ILicensingService
+
+
+# 保留support下的所有类及其内部类
+-keep class android.support.** {*;}
+
+# 保留继承的
+-keep public class * extends android.support.v4.**
+-keep public class * extends android.support.v7.**
+-keep public class * extends android.support.annotation.**
+
+# 保留R下面的资源
+-keep class **.R$* {*;}
+
+# 保留本地native方法不被混淆
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+# 保留在Activity中的方法参数是view的方法,
+# 这样以来我们在layout中写的onClick就不会被影响
+-keepclassmembers class * extends android.app.Activity{
+ public void *(android.view.View);
+}
+
+# 保留枚举类不被混淆
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+# 保留我们自定义控件(继承自View)不被混淆
+-keep public class * extends android.view.View{
+ *** get*();
+ void set*(***);
+ public (android.content.Context);
+ public (android.content.Context, android.util.AttributeSet);
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+# 保留Parcelable序列化类不被混淆
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
+
+# 保留Serializable序列化的类不被混淆
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ private static final java.io.ObjectStreamField[] serialPersistentFields;
+ !static !transient ;
+ !private ;
+ !private ;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+
+# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆
+-keepclassmembers class * {
+ void *(**On*Event);
+ void *(**On*Listener);
+}
+
+# webView处理,项目中没有使用到webView忽略即可
+-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+ public *;
+}
+-keepclassmembers class * extends android.webkit.webViewClient {
+ public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
+ public boolean *(android.webkit.WebView, java.lang.String);
+}
+-keepclassmembers class * extends android.webkit.webViewClient {
+ public void *(android.webkit.webView, jav.lang.String);
+}
+
+# 移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用
+# 记得proguard-android.txt中一定不要加-dontoptimize才起作用
+# 另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制
+#-assumenosideeffects class android.util.Log {
+# public static int v(...);
+# public static int i(...);
+# public static int w(...);
+# public static int d(...);
+# public static int e(...);
+#}
+
+### greenDAO 3
+-keep class org.greenrobot.greendao.**{ *; }
+-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
+public static java.lang.String TABLENAME;
+}
+-keep class **$Properties
+-dontwarn org.greenrobot.greendao.database.**
+-dontwarn rx.**
+
+-dontwarn okio.**
+-dontwarn retrofit2.**
+-dontwarn javax.annotation.**
+-keep class retrofit2.**{*;}
+-keep class okhttp3.**{*;}
+-keep class okio.**{*;}
+-keep class com.hwangjr.rxbus.**{*;}
+-dontwarn org.apache.log4j.lf5.viewer.**
+-dontnote org.apache.log4j.lf5.viewer.**
+-dontwarn freemarker.**
+-dontnote org.python.core.**
+-dontwarn com.hwangjr.rxbus.**
+
+-keep class com.monke.monkeybook.widget.**{*;}
+-keep class com.monke.monkeybook.bean.**{*;}
+-keep class android.support.**{*;}
+-keep class me.grantland.widget.**{*;}
+-keep class de.hdodenhof.circleimageview.**{*;}
+-keep class retrofit2.**{*;}
+-keep class tyrant.explosionfield.**{*;}
+-keep class tyrantgit.explosionfield.**{*;}
+-keep class freemarker.**{*;}
+##JSOUP
+-keep class org.jsoup.**{ *; }
+-keep class com.monke.mprogressbar.**{ *; }
+
+##友盟统计
+-keepclassmembers class * {
+ public (org.json.JSONObject);
+}
+-keep public class com.monke.monkeybook.R$*{
+ public static final int *;
+}
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+##百度自动更新
+-keep class com.baidu.**{*;}
diff --git a/app/src/androidTest/java/com/monke/monkeybook/ApplicationTest.java b/app/src/androidTest/java/com/monke/monkeybook/ApplicationTest.java
new file mode 100644
index 0000000000..5fa3869c7d
--- /dev/null
+++ b/app/src/androidTest/java/com/monke/monkeybook/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.monke.monkeybook;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..530fef4372
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/monke/monkeybook/BitIntentDataManager.java b/app/src/main/java/com/monke/monkeybook/BitIntentDataManager.java
new file mode 100644
index 0000000000..9db86da2dc
--- /dev/null
+++ b/app/src/main/java/com/monke/monkeybook/BitIntentDataManager.java
@@ -0,0 +1,34 @@
+package com.monke.monkeybook;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class BitIntentDataManager {
+ public static Map bigData;
+
+ private static BitIntentDataManager instance = null;
+
+ public static BitIntentDataManager getInstance(){
+ if(instance == null){
+ synchronized (BitIntentDataManager.class){
+ if(instance == null){
+ instance = new BitIntentDataManager();
+ }
+ }
+ }
+ return instance;
+ }
+
+ private BitIntentDataManager(){
+ bigData = new HashMap<>();
+ }
+ public Object getData(String key){
+ return bigData.get(key);
+ }
+ public void putData(String key,Object data){
+ bigData.put(key,data);
+ }
+ public void cleanData(String key){
+ bigData.remove(key);
+ }
+}
diff --git a/app/src/main/java/com/monke/monkeybook/ErrorAnalyContentManager.java b/app/src/main/java/com/monke/monkeybook/ErrorAnalyContentManager.java
new file mode 100644
index 0000000000..e99adda161
--- /dev/null
+++ b/app/src/main/java/com/monke/monkeybook/ErrorAnalyContentManager.java
@@ -0,0 +1,124 @@
+package com.monke.monkeybook;
+
+import com.monke.monkeybook.base.observer.SimpleObserver;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import io.reactivex.Observable;
+import io.reactivex.ObservableEmitter;
+import io.reactivex.ObservableOnSubscribe;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.schedulers.Schedulers;
+
+public class ErrorAnalyContentManager {
+ private ErrorAnalyContentManager(){
+
+ }
+ private static ErrorAnalyContentManager instance;
+
+ public static ErrorAnalyContentManager getInstance(){
+ if(instance == null){
+ synchronized (ErrorAnalyContentManager.class){
+ if(instance == null){
+ instance = new ErrorAnalyContentManager();
+ }
+ }
+ }
+ return instance;
+ }
+
+ public void writeNewErrorUrl(final String url){
+ Observable.create(new ObservableOnSubscribe() {
+ @Override
+ public void subscribe(ObservableEmitter e) throws Exception {
+ String filePath = MApplication.getInstance().getExternalFilesDir("").getPath();
+ File dir = new File(filePath);
+ if(!dir.exists()){
+ dir.mkdirs();
+ }
+
+ File file2 = new File(filePath,"ErrorAnalyUrlsDetail.txt");
+ if(!file2.exists()) {
+ file2.createNewFile();
+ }
+ FileOutputStream fileOutputStream2 = new FileOutputStream(file2,true);
+ fileOutputStream2.write((url+" \r\n").getBytes());
+ fileOutputStream2.flush();
+ fileOutputStream2.close();
+ ///////////////////////////////////////////////////////////////////////
+ File file1 = new File(filePath,"ErrorAnalyUrls.txt");
+ if(!file1.exists()) {
+ file1.createNewFile();
+ }
+ FileInputStream inputStream = new FileInputStream(file1);
+ byte[] bytes = new byte[1024];
+ ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
+ while (inputStream.read(bytes) != -1) {
+ arrayOutputStream.write(bytes, 0, bytes.length);
+ }
+ inputStream.close();
+ arrayOutputStream.close();
+ String content = new String(arrayOutputStream.toByteArray());
+ if(!content.contains(url.substring(0,url.indexOf('/',8)))){
+ FileOutputStream fileOutputStream1 = new FileOutputStream(file1,true);
+ fileOutputStream1.write((url.substring(0,url.indexOf('/',8))+" \r\n").getBytes());
+ fileOutputStream1.flush();
+ fileOutputStream1.close();
+ }
+ e.onNext(true);
+ e.onComplete();
+ }
+ })
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new SimpleObserver() {
+ @Override
+ public void onNext(Boolean value) {
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+
+ }
+ });
+ }
+
+ public void writeMayByNetError(final String url){
+ Observable.create(new ObservableOnSubscribe() {
+ @Override
+ public void subscribe(ObservableEmitter e) throws Exception {
+ String filePath = MApplication.getInstance().getExternalFilesDir("").getPath();
+ File dir = new File(filePath);
+ if(!dir.exists()){
+ dir.mkdirs();
+ }
+
+ File file = new File(filePath,"ErrorNetUrl.txt");
+ if(!file.exists()) {
+ file.createNewFile();
+ }
+ FileOutputStream fileOutputStream2 = new FileOutputStream(file,true);
+ fileOutputStream2.write((url+" \r\n").getBytes());
+ fileOutputStream2.flush();
+ fileOutputStream2.close();
+ e.onNext(true);
+ e.onComplete();
+ }
+ })
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new SimpleObserver() {
+ @Override
+ public void onNext(Boolean value) {
+
+ }
+
+ @Override
+ public void onError(Throwable e) {
+
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/monke/monkeybook/MApplication.java b/app/src/main/java/com/monke/monkeybook/MApplication.java
new file mode 100644
index 0000000000..01c891111f
--- /dev/null
+++ b/app/src/main/java/com/monke/monkeybook/MApplication.java
@@ -0,0 +1,38 @@
+package com.monke.monkeybook;
+
+import android.app.Application;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.widget.Toast;
+
+import com.monke.monkeybook.service.DownloadService;
+import com.umeng.analytics.MobclickAgent;
+
+public class MApplication extends Application {
+
+ private static MApplication instance;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ if (BuildConfig.IS_RELEASE) {
+ String channel = "debug";
+ try {
+ ApplicationInfo appInfo = getPackageManager()
+ .getApplicationInfo(getPackageName(),
+ PackageManager.GET_META_DATA);
+ channel = appInfo.metaData.getString("UMENG_CHANNEL_VALUE");
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ MobclickAgent.startWithConfigure(new MobclickAgent.UMAnalyticsConfig(this, getString(R.string.umeng_key), channel, MobclickAgent.EScenarioType.E_UM_NORMAL, true));
+ }
+ instance = this;
+ startService(new Intent(this, DownloadService.class));
+ }
+
+ public static MApplication getInstance() {
+ return instance;
+ }
+}
diff --git a/app/src/main/java/com/monke/monkeybook/ReadBookControl.java b/app/src/main/java/com/monke/monkeybook/ReadBookControl.java
new file mode 100644
index 0000000000..c7f4412e1d
--- /dev/null
+++ b/app/src/main/java/com/monke/monkeybook/ReadBookControl.java
@@ -0,0 +1,176 @@
+package com.monke.monkeybook;
+
+import android.content.SharedPreferences;
+import android.graphics.Color;
+import com.monke.monkeybook.utils.DensityUtil;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ReadBookControl {
+ public static final int DEFAULT_TEXT = 2;
+ public static final int DEFAULT_BG = 1;
+
+ private static List