diff --git a/202014040130tangjiefeng_Reader/.idea/.gitignore b/202014040130tangjiefeng_Reader/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/202014040130tangjiefeng_Reader/.idea/compiler.xml b/202014040130tangjiefeng_Reader/.idea/compiler.xml
new file mode 100644
index 0000000..fb7f4a8
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/.idea/dbnavigator.xml b/202014040130tangjiefeng_Reader/.idea/dbnavigator.xml
new file mode 100644
index 0000000..70f212e
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/.idea/dbnavigator.xml
@@ -0,0 +1,414 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/.idea/gradle.xml b/202014040130tangjiefeng_Reader/.idea/gradle.xml
new file mode 100644
index 0000000..a2d7c21
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/.idea/jarRepositories.xml b/202014040130tangjiefeng_Reader/.idea/jarRepositories.xml
new file mode 100644
index 0000000..7d192c5
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/.idea/misc.xml b/202014040130tangjiefeng_Reader/.idea/misc.xml
new file mode 100644
index 0000000..bdd9278
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/AAD b/202014040130tangjiefeng_Reader/AAD
new file mode 160000
index 0000000..aec645b
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/AAD
@@ -0,0 +1 @@
+Subproject commit aec645b6d670e75be67c525ebe11c562f66ff1f7
diff --git a/202014040130tangjiefeng_Reader/NovelReader.plantuml b/202014040130tangjiefeng_Reader/NovelReader.plantuml
new file mode 100644
index 0000000..87efd16
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/NovelReader.plantuml
@@ -0,0 +1,29 @@
+@startuml
+
+title __NOVELREADER's Component Diagram__\n
+
+ component "NovelReader.app.unitTest" {
+ [NovelReader.app.main]
+ component "NovelReader.app.main" {
+ [NovelReader.app.androidTest]
+ component "NovelReader.app.androidTest" {
+ [NovelReader.app]
+ }
+
+
+ }
+
+
+ }
+
+
+
+
+right footer
+
+
+PlantUML diagram generated by SketchIt! (https://bitbucket.org/pmesmeur/sketch.it)
+For more information about this tool, please contact philippe.mesmeur@gmail.com
+endfooter
+
+@enduml
diff --git a/202014040130tangjiefeng_Reader/app/build.gradle b/202014040130tangjiefeng_Reader/app/build.gradle
new file mode 100644
index 0000000..fe8d4b9
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/build.gradle
@@ -0,0 +1,41 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 28
+ defaultConfig {
+ applicationId "fte.finalproject"
+ minSdkVersion 22
+ targetSdkVersion 28
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'com.android.support:appcompat-v7:28.0.0'
+ implementation 'com.android.support.constraint:constraint-layout:1.1.3'
+ implementation 'com.android.support:cardview-v7:28.0.0'
+ implementation 'com.android.support:recyclerview-v7:28.0.0'
+ implementation 'de.hdodenhof:circleimageview:2.2.0'
+ implementation 'com.android.support:cardview-v7:28.0.0'
+ implementation 'com.squareup.retrofit2:retrofit:2.0.2'
+ implementation 'com.squareup.retrofit2:converter-scalars:2.0.0'
+ implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
+ implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
+ implementation 'io.reactivex:rxandroid:1.2.1'
+ implementation 'io.reactivex:rxjava:1.2.1'
+ implementation 'com.squareup.okhttp3:okhttp:3.2.0'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'com.android.support.test:runner:1.0.2'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+ implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
+ implementation 'io.reactivex.rxjava2:rxjava:2.1.0'
+}
diff --git a/202014040130tangjiefeng_Reader/app/proguard-rules.pro b/202014040130tangjiefeng_Reader/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# 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 *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/202014040130tangjiefeng_Reader/app/release/output.json b/202014040130tangjiefeng_Reader/app/release/output.json
new file mode 100644
index 0000000..9f0c959
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/release/output.json
@@ -0,0 +1 @@
+[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/androidTest/java/com/example/ExampleInstrumentedTest.java b/202014040130tangjiefeng_Reader/app/src/androidTest/java/com/example/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..d6fcbc7
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/androidTest/java/com/example/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.example;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * 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.getTargetContext();
+
+ assertEquals("fte.finalproject", appContext.getPackageName());
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/AndroidManifest.xml b/202014040130tangjiefeng_Reader/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..351cb93
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/AndroidManifest.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/BookDetailActivity.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/BookDetailActivity.java
new file mode 100644
index 0000000..174a7c8
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/BookDetailActivity.java
@@ -0,0 +1,409 @@
+package com.example.Activity;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Handler;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import com.example.DataBase.DatabaseControl;
+import com.example.Object.BookObj;
+import com.example.Object.CategoryObj;
+import com.example.Object.ChapterLinkObj;
+import com.example.Object.RecomListObj;
+import com.example.Object.ShelfBookObj;
+import com.example.R;
+import com.example.Service.BookService;
+
+public class BookDetailActivity extends AppCompatActivity {
+
+ RadioButton addButton;
+ RadioButton readButton;
+// RadioButton downloadButton;
+ Button moreButton;
+ Button recom1;
+ Button recom2;
+ Button recom3;
+
+ ImageView back;
+ TextView pageTitle;
+ ImageView bookCover;
+ TextView bookTitle;
+ TextView bookInfo;
+ TextView updateTime;
+ TextView follower;
+ TextView retentionRatio;
+ TextView bookIntro;
+ RadioGroup recomRG;
+
+ // 书籍对象
+ private BookObj bookObj;
+
+ // 同类书籍
+ private CategoryObj categoryObj;
+
+ private List bookObjs = new ArrayList<>();
+
+ private Bitmap cover;
+
+ private List linkList;
+
+ private StringBuilder stringBuilder = new StringBuilder();
+
+ Handler mHandler = new Handler();
+
+ private SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-mm'T'HH:MM:SS");
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_book_detail);
+
+ // 获取控件
+ back = findViewById(R.id.detail_back);
+ pageTitle = findViewById(R.id.detail_title);
+ addButton = findViewById(R.id.detail_bottom_add);
+ readButton = findViewById(R.id.detail_bottom_read);
+// downloadButton = findViewById(R.id.detail_bottom_download);
+ moreButton = findViewById(R.id.detail_more);
+ bookCover = findViewById(R.id.detail_cover);
+ bookTitle = findViewById(R.id.detail_bookTitle);
+ bookInfo = findViewById(R.id.detail_TV);
+ updateTime = findViewById(R.id.detail_update);
+ follower = findViewById(R.id.detail_follower2);
+ retentionRatio = findViewById(R.id.detail_retentionRatio2);
+ bookIntro = findViewById(R.id.detail_longIntro);
+ recomRG = findViewById(R.id.detail_recomRG);
+ recom1 = findViewById(R.id.detail_recom1);
+ recom2 = findViewById(R.id.detail_recom2);
+ recom3 = findViewById(R.id.detail_recom3);
+
+ Intent intent = getIntent();
+ final Bundle bundle = intent.getExtras();
+ bookObj = (BookObj) bundle.getSerializable("bookobj");
+
+ // 获取封面图片
+ final String iconURL = BookService.StaticsUrl + bookObj.getCover();
+ final Matrix largeMatrix = new Matrix();
+ final Matrix littleMatrix = new Matrix();
+ largeMatrix.postScale((float) 2, (float) 2);
+ littleMatrix.postScale((float) 0.4, (float) 0.4);
+
+ if (!isNetWorkConnected(BookDetailActivity.this)) {
+ Toast.makeText(BookDetailActivity.this, "未连接网络", Toast.LENGTH_SHORT).show();
+ } else {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ URL url = new URL(iconURL);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setConnectTimeout(10000);
+ if (connection.getResponseCode() == 200) {
+ InputStream inputStream = connection.getInputStream();
+ cover = BitmapFactory.decodeStream(inputStream);
+ if (cover != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ Log.d("width", String.valueOf(cover.getWidth()));
+ Log.d("height", String.valueOf(cover.getHeight()));
+ littleMatrix.postScale((float) 0.5, (float) 0.5);
+ }
+ });
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }).start();
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ URL url = new URL(iconURL);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setConnectTimeout(10000);
+ if (connection.getResponseCode() == 200) {
+ InputStream inputStream = connection.getInputStream();
+ cover = BitmapFactory.decodeStream(inputStream);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ Log.d("width", String.valueOf(cover.getWidth()));
+ Log.d("height", String.valueOf(cover.getHeight()));
+ /*if (cover.getWidth() <= 150 && cover.getHeight() <= 200) {
+ bookCover.setImageBitmap(Bitmap.createBitmap(cover, 0, 0, cover.getWidth(), cover.getHeight(), largeMatrix, true));
+ } else if (cover.getWidth() > 300 && cover.getHeight() > 400) {
+ bookCover.setImageBitmap(Bitmap.createBitmap(cover, 0, 0, cover.getWidth(), cover.getHeight(), littleMatrix, true));
+ } else {
+ bookCover.setImageBitmap(cover);
+ }*/
+ bookCover.setImageBitmap(cover);
+ }
+ });
+ bookCover.setImageBitmap(cover);
+ }
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ }
+ }
+ }).start();
+
+ if (!isNetWorkConnected(BookDetailActivity.this)) {
+ Toast.makeText(BookDetailActivity.this, "未连接网络", Toast.LENGTH_SHORT).show();
+ } else {
+ // 获取书籍相关信息
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ bookObj = BookService.getBookService().getBookById(bookObj.getId());
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ bookTitle.setText(bookObj.getTitle());
+ pageTitle.setText(bookObj.getTitle());
+ int wordNum = bookObj.getWordCount() / 10000;
+ bookInfo.setText(bookObj.getAuthor() + " | " + bookObj.getMinorCate() + " | " + String.valueOf(wordNum) + "万字");
+ String updateStr = "";
+ try {
+ Date date = format.parse(bookObj.getUpdated());
+ Date now = new Date(System.currentTimeMillis());
+ long period = now.getTime() - date.getTime();
+ Log.d("period", String.valueOf(period));
+ if (period / 86400000 < 1) {
+ updateStr = "上次更新: 今天";
+ } else if (period / 86400000 > 1) {
+ updateStr = "上次更新: " + String.valueOf(period / 86400000) + "天前";
+ }
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ updateTime.setText(updateStr);
+ // int followerNum = bookObj.getLatelyFollower() / 10000;
+ follower.setText(String.valueOf(bookObj.getLatelyFollower()) + "人");
+ retentionRatio.setText(bookObj.getRetentionRatio() + "%");
+ String intro = bookObj.getLongIntro();
+ if (intro.length() > 80) intro = intro.substring(0, 80);
+ intro += "...";
+ bookIntro.setText(intro);
+
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ categoryObj = BookService.getBookService().getBooksByCategoty("reputation", bookObj.getMajorCate(), 0, 10, bookObj.getGender()[0]);
+ Log.d("size", String.valueOf(categoryObj.getBooks().size()));
+ for (int i = 0; i < categoryObj.getBooks().size(); i++) {
+ final int j = i;
+ final BookObj temp = BookService.getBookService().getBookById(categoryObj.getBooks().get(j).getId());
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ bookObjs.add(temp);
+ if (j < 3) {
+ final String iconURL = BookService.StaticsUrl + temp.getCover();
+ final Button button = (Button) recomRG.getChildAt(j);
+ button.setText(bookObjs.get(j).getTitle());
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ URL url = new URL(iconURL);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setConnectTimeout(10000);
+ if (connection.getResponseCode() == 200) {
+ InputStream inputStream = connection.getInputStream();
+ final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ Drawable drawable = null;
+ drawable = new BitmapDrawable(Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), littleMatrix, true));
+ drawable.setBounds(0, 0, 270, 360);
+ button.setCompoundDrawables(null, drawable, null, null);
+ }
+ });
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }).start();
+ }
+ }
+ });
+
+
+ }
+ }
+ }).start();
+ }
+ });
+ }
+ }).start();
+ }
+
+ recom1.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(BookDetailActivity.this, BookDetailActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putSerializable("bookobj", bookObjs.get(0));
+ intent.putExtras(bundle);
+ startActivity(intent);
+ }
+ });
+
+ recom2.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(BookDetailActivity.this, BookDetailActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putSerializable("bookobj", bookObjs.get(1));
+ intent.putExtras(bundle);
+ startActivity(intent);
+ }
+ });
+
+ recom3.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(BookDetailActivity.this, BookDetailActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putSerializable("bookobj", bookObjs.get(2));
+ intent.putExtras(bundle);
+ startActivity(intent);
+ }
+ });
+
+ // 返回
+ back.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ });
+
+ if (DatabaseControl.getInstance(BookDetailActivity.this).judgeBookExist(bookObj.getId())) {
+ // 已存在
+ setButtonToDelete();
+ } else {
+ // 不存在
+ setButtonToAdd();
+ }
+
+ // 阅读
+ readButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(BookDetailActivity.this, ReadPageActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putString("bookid", bookObj.getId());
+ intent.putExtras(bundle);
+ startActivity(intent);
+ }
+ });
+
+ // 下载
+ /*downloadButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ *//*new Thread(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = 0; i < linkList.size(); i++) {
+ ChapterObj chapterObj = BookService.getBookService().getChapterByLink(linkList.get(i).getLink());
+ stringBuilder.append(chapterObj.getIchapter().getTitle());
+ stringBuilder.append("\n");
+ stringBuilder.append(chapterObj.getIchapter().getBody());
+ }
+
+ }
+ }).start();*//*
+ Toast.makeText(BookDetailActivity.this, "功能开发中,敬请期待", Toast.LENGTH_SHORT).show();
+ }
+ });*/
+
+ // 查看更多同类书籍
+ moreButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(BookDetailActivity.this, RecomActivity.class);
+ Bundle bundle = new Bundle();
+ RecomListObj recomListObj = new RecomListObj(bookObjs);
+ bundle.putSerializable("list", recomListObj);
+ intent.putExtras(bundle);
+ startActivity(intent);
+ }
+ });
+ }
+ }
+
+ private void setButtonToAdd() {
+ addButton.setText("加入书架");
+ addButton.setTextColor(getResources().getColor(R.color.colorRed));
+ addButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ DatabaseControl.getInstance(BookDetailActivity.this).addShelfBook(new ShelfBookObj(bookObj.getId(), bookObj.getTitle(), cover, bookObj.getCover(),0, "online", 0, bookObj.getLongIntro(), bookObj.getAuthor(), bookObj.getMajorCate()));
+ Toast.makeText(BookDetailActivity.this, "已添加《" + bookObj.getTitle() + "》", Toast.LENGTH_SHORT).show();
+ setButtonToDelete();
+ }
+ });
+ }
+
+ private void setButtonToDelete() {
+ addButton.setText("移除书架");
+ addButton.setTextColor(getResources().getColor(R.color.colorGrey));
+ addButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ DatabaseControl.getInstance(BookDetailActivity.this).deleteShelfBook(bookObj.getId());
+ Toast.makeText(BookDetailActivity.this, "已移除《" + bookObj.getTitle() + "》", Toast.LENGTH_SHORT).show();
+ setButtonToAdd();
+ }
+ });
+ }
+
+ // 辅助函数:判断网络是否连接
+ private boolean isNetWorkConnected(Context context) {
+ if (context != null) {
+ ConnectivityManager mConnectivityManager = (ConnectivityManager) context
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
+ if (mNetworkInfo != null) {
+ return mNetworkInfo.isConnected();
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/CategoryActivity.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/CategoryActivity.java
new file mode 100644
index 0000000..1995587
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/CategoryActivity.java
@@ -0,0 +1,171 @@
+package com.example.Activity;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.view.ViewPager;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.example.Fragment.DetailCategoryFragment;
+import com.example.Fragment.TabFragmentPagerAdapter;
+import com.example.R;
+
+//这个Activity可用于榜单和具体分类
+public class CategoryActivity extends AppCompatActivity {
+ private boolean isRanking; //排行榜/分类
+ private boolean isMale; //男生/女生
+
+ private TextView title;
+ private ImageView backImage;
+
+ private RadioGroup RG;
+ private RadioButton RB1;
+ private RadioButton RB2;
+ private RadioButton RB3;
+ private RadioButton RB4;
+
+ private ViewPager viewPager;
+ private List fragmentList = new ArrayList<>();
+ private TabFragmentPagerAdapter pagerAdapter;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_category);
+ //获取传递的参数
+ Bundle bundle = this.getIntent().getExtras();
+ isRanking = bundle.getBoolean("isRanking");
+ isMale = bundle.getBoolean("isMale");
+
+ //初始化控件
+ title = findViewById(R.id.category_activity_title);
+ backImage = findViewById(R.id.category_activity_back);
+ RG = findViewById(R.id.category_activity_RG);
+ RB1 = findViewById(R.id.category_activity_RB1);
+ RB2 = findViewById(R.id.category_activity_RB2);
+ RB3 = findViewById(R.id.category_activity_RB3);
+ RB4 = findViewById(R.id.category_activity_RB4);
+ viewPager = findViewById(R.id.category_activity_viewPager);
+
+ //设置显示内容
+ title.setText(bundle.getString("title"));
+ if (isRanking) {
+ RB1.setText("周榜");
+ RB2.setText("月榜");
+ RB3.setText("总榜");
+ RB4.setVisibility(View.GONE);
+ }
+ else {
+ RB1.setText("热门");
+ RB2.setText("新书");
+ RB3.setText("好评");
+ RB4.setVisibility(View.VISIBLE);
+ }
+
+ //设置返回事件
+ backImage.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onBackPressed();
+ }
+ });
+
+ //添加Fragment
+ if (isRanking) {
+ //排行榜的Fragment
+ for (int i = 0; i < 3; ++i) {
+ DetailCategoryFragment fragment = new DetailCategoryFragment();
+ Bundle bundle1 = new Bundle();
+ bundle1.putString("title", bundle.getString("title"));
+ bundle1.putBoolean("isRanking", isRanking);
+ bundle1.putBoolean("isMale", isMale);
+ if (i == 0) bundle1.putString("type", "周榜");
+ else if (i == 1) bundle1.putString("type", "月榜");
+ else bundle1.putString("type", "总榜");
+ fragment.setArguments(bundle1);
+ fragmentList.add(fragment);
+ }
+ }
+ else {
+ //具体分类的Fragment
+ for (int i = 0; i < 4; ++i) {
+ DetailCategoryFragment fragment = new DetailCategoryFragment();
+ Bundle bundle1 = new Bundle();
+ bundle1.putString("title", bundle.getString("title"));
+ bundle1.putBoolean("isRanking", isRanking);
+ bundle1.putBoolean("isMale", isMale);
+ if (i == 0) bundle1.putString("type", "热门");
+ else if (i == 1) bundle1.putString("type", "新书");
+ else if (i == 2) bundle1.putString("type", "好评");
+ else bundle1.putString("type", "完结");
+ fragment.setArguments(bundle1);
+ fragmentList.add(fragment);
+ }
+ }
+ viewPager.setOnPageChangeListener(new MyPagerChangeListener());
+ pagerAdapter = new TabFragmentPagerAdapter(getSupportFragmentManager(), fragmentList);
+ viewPager.setAdapter(pagerAdapter);
+ viewPager.setCurrentItem(0);
+ if (isRanking) viewPager.setOffscreenPageLimit(2);
+ else viewPager.setOffscreenPageLimit(3);
+
+ //设置RadioGroup响应事件
+ RG.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ switch (checkedId){
+ case R.id.category_activity_RB1:
+ viewPager.setCurrentItem(0);
+ break;
+ case R.id.category_activity_RB2:
+ viewPager.setCurrentItem(1);
+ break;
+ case R.id.category_activity_RB3:
+ viewPager.setCurrentItem(2);
+ break;
+ case R.id.category_activity_RB4:
+ viewPager.setCurrentItem(3);
+ break;
+ }
+ }
+ });
+
+ }
+
+ //设置一个ViewPager的监听事件,左右滑动ViewPager时进行处理
+ public class MyPagerChangeListener implements ViewPager.OnPageChangeListener {
+ @Override
+ public void onPageScrollStateChanged(int arg0) {
+ }
+
+ @Override
+ public void onPageScrolled(int arg0, float arg1, int arg2) {
+ }
+
+ @Override
+ public void onPageSelected(int arg0) {
+ switch (arg0) {
+ case 0:
+ RB1.setChecked(true);
+ break;
+ case 1:
+ RB2.setChecked(true);
+ break;
+ case 2:
+ RB3.setChecked(true);
+ break;
+ case 3:
+ RB4.setChecked(true);
+ break;
+ }
+ }
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/MainActivity.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/MainActivity.java
new file mode 100644
index 0000000..8b4622a
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/MainActivity.java
@@ -0,0 +1,228 @@
+package com.example.Activity;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.support.v4.app.Fragment;
+import android.support.v4.view.ViewPager;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.example.Fragment.BookShelfFragment;
+import com.example.Fragment.CategoryFragment;
+import com.example.Fragment.RankingFragment;
+import com.example.Fragment.TabFragmentStatePagerAdapter;
+import com.example.R;
+
+//总体界面,包含书架、排行榜、分类
+public class MainActivity extends AppCompatActivity {
+ private RadioGroup radioGroup;
+ private TextView title;
+ private ImageView search;
+
+ private RadioGroup bottomRG;
+ private RadioButton bookshelfRB;
+ private RadioButton rankingRB;
+ private RadioButton categoryRB;
+
+ private RadioGroup topRG;
+ private RadioButton maleRB;
+ private RadioButton femaleRB;
+ private static Context context = null;
+
+ private ViewPager viewPager;
+ private List fragmentList = new ArrayList<>();
+ private TabFragmentStatePagerAdapter fragmentPagerAdapter;
+
+ public static Context getContext() {
+ return context;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ context = this.getBaseContext();
+ //初始化控件
+ radioGroup = findViewById(R.id.main_top_RG);
+ title = findViewById(R.id.main_title);
+ search = findViewById(R.id.main_search);
+ bottomRG = findViewById(R.id.main_bottomRG);
+ bookshelfRB = findViewById(R.id.main_bottom_bookshelf);
+ rankingRB = findViewById(R.id.main_bottom_ranking);
+ categoryRB = findViewById(R.id.main_bottom_category);
+ topRG = findViewById(R.id.main_top_RG);
+ maleRB = findViewById(R.id.main_top_male);
+ femaleRB = findViewById(R.id.main_top_female);
+ viewPager = findViewById(R.id.main_viewPager);
+
+ //初始化Fragment
+ BookShelfFragment bookShelfFragment = new BookShelfFragment();
+ RankingFragment rankingFragment = new RankingFragment();
+ Bundle bundle = new Bundle();
+ bundle.putBoolean("isMale", true);
+ rankingFragment.setArguments(bundle);
+ CategoryFragment categoryFragment = new CategoryFragment();
+ fragmentList.add(bookShelfFragment);
+ fragmentList.add(rankingFragment);
+ fragmentList.add(categoryFragment);
+
+ viewPager.setOnPageChangeListener(new MyPagerChangeListener());
+ fragmentPagerAdapter = new TabFragmentStatePagerAdapter(getSupportFragmentManager(), fragmentList);
+ viewPager.setAdapter(fragmentPagerAdapter);
+ viewPager.setCurrentItem(0);
+ viewPager.setOffscreenPageLimit(2);
+
+ //设置底部按钮图标大小
+ Drawable drawable = getResources().getDrawable(R.mipmap.bookshelf_red);
+ drawable.setBounds(0, 0, 70, 70);
+ bookshelfRB.setCompoundDrawables(null, drawable , null,null);
+ drawable = getResources().getDrawable(R.mipmap.ranking);
+ drawable.setBounds(0, 0, 70, 70);
+ rankingRB.setCompoundDrawables(null, drawable, null,null);
+ drawable = getResources().getDrawable(R.mipmap.category);
+ drawable.setBounds(0, 0, 70, 70);
+ categoryRB.setCompoundDrawables(null, drawable,null, null);
+
+ //设置顶部按钮图标大小
+ drawable = getResources().getDrawable(R.mipmap.male_blue);
+ drawable.setBounds(0, 0, 70, 70);
+ maleRB.setCompoundDrawables(null, drawable, null, null);
+ drawable = getResources().getDrawable(R.mipmap.female_black);
+ drawable.setBounds(0, 0, 70, 70);
+ femaleRB.setCompoundDrawables(null, drawable, null, null);
+
+ //处理顶部RG事件
+ topRG.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ switch (checkedId) {
+ case R.id.main_top_male:
+ Drawable drawable = getResources().getDrawable(R.mipmap.male_blue);
+ drawable.setBounds(0, 0, 70, 70);
+ maleRB.setCompoundDrawables(null, drawable, null, null);
+ drawable = getResources().getDrawable(R.mipmap.female_black);
+ drawable.setBounds(0, 0, 70, 70);
+ femaleRB.setCompoundDrawables(null, drawable, null, null);
+ RankingFragment rankingFragment1 = new RankingFragment();
+ Bundle bundle = new Bundle();
+ bundle.putBoolean("isMale", true);
+ rankingFragment1.setArguments(bundle);
+ fragmentList.set(1, rankingFragment1);
+ fragmentPagerAdapter.notifyDataSetChanged();
+ viewPager.setCurrentItem(1);
+ break;
+ case R.id.main_top_female:
+ drawable = getResources().getDrawable(R.mipmap.male_black);
+ drawable.setBounds(0, 0, 70, 70);
+ maleRB.setCompoundDrawables(null, drawable, null, null);
+ drawable = getResources().getDrawable(R.mipmap.female_red);
+ drawable.setBounds(0, 0, 70, 70);
+ femaleRB.setCompoundDrawables(null, drawable, null, null);
+ RankingFragment rankingFragment2 = new RankingFragment();
+ bundle = new Bundle();
+ bundle.putBoolean("isMale", false);
+ rankingFragment2.setArguments(bundle);
+ fragmentList.set(1, rankingFragment2);
+ fragmentPagerAdapter.notifyDataSetChanged();
+ viewPager.setCurrentItem(1);
+ break;
+ }
+ }
+ });
+
+ //处理底部RG事件
+ bottomRG.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ int index = 0;
+ switch (checkedId) {
+ case R.id.main_bottom_bookshelf:
+ index = 0;
+ Drawable drawable = getResources().getDrawable(R.mipmap.bookshelf_red);
+ drawable.setBounds(0, 0, 70, 70);
+ bookshelfRB.setCompoundDrawables(null, drawable , null,null);
+ drawable = getResources().getDrawable(R.mipmap.ranking);
+ drawable.setBounds(0, 0, 70, 70);
+ rankingRB.setCompoundDrawables(null, drawable, null,null);
+ drawable = getResources().getDrawable(R.mipmap.category);
+ drawable.setBounds(0, 0, 70, 70);
+ categoryRB.setCompoundDrawables(null, drawable,null, null);
+ break;
+ case R.id.main_bottom_ranking:
+ index = 1;
+ drawable = getResources().getDrawable(R.mipmap.bookshelf);
+ drawable.setBounds(0, 0, 70, 70);
+ bookshelfRB.setCompoundDrawables(null, drawable , null,null);
+ drawable = getResources().getDrawable(R.mipmap.ranking_red);
+ drawable.setBounds(0, 0, 70, 70);
+ rankingRB.setCompoundDrawables(null, drawable, null,null);
+ drawable = getResources().getDrawable(R.mipmap.category);
+ drawable.setBounds(0, 0, 70, 70);
+ categoryRB.setCompoundDrawables(null, drawable,null, null);
+ break;
+ case R.id.main_bottom_category:
+ index = 2;
+ drawable = getResources().getDrawable(R.mipmap.bookshelf);
+ drawable.setBounds(0, 0, 70, 70);
+ bookshelfRB.setCompoundDrawables(null, drawable , null,null);
+ drawable = getResources().getDrawable(R.mipmap.ranking);
+ drawable.setBounds(0, 0, 70, 70);
+ rankingRB.setCompoundDrawables(null, drawable, null,null);
+ drawable = getResources().getDrawable(R.mipmap.category_red);
+ drawable.setBounds(0, 0, 70, 70);
+ categoryRB.setCompoundDrawables(null, drawable,null, null);
+ break;
+ }
+ viewPager.setCurrentItem(index);
+ }
+ });
+
+ //搜索按钮点击事件
+ search.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ startActivity(new Intent(MainActivity.this, SearchActivity.class));
+ }
+ });
+
+ }
+
+ //设置一个ViewPager的监听事件,左右滑动ViewPager时进行处理
+ public class MyPagerChangeListener implements ViewPager.OnPageChangeListener {
+ @Override
+ public void onPageScrollStateChanged(int arg0) {
+ }
+ @Override
+ public void onPageScrolled(int arg0, float arg1, int arg2) {
+ }
+ @Override
+ public void onPageSelected(int arg0) {
+ switch (arg0) {
+ case 0:
+ title.setText("书架");
+ radioGroup.setVisibility(View.GONE);
+ bookshelfRB.setChecked(true);
+ break;
+ case 1:
+ title.setText("排行榜");
+ radioGroup.setVisibility(View.VISIBLE);
+ rankingRB.setChecked(true);
+ break;
+ case 2:
+ title.setText("分类");
+ radioGroup.setVisibility(View.GONE);
+ categoryRB.setChecked(true);
+ break;
+ }
+ }
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/ReadPageActivity.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/ReadPageActivity.java
new file mode 100644
index 0000000..22fbc4c
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/ReadPageActivity.java
@@ -0,0 +1,1118 @@
+package com.example.Activity;
+
+import android.app.Dialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+import android.os.Looper;
+import android.support.v4.app.Fragment;
+import android.support.v4.view.ViewPager;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import com.example.Fragment.ReadPageFragment;
+import com.example.Fragment.TabFragmentStatePagerAdapter;
+import com.example.DataBase.DatabaseControl;
+import com.example.R;
+import com.example.RecyclerView.MyRecyclerViewAdapter;
+import com.example.RecyclerView.MyViewHolder;
+import com.example.Object.ChapterLinkObj;
+import com.example.Object.ChapterObj;
+import com.example.Object.CptListObj;
+import com.example.Object.UserStatusObj;
+import com.example.Service.BookService;
+import io.reactivex.Observable;
+import io.reactivex.ObservableEmitter;
+import io.reactivex.ObservableOnSubscribe;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.observers.DisposableObserver;
+import io.reactivex.schedulers.Schedulers;
+
+import static android.content.Intent.ACTION_TIME_TICK;
+
+
+public class ReadPageActivity extends AppCompatActivity {
+ private List fragmentList = new ArrayList<>(); //存储所有页面Fragment
+ private TabFragmentStatePagerAdapter fragmentAdapter;
+ private ViewPager viewPager;
+
+ private String bookid; // 书籍id
+ private String bookname; // 书籍名
+ private CptListObj cptListObj; //章节列表
+ List chapterLinks; // 章节查询链接List
+ List chapterObjs; // 章节内容OBJ队列
+ private int currChapter; //当前阅读到的章节 zero-based
+ List> chaptersContent; // 每一章每一页的内容
+ int totalChapter; // 该书总共的章节数
+ int cache_chapter_range_min; // 当前缓冲存储的章节数范围下界 zero-based
+ int cache_chapter_range_max; // 当前缓冲存储的章节数范围上界 zero-based
+
+ // 处理点击的坐标变量
+ private float DownX;
+ private float DownY;
+ private float UpX;
+ private float UpY;
+
+ // 页面控件处理
+ private RadioGroup rg_control;
+ private RadioButton day_and_night_rb_control;
+ private RadioButton horizontal_and_vertical_rb_control;
+ private RadioButton setting_rb_control;
+ //private RadioButton download_rb_control;
+ private RadioButton catalog_rb_control;
+ private ProgressBar progressBar;
+ private RelativeLayout bottom_layout_control;
+ private TextView battery_percent_control;
+ private TextView time_control;
+ private TextView read_page_process_control;
+ private RelativeLayout whole_layout_control;
+
+ // 屏幕宽高
+ float SCREEN_HEIGHT;
+ float SCREEN_WIDTH;
+
+ // 功能栏是否显示
+ boolean show_functional_button = false;
+
+ // 活动上下文
+ Context context;
+
+ // 广播
+ MyReceiver myReceiver;
+ IntentFilter intentFilter;
+
+ // 用户阅读状态
+ UserStatusObj userStatusObj;
+ boolean is_vertical_screen;
+ int day_or_night_status;
+ int textSize;
+
+ // 目录弹窗
+ MyRecyclerViewAdapter adapter;
+ List myCategory;
+
+ // 设置功能按钮是否可点击
+ boolean clickable = false;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_read_page);
+ System.out.println("onCreate创建");
+
+ //从传递的参数中获取章节相关信息
+ Intent intent = this.getIntent();
+ Bundle bundle = intent.getExtras();
+ bookid = bundle.getString("bookid");
+ bookname = bundle.getString("bookname");
+ currChapter = bundle.getInt("currentChapter");
+ //System.out.println("bookid: " + bookid + " currentChapter: " + currChapter);
+
+
+ // 获取页面控件
+ init_page_control();
+
+ // 设置用户阅读习惯状态与界面适配
+ set_Reading_Status();
+
+ // 获取页面宽高
+ get_screen_info();
+
+ // 注册底部信息栏的系统接收广播
+ init_info_broadcast();
+
+ // 设置功能按键
+ set_functional_button();
+
+ // 获取上下文
+ context = this;
+ // 全屏阅读,去除手机状态栏
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
+
+ // 初始化底部信息栏显示
+ init_bottom_info_layout();
+
+ //初始化 Fragment
+ init_fragment();
+ }
+
+ // 从数据库中获取用户的阅读习惯
+ private void set_Reading_Status() {
+ // 获取用户状态(默认用户状态)
+ userStatusObj = DatabaseControl.getInstance(this).get_User_Status_Obj(0);
+ // 获取默认用户下的横竖屏状态
+ int hor_or_ver_screen = userStatusObj.getHor_or_ver_screen();
+ //System.out.println("从数据库中获取到的横竖屏状态: " + hor_or_ver_screen);
+ if(hor_or_ver_screen == 1) {
+ is_vertical_screen = true;
+ System.out.println("新建Activity:数据库中是竖屏状态");
+ }
+ else {
+ is_vertical_screen = false;
+ System.out.println("新建Activity:数据库中是横屏状态");
+ // 切换成横屏
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ }
+
+ day_or_night_status = userStatusObj.getDay_or_night_status();
+ if(day_or_night_status == 1) whole_layout_control.setBackgroundColor(getResources().getColor(R.color.nightBackGround));
+
+ textSize = userStatusObj.getTextSize();
+ }
+
+ // 初始化底部信息栏显示
+ private void init_bottom_info_layout() {
+ // 设置当前时间
+ // 设置时间格式
+ SimpleDateFormat formatter = new SimpleDateFormat("HH:mm");
+ // 获取当前时间
+ Date curdate = new Date(System.currentTimeMillis());
+ // 按照格式将Date 时间转化成格式字符串
+ String time = formatter.format(curdate);
+ // UI设置显示
+ time_control.setText(time);
+ }
+
+ // 注册底部信息栏的系统接收广播
+ private void init_info_broadcast() {
+ //注册广播接受者java代码
+ intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); // 电量变化广播
+ intentFilter.addAction(ACTION_TIME_TICK);
+ //创建广播接受者对象
+ myReceiver = new MyReceiver();
+ //注册receiver
+ registerReceiver(myReceiver, intentFilter);
+ }
+
+ // 阅读帧初始化
+ private void init_fragment() {
+ // 设置等待进度条
+ progressBar.setVisibility(View.VISIBLE);
+ viewPager.setVisibility(View.GONE);
+ clickable = false;
+ // 清空当前的FragmentList
+ fragmentList.clear();
+ System.out.println("上次看到的章节数为:(zero-based)" + currChapter);
+ // 用线程进行帧初始化,避免进入阅读界面阻塞
+ Thread init_fragment_thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ // 判断是否联网了
+ Boolean isNetworkConnected = isNetWorkConnected(context);
+ // 未联网的响应处理
+ if(!isNetworkConnected) {
+ Looper.prepare();
+ // 弹出Toast提示
+ Toast.makeText(ReadPageActivity.this, "网络未连接,书籍获取失败", Toast.LENGTH_SHORT).show();
+ ReadPageActivity.this.finish();
+ Looper.loop();
+ // ProgressBar等待框消失
+ progressBar.setVisibility(View.GONE);
+ }
+ // 已经联网,获取书籍信息进行阅读
+ else {
+ //获取到:章节总页数totalPage、章节title、每页的内容content
+ Thread initContentThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ // 获取所有章节信息
+ cptListObj = BookService.getBookService().getChaptersByBookId(bookid);
+ if(cptListObj != null) {
+ chapterLinks = cptListObj.getImixToc().getChapterLinks();
+ totalChapter = chapterLinks.size();
+ System.out.println("共有章节数目: " + totalChapter);
+ /*for(int i = 0; i < chapterLinks.size(); i++) {
+ System.out.println(chapterLinks.get(i).getTitle() + ": " + chapterLinks.get(i).getLink());
+ }*/
+ chaptersContent = new ArrayList<>(totalChapter);
+
+ // 缓存当前章节以及上下10章的数据
+ chapterObjs = new ArrayList(totalChapter) {
+ };
+ cache_chapter_range_min = currChapter - 10;
+ cache_chapter_range_max = currChapter + 10;
+ for (int i = cache_chapter_range_min; i <= cache_chapter_range_max; i++) {
+ System.out.println("正在下载(zero-based): i---" + i + " min---" + cache_chapter_range_min + "---max---" + cache_chapter_range_max);
+ //超出章节范围
+ if (i > totalChapter - 1) {
+ //cache_chapter_range_max--;
+ cache_chapter_range_max = totalChapter - 1;
+ break;
+ //continue;
+ }
+ if (i < 0) {
+ cache_chapter_range_min++;
+ continue;
+ }
+ ChapterObj c = BookService.getBookService().getChapterByLink(chapterLinks.get(i).getLink());
+ //System.out.println(chapterLinks.get(i).getLink());
+ chapterObjs.add(i - cache_chapter_range_min, c);
+ //System.out.println(i);
+ }
+ System.out.println(cache_chapter_range_min + "----" + cache_chapter_range_max);
+ //System.out.println(chapterLinks.size());
+
+ //currentChapterContent.append(c.getIchapter().getBody());
+ //System.out.println(c.getIchapter().getTitle() + "\n" + c.getIchapter().getBody());
+ }
+ else {
+ Looper.prepare();
+ // 弹出Toast提示
+ Toast.makeText(ReadPageActivity.this, "无法获取书籍源", Toast.LENGTH_SHORT).show();
+ ReadPageActivity.this.finish();
+ Looper.loop();
+ }
+ }
+ });
+ initContentThread.start();
+
+ try {
+ initContentThread.join();
+ } catch (InterruptedException e) {
+ Log.d("[Error] ", "线程获取信息失败");
+ e.printStackTrace();
+ }
+
+ // 将章节内容分页
+ // 512字节长度一页
+ /*currTotalPage = content.length()/pageLen + 1;
+ System.out.println("分成了" + currTotalPage + "页");
+ List pages = getStrList(content, pageLen);
+ System.out.println("已经分割成: " + pages.size() + "页");
+ System.out.println(pages.get(0));*/
+
+ /*System.out.println("Test: ");
+ int len1 = "l".length();
+ int len2 = "好".length();
+ int len3 = ",".length();
+ int len4 = ",".length();
+ int len5 = "\n".length();
+ String test = "\u3000\u3000大漠。\r\n\u3000\u3000YES";
+ System.out.println(test);
+ int len6 = test.length();
+ System.out.println("长度:" + len1 + " " + len2 + " " + len3 + " " + len4 + " " + len5 + " " + len6);*/
+
+ // 根据内容适配各帧
+ int count =(cache_chapter_range_max-cache_chapter_range_min+1);
+ System.out.println(count);
+ for (int i = cache_chapter_range_min; i <= cache_chapter_range_max; ++i) {
+ // 解析章节内容
+ //String title = chapterObjs.get(0).getIchapter().getTitle(); // 这种获取Title的内容错误的(API问题)
+ String title = chapterLinks.get(i).getTitle();
+ String content;
+ if(chapterObjs.get(i-cache_chapter_range_min) == null) {
+ content = "章节获取失败了呢!客官";
+ }
+ else content = chapterObjs.get(i-cache_chapter_range_min).getIchapter().getBody();
+ // 为段首添加缩进
+ content = "\u3000\u3000" + content;
+ content = content.replaceAll("\n", "\n\u3000\u3000");
+ // 新建对应章节内容帧
+ ReadPageFragment fragment = new ReadPageFragment();
+ // 给帧传数据
+ Bundle bundle = new Bundle();
+ bundle.putString("title", title);
+ bundle.putString("content", content);
+ bundle.putInt("day_or_night_status", day_or_night_status);
+ bundle.putInt("textSize", textSize);
+ fragment.setArguments(bundle);
+ // 将新加的帧放入队列中
+ fragmentList.add(fragment);
+ }
+
+ viewPager.setOnPageChangeListener(new MyPagerChangeListener());
+ fragmentAdapter = new TabFragmentStatePagerAdapter(getSupportFragmentManager(), fragmentList);
+
+ // 用rxjava更新主线程
+ rxjava_update_page(0);
+
+ }
+ }
+ });
+ init_fragment_thread.start();
+
+ }
+
+ // 获取屏幕宽高等信息
+ private void get_screen_info() {
+ DisplayMetrics dm = getResources().getDisplayMetrics();
+ SCREEN_HEIGHT = dm.heightPixels;
+ SCREEN_WIDTH = dm.widthPixels;
+ /*String str = "屏幕宽高:" + SCREEN_WIDTH + ":" + SCREEN_HEIGHT;
+ Toast.makeText(ReadPageActivity.this, str, Toast.LENGTH_SHORT).show();*/
+ }
+
+ @Override
+ protected void onPause() {
+ System.out.println("onPause");
+ // 将阅读到的当前章节存入数据库
+ DatabaseControl.getInstance(this).updateProgress(currChapter, bookid);
+ // 将当前设置的用户习惯存入数据库(报错)
+ userStatusObj.setDay_or_night_status(day_or_night_status);
+ userStatusObj.setHor_or_ver_screen((is_vertical_screen?1:0));
+ userStatusObj.setTextSize(textSize);
+ DatabaseControl.getInstance(this).updateStatus(0,userStatusObj);
+ super.onPause();
+ }
+
+ @Override
+ protected void onDestroy() {
+ System.out.println("onDestroy");
+ System.out.println("横竖屏状况:" + ((is_vertical_screen) ? "竖屏":"横屏"));
+ // todo:注销广播
+ unregisterReceiver(myReceiver);
+ super.onDestroy();
+ }
+
+ // 屏幕点击处理
+ // 处理屏幕滑动翻页和点击中部弹出功能按键底框
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ if(!clickable) return false;
+ if (MotionEvent.ACTION_DOWN == event.getAction()) {
+ DownX = event.getX();
+ DownY = event.getY();
+ }
+ else if (MotionEvent.ACTION_UP == event.getAction()) {
+ UpX = event.getX();
+ UpY = event.getY();
+ }
+
+ // 滑动事件
+ if(Math.abs(UpX-DownX) > 10 || Math.abs(UpY-DownY)>10) {
+
+ }
+ // 点击事件
+ else {
+ System.out.println("点击位置:" + DownX + ":" + DownY);
+ System.out.println("屏幕宽高:" + SCREEN_WIDTH + " " + SCREEN_HEIGHT);
+ if (DownX > SCREEN_WIDTH / 3 && DownX < SCREEN_WIDTH * 2 / 3 && DownY > SCREEN_HEIGHT / 5 && DownY < SCREEN_HEIGHT * 4 / 5) {
+ if (show_functional_button) {
+ rg_control.setVisibility(View.GONE);
+ bottom_layout_control.setVisibility(View.VISIBLE);
+ show_functional_button = false;
+ } else {
+ bottom_layout_control.setVisibility(View.GONE);
+ rg_control.setVisibility(View.VISIBLE);
+ show_functional_button = true;
+ }
+
+ } /*else if (DownX <= SCREEN_WIDTH / 3) {
+ // todo:翻页有bug
+ Toast.makeText(ReadPageActivity.this, "向上翻页", Toast.LENGTH_SHORT).show();
+ System.out.println("当前阅读到的章节: " + (currChapter+1));
+ if(currChapter-1 >= cache_chapter_range_min)
+ viewPager.setCurrentItem((currChapter-1-cache_chapter_range_min), false);
+ } else {
+ // todo:翻页有bug
+ Toast.makeText(ReadPageActivity.this, "向下翻页", Toast.LENGTH_SHORT).show();
+ System.out.println("当前阅读到的章节:" + (currChapter+1));
+ if(currChapter+1 <= cache_chapter_range_max)
+ viewPager.setCurrentItem((currChapter+1-cache_chapter_range_min), false);
+ }*/
+ }
+
+
+ return super.dispatchTouchEvent(event);
+ }
+
+ // 设置功能按键
+ // 图标样式&&点击处理
+ private void set_functional_button() {
+ // 设置底部功能按钮的大小
+ Drawable drawable;
+ // 根据当前阅读日间/夜间模式设置图标
+
+ if(day_or_night_status == 0) {
+ drawable = getResources().getDrawable(R.mipmap.nighttime);
+ drawable.setBounds(0, 0, 70, 70);
+ day_and_night_rb_control.setCompoundDrawables(null, drawable, null, null);
+ day_and_night_rb_control.setText("夜间");
+ }
+ else {
+ drawable = getResources().getDrawable(R.mipmap.daytime);
+ drawable.setBounds(0, 0, 70, 70);
+ day_and_night_rb_control.setCompoundDrawables(null, drawable, null, null);
+ day_and_night_rb_control.setText("日间");
+ }
+ // 根据当前横竖屏状况设置图标
+ if(is_vertical_screen) {
+ drawable = getResources().getDrawable(R.mipmap.horizontal_screen);
+ drawable.setBounds(0, 0, 70, 70);
+ horizontal_and_vertical_rb_control.setCompoundDrawables(null, drawable, null,null);
+ horizontal_and_vertical_rb_control.setText("横屏");
+ horizontal_and_vertical_rb_control.setTextColor(Color.BLACK);
+ }
+ else {
+ drawable = getResources().getDrawable(R.mipmap.vertical_screen);
+ drawable.setBounds(0, 0, 70, 70);
+ horizontal_and_vertical_rb_control.setCompoundDrawables(null, drawable, null,null);
+ horizontal_and_vertical_rb_control.setText("竖屏");
+ horizontal_and_vertical_rb_control.setTextColor(Color.BLACK);
+ }
+ drawable = getResources().getDrawable(R.mipmap.textsize);
+ drawable.setBounds(0, 0, 70, 70);
+ setting_rb_control.setCompoundDrawables(null, drawable,null, null);
+ /*drawable = getResources().getDrawable(R.mipmap.download);
+ drawable.setBounds(0, 0, 70, 70);
+ download_rb_control.setCompoundDrawables(null, drawable,null, null);*/
+ drawable = getResources().getDrawable(R.mipmap.catalog);
+ drawable.setBounds(0, 0, 70, 70);
+ catalog_rb_control.setCompoundDrawables(null, drawable,null, null);
+ // 设置功能按钮的点击响应处理
+ // 夜间/白日功能切换
+ day_and_night_rb_control.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if(day_or_night_status == 0) {
+ whole_layout_control.setBackgroundColor(getResources().getColor(R.color.nightBackGround));
+ day_or_night_status = 1;
+ //userStatusObj.setDay_or_night_status(day_or_night_status);
+ //DatabaseControl.getInstance(context).updateStatus(0, userStatusObj);
+ changeFrameStyle();
+ day_and_night_rb_control.setTextColor(Color.BLACK);
+ Drawable drawable = getResources().getDrawable(R.mipmap.daytime);
+ drawable.setBounds(0, 0, 70, 70);
+ day_and_night_rb_control.setCompoundDrawables(null, drawable, null, null);
+ day_and_night_rb_control.setText("日间");
+ }
+ else {
+ whole_layout_control.setBackgroundColor(getResources().getColor(R.color.PapayaWhip));
+ day_or_night_status = 0;
+ //userStatusObj.setDay_or_night_status(day_or_night_status);
+ //DatabaseControl.getInstance(context).updateStatus(0, userStatusObj);
+ //init_fragment();
+ changeFrameStyle();
+ day_and_night_rb_control.setTextColor(Color.BLACK);
+ Drawable drawable = getResources().getDrawable(R.mipmap.nighttime);
+ drawable.setBounds(0, 0, 70, 70);
+ day_and_night_rb_control.setCompoundDrawables(null, drawable, null, null);
+ day_and_night_rb_control.setText("夜间");
+ }
+ }
+ });
+
+ // 横屏竖屏功能切换
+ horizontal_and_vertical_rb_control.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // 当前竖屏状态
+ if(is_vertical_screen) {
+ // 记录状态数据转变,更新默认用户
+ is_vertical_screen = false;
+ //userStatusObj.setHor_or_ver_screen(0);
+ horizontal_and_vertical_rb_control.setTextColor(Color.BLACK);
+ //DatabaseControl.getInstance(context).updateStatus(0,0);
+ //DatabaseControl.getInstance(context).updateStatus(0, userStatusObj);
+ // 切换成横屏
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ Drawable drawable = getResources().getDrawable(R.mipmap.vertical_screen);
+ drawable.setBounds(0, 0, 70, 70);
+ horizontal_and_vertical_rb_control.setCompoundDrawables(null, drawable, null,null);
+ horizontal_and_vertical_rb_control.setText("竖屏");
+ horizontal_and_vertical_rb_control.setTextColor(Color.BLACK);
+ }
+ // 当前横屏状态
+ else {
+ // 记录状态数据转变
+ is_vertical_screen = true;
+ //userStatusObj.setHor_or_ver_screen(1);
+ horizontal_and_vertical_rb_control.setTextColor(Color.BLACK);
+ //DatabaseControl.getInstance(context).updateStatus(0,1);
+ //DatabaseControl.getInstance(context).updateStatus(0, userStatusObj);
+ System.out.println("改成竖屏");
+ System.out.println(DatabaseControl.getInstance(context).get_Hor_Or_Ver_Screen_Status(0));
+ // 切换成竖屏状态
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ Drawable drawable = getResources().getDrawable(R.mipmap.horizontal_screen);
+ drawable.setBounds(0, 0, 70, 70);
+ horizontal_and_vertical_rb_control.setCompoundDrawables(null, drawable, null,null);
+ horizontal_and_vertical_rb_control.setText("横屏");
+ horizontal_and_vertical_rb_control.setTextColor(Color.BLACK);
+ }
+ }
+ });
+ // 字体样式和大小设置功能
+ setting_rb_control.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // 弹出一个字体样式大小设置框
+ final Dialog dialog = new Dialog(context);
+ dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ dialog.setContentView(R.layout.dialog_text_setting);
+ // 字体不变红色
+ setting_rb_control.setTextColor(Color.BLACK);
+
+ final WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
+ params.width = (int)(SCREEN_WIDTH * 2 / 3);
+ /*params.height = (int)(SCREEN_HEIGHT * 2 / 3);*/
+ dialog.getWindow().setAttributes(params);
+ ImageView textSize_plus_control = dialog.findViewById(R.id.dialog_text_setting_plus_imageview);
+ final ImageView textSize_minus_control = dialog.findViewById(R.id.dialog_text_setting_minus_imageview);
+ final TextView textSize_textView = dialog.findViewById(R.id.dialog_text_setting_textSize);
+ textSize_textView.setText(Integer.toString(textSize));
+ textSize_minus_control.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if(textSize > 10) textSize-=2;
+ textSize_textView.setText(Integer.toString(textSize));
+ changeFrameStyle();
+ }
+ });
+ textSize_plus_control.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if(textSize < 50) textSize+=2;
+ textSize_textView.setText(Integer.toString(textSize));
+ changeFrameStyle();
+ }
+ });
+ // 设置 dialog 属性并显示
+ dialog.setCancelable(true);
+ dialog.show();
+
+ dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ changeFrameStyle();
+ }
+ });
+ }
+ });
+ // 下载功能
+ /*download_rb_control.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Toast.makeText(ReadPageActivity.this, "文本下载功能还没实现呢!客官", Toast.LENGTH_LONG).show();
+ }
+ });*/
+ // 目录功能
+ catalog_rb_control.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // 弹出一个目录选择框
+ final Dialog dialog = new Dialog(context);
+ dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ dialog.setContentView(R.layout.catalog_dialog);
+ // 隐藏功能按钮控件框
+ rg_control.setVisibility(View.GONE);
+ show_functional_button = false;
+ bottom_layout_control.setVisibility(View.VISIBLE);
+ // 字体不变红色
+ catalog_rb_control.setTextColor(Color.BLACK);
+ // 设置dialog标题为书名
+ TextView title = dialog.findViewById(R.id.catalog_title);
+ title.setText(bookname);
+ // 书籍目录RecyclerView
+ RecyclerView dialog_catalog = dialog.findViewById(R.id.catalog_recylerView);
+ // 书籍目录数据初始化
+ myCategory = new ArrayList<>();
+ for(int i = 0; i < chapterLinks.size(); i++)
+ myCategory.add(chapterLinks.get(i).getTitle());
+
+ // 设置 Adapter
+ adapter = new MyRecyclerViewAdapter(context, R.layout.item_catalog, myCategory) {
+ @Override
+ public void convert(MyViewHolder holder, String s) {
+ TextView title = holder.getView(R.id.catalog_title);
+ title.setText(s);
+ }
+ };
+ // 设置点击目录跳转到相应章节
+ adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
+ @Override
+ public void onClick(int position) {
+ // dialog目录框消失
+ dialog.dismiss();
+ // 设置等待进度条
+ viewPager.setVisibility(View.GONE);
+ progressBar.setVisibility(View.VISIBLE);
+ clickable = false;
+ // 清空当前的FragmentList
+ fragmentList.clear();
+ // 设置跳转章节数
+ currChapter = position;
+ // 加载帧
+ init_fragment();
+ // 更新UI
+ //rxjava_update_page(2);
+ }
+
+ @Override
+ public void onLongClick(int position) {
+
+ }
+ });
+
+ final WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
+ params.width = (int)(SCREEN_WIDTH * 2 / 3);
+ params.height = (int)(SCREEN_HEIGHT * 2 / 3);
+ dialog.getWindow().setAttributes(params);
+
+ // 适配 Adapter
+ dialog_catalog.setAdapter(adapter);
+
+ // 设置 RecyclerView 布局
+ dialog_catalog.setLayoutManager(new LinearLayoutManager(context));
+
+ // 设置 dialog 属性并显示
+ dialog.setCancelable(true);
+ dialog.show();
+ }
+ });
+ }
+
+ // 获取页面控件
+ private void init_page_control() {
+ rg_control = findViewById(R.id.read_page_bottom_rg);
+ day_and_night_rb_control = findViewById(R.id.read_page_day_and_night_rb);
+ horizontal_and_vertical_rb_control = findViewById(R.id.read_page_horizontal_and_vertical_rb);
+ setting_rb_control = findViewById(R.id.read_page_setting_rb);
+ //download_rb_control = findViewById(R.id.read_page_download_rb);
+ catalog_rb_control = findViewById(R.id.read_page_catalog_rb);
+ viewPager = findViewById(R.id.read_page_viewPager);
+ progressBar = findViewById(R.id.read_page_progressbar);
+ bottom_layout_control = findViewById(R.id.activity_read_page_bottom_layout);
+ battery_percent_control = findViewById(R.id.activity_read_page_battery_percent);
+ time_control = findViewById(R.id.activity_read_page_time);
+ read_page_process_control = findViewById(R.id.activity_read_page_process);
+ whole_layout_control = findViewById(R.id.read_page_whole_layout);
+ }
+
+ //设置一个ViewPager的监听事件,左右滑动ViewPager时进行处理
+ //当滑动到当前缓存的倒数第M章的时候,进行网络资源访问,获取新的N章的资源
+ public class MyPagerChangeListener implements ViewPager.OnPageChangeListener {
+ int from;
+ @Override
+ public void onPageScrollStateChanged(int arg0) {
+
+ }
+ @Override
+ public void onPageScrolled(int arg0, float arg1, int arg2) {
+ from = arg0;
+ }
+
+ @Override
+ public void onPageSelected(final int arg0) {
+ Log.d("跳转", arg0 + ", " + from);
+
+ int cache_left = 5; // 设置当缓存剩余多少章节时,重新开始进行资源获取
+ final int cache_num = 10; // 设置一次获取资源的章节数
+ // 帧界面向右滑动了一次
+ if (arg0 == from + 1) {
+ // 当前章节数+1
+ currChapter++;
+ // 设置进度显示
+ read_page_process_control.setText(Integer.toString(currChapter+1) + "/" + Integer.toString(totalChapter));
+ // 滑动到当前缓存剩余量不多时,当前再访问剩余量设置是五章节(不包括当前章节)
+ if(arg0 == (cache_chapter_range_max-cache_chapter_range_min) - cache_left) {
+
+ // 已经缓存到网络上的最后一章了,没有更新
+ if(cache_chapter_range_max == totalChapter) {
+ //Toast.makeText(ReadPageActivity.this, "已经是最后一章了!客官", Toast.LENGTH_LONG).show();
+ }
+ else {
+ // 隐藏ViewPager避免添加帧的时候滑动ViewPager报错
+ // 等待后台适配阅读帧
+ viewPager.setVisibility(View.GONE);
+ progressBar.setVisibility(View.VISIBLE);
+ clickable = false;
+ //使用子线程进行缓存更新
+ Thread update_cache_thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ // 再使用子线程进行网络访问,获取下面N个章节的内容(当前N设置为10)
+ /*final int newChapterNum = arg0 + 1;*/
+ Thread getNewChapterThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ if(isNetWorkConnected(context)) {
+ for (int i = 1; i <= cache_num; i++) {
+ int newChapterNum = cache_chapter_range_max + i;
+ // 非法章节数(已超出网络给出的章节数)
+ if (newChapterNum >= totalChapter) continue;
+ // 合法章节则获取新章节
+ ChapterObj c = BookService.getBookService().getChapterByLink(chapterLinks.get(newChapterNum).getLink());
+ System.out.println("正在下载(zero-based): newChapterNum---" + newChapterNum + " min---" + cache_chapter_range_min + "---max---" + cache_chapter_range_max);
+ System.out.println("获取章节: " + newChapterNum + "------" + chapterLinks.get(newChapterNum).getLink());
+ chapterObjs.add(newChapterNum - cache_chapter_range_min, c);
+ }
+ }
+ else {
+ Log.e("ERROR", "网络连接状况:未连接");
+ }
+ }
+ });
+ getNewChapterThread.start();
+
+ // 等待网络访问子线程完成
+ try {
+ getNewChapterThread.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ System.out.println("子线程更新完毕");
+ // 新增N个帧
+ for(int i = 1; i <= cache_num; i++) {
+ int newChapterNum = cache_chapter_range_max + 1;
+ // 已经超出总章节数
+ if(newChapterNum >= totalChapter) continue;
+ // 网络连接故障,要获取的章节未缓存成功,不添加新帧
+ if(newChapterNum - cache_chapter_range_min >= chapterObjs.size()) break;
+ // 合法的章节数
+ cache_chapter_range_max++;
+ // 解析章节内容
+ //String title = chapterObjs.get(0).getIchapter().getTitle(); // 这种获取Title的内容错误的(API问题)
+ String title = chapterLinks.get(newChapterNum).getTitle();
+ String content;
+ if(chapterObjs.get(newChapterNum-cache_chapter_range_min) == null) {
+ content = "章节获取失败了呢!客官";
+ }
+ else content = chapterObjs.get(newChapterNum-cache_chapter_range_min).getIchapter().getBody();
+ // 为段首添加缩进
+ content = "\u3000\u3000" + content;
+ content = content.replaceAll("\n", "\n\u3000\u3000");
+ // 新建对应章节内容帧
+ ReadPageFragment fragment = new ReadPageFragment();
+ // 给帧传数据
+ Bundle bundle = new Bundle();
+ bundle.putString("title", title);
+ bundle.putString("content", content);
+ bundle.putInt("day_or_night_status", day_or_night_status);
+ bundle.putInt("textSize", textSize);
+ fragment.setArguments(bundle);
+ // 将新加的帧放入队列中
+ fragmentList.add(fragment);
+ }
+ // 使用rxjava进行主界面UI更新
+ rxjava_update_page(1);
+ System.out.println("更新章节: ");
+ }
+ });
+ update_cache_thread.start();
+ }
+
+ }
+ }
+ // 向左滑动一页
+ else if (arg0 == from) {
+ // 当前章节数-1
+ currChapter--;
+ // 设置进度显示
+ read_page_process_control.setText(Integer.toString(currChapter+1) + "/" + Integer.toString(totalChapter));
+ // 滑动到当前缓存剩余量不多时,当前再访问剩余量设置是五章节(不包括当前章节)
+ System.out.println("arg0-currChapter-min-max: " + arg0 + " " + currChapter + " " + cache_chapter_range_min + " " + cache_chapter_range_max);
+ if((currChapter-cache_chapter_range_min) == cache_left) {
+ // 已经是网络上的第一章了
+ if(cache_chapter_range_min == 0) {
+ //Toast.makeText(ReadPageActivity.this, "已经是第一章了!客官", Toast.LENGTH_LONG).show();
+ }
+ else {
+ // 隐藏ViewPager避免添加帧的时候滑动ViewPager报错
+ // 等待后台适配阅读帧
+ viewPager.setVisibility(View.GONE);
+ progressBar.setVisibility(View.VISIBLE);
+ clickable = false;
+ //使用子线程进行缓存更新
+ Thread update_cache_thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ // 再使用子线程进行网络访问,获取下面N个章节的内容(当前N设置为10)
+ /*final int newChapterNum = arg0 + 1;*/
+ Thread getNewChapterThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ if(isNetWorkConnected(context)) {
+ for (int i = 1; i <= cache_num; i++) {
+ int newChapterNum = cache_chapter_range_min - i;
+ // 非法章节数(已经到第一章了)
+ if (newChapterNum < 0) continue;
+ // 合法章节则获取新章节
+ ChapterObj c = BookService.getBookService().getChapterByLink(chapterLinks.get(newChapterNum).getLink());
+ System.out.println(chapterLinks.get(newChapterNum).getLink());
+ // 在队列头插入章节信息
+ chapterObjs.add(0, c);
+ }
+ }
+ }
+ });
+ getNewChapterThread.start();
+
+ // 等待网络访问子线程完成
+ try {
+ getNewChapterThread.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ // 新增N个帧
+ for(int i = 1; i <= cache_num; i++) {
+ int newChapterNum = cache_chapter_range_min - 1;
+ // 比第一章还小,非法章节数
+ if(newChapterNum < 0) continue;
+ // 因网络故障未缓存到所要章节
+ if(cache_chapter_range_max - cache_chapter_range_min + 1 >= chapterObjs.size()) break;
+ // 合法的章节数
+ cache_chapter_range_min--;
+ // 解析章节内容
+ //String title = chapterObjs.get(0).getIchapter().getTitle(); // 这种获取Title的内容错误的(API问题)
+ String title = chapterLinks.get(newChapterNum).getTitle();
+ String content;
+ if(chapterObjs.get(newChapterNum-cache_chapter_range_min) == null) {
+ content = "章节获取失败了呢!客官";
+ }
+ else content = chapterObjs.get(newChapterNum-cache_chapter_range_min).getIchapter().getBody();
+ // 为段首添加缩进
+ content = "\u3000\u3000" + content;
+ content = content.replaceAll("\n", "\n\u3000\u3000");
+ // 新建对应章节内容帧
+ ReadPageFragment fragment = new ReadPageFragment();
+ // 给帧传数据
+ Bundle bundle = new Bundle();
+ bundle.putString("title", title);
+ bundle.putString("content", content);
+ bundle.putInt("day_or_night_status", day_or_night_status);
+ bundle.putInt("textSize", textSize);
+ fragment.setArguments(bundle);
+ // 将新加的帧放入队列中
+ fragmentList.add(0,fragment);
+ }
+ // 使用rxjava进行主界面UI更新
+ rxjava_update_page(2);
+ System.out.println("更新章节: ");
+ }
+ });
+ update_cache_thread.start();
+ }
+
+ }
+ }
+ }
+ }
+
+ // 辅助函数:判断网络是否连接
+ public boolean isNetWorkConnected(Context context) {
+ if (context != null) {
+ ConnectivityManager mConnectivityManager = (ConnectivityManager) context
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
+ if (mNetworkInfo != null) {
+ return mNetworkInfo.isConnected();
+ }
+ }
+ return false;
+ }
+
+ // RXJAVA2 更新主界面UI
+ private void rxjava_update_page(final int type) {
+ final Observable observable = Observable.create(new ObservableOnSubscribe() {
+
+ @Override
+ public void subscribe(ObservableEmitter e) throws Exception {
+ e.onNext(type);
+ e.onComplete();
+ }
+
+ });
+
+ CompositeDisposable mCompositeDisposable = new CompositeDisposable();
+
+ DisposableObserver disposableObserver = new DisposableObserver() {
+ @Override
+ public void onNext(Integer value) {
+ Log.d("BackgroundActivity", "onNext");
+ // type = 0 界面初始化更新
+ if(type == 0) {
+ // 初始化适配阅读帧
+ fragmentAdapter.notifyDataSetChanged();
+ viewPager.setAdapter(fragmentAdapter);
+ // 跳到上次阅读到的章节
+ viewPager.setCurrentItem(currChapter-cache_chapter_range_min);
+ // 适配完毕,取消ProgressBar, 隐藏功能按键,显示底部信息栏
+ progressBar.setVisibility(View.GONE);
+ rg_control.setVisibility(View.GONE);
+ viewPager.setVisibility(View.VISIBLE);
+ clickable = true;
+ read_page_process_control.setText(Integer.toString(currChapter+1) + "/" + Integer.toString(totalChapter));
+ bottom_layout_control.setVisibility(View.VISIBLE);
+ }
+ // type == 1 界面获取下N章节更新
+ else if(type == 1) {
+ fragmentAdapter.notifyDataSetChanged();
+ // 适配完毕,取消ProgressBar, 隐藏功能按键
+ progressBar.setVisibility(View.GONE);
+ viewPager.setVisibility(View.VISIBLE);
+ clickable = true;
+ }
+ // type == 2 界面获取上N章节更新
+ else if(type == 2) {
+ // 适配Adapter
+ fragmentAdapter.notifyDataSetChanged();
+ // 跳回到刚才阅读到的章节
+ viewPager.setCurrentItem((currChapter-cache_chapter_range_min), false);
+ // 适配完毕,取消ProgressBar, 隐藏功能按键
+ progressBar.setVisibility(View.GONE);
+ viewPager.setVisibility(View.VISIBLE);
+ clickable = true;
+ }
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ Log.d("BackgroundActivity", "onError=" + e);
+ }
+
+ @Override
+ public void onComplete() {
+ Log.d("BackgroundActivity", "onComplete");
+ }
+ };
+
+ observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(disposableObserver);
+ mCompositeDisposable.add(disposableObserver);
+
+ }
+
+ // 辅助函数 : 将字符串按指定长度分割
+ public static List getStrList(String inputString, int length) {
+ int size = inputString.length() / length;
+ if (inputString.length() % length != 0) {
+ size += 1;
+ }
+ List res = new ArrayList<>();
+ for(int i = 0; i < size - 1; i++) {
+ String s = inputString.substring(i*length, (i+1)*length-1);
+ res.add(s);
+ }
+ String s = inputString.substring((size-1)*length);
+ res.add(s);
+ return res;
+ }
+
+ // 注册获取系统广播
+ // 广播获取系统电量和时间
+ class MyReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // TODO Auto-generated method stub
+ // 判断它是否是为电量变化的Broadcast Action
+ // 电量变化广播
+ if(Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())){
+ //获取当前电量
+ int level = intent.getIntExtra("level", 0);
+ //电量的总刻度
+ int scale = intent.getIntExtra("scale", 100);
+ //把它转成百分比
+ int percent = level*100/scale;
+ battery_percent_control.setText(Integer.toString(percent));
+ }
+ else if (Intent.ACTION_TIME_TICK.equals(intent.getAction())) {
+ // 设置时间格式
+ SimpleDateFormat formatter = new SimpleDateFormat("HH:mm");
+ // 获取当前时间
+ Date curdate = new Date(System.currentTimeMillis());
+ // 按照格式将Date 时间转化成格式字符串
+ String time = formatter.format(curdate);
+ // UI设置显示
+ time_control.setText(time);
+ }
+ }
+
+ }
+
+
+ // 当使用功能按键切换阅读界面阅读习惯时
+ // 不必要重新进行网络访问
+ // 直接改变阅读帧的样式
+ public void changeFrameStyle() {
+ System.out.println("---------[changeFrameStyle]-----------");
+ // 设置等待进度条
+ progressBar.setVisibility(View.VISIBLE);
+ viewPager.setVisibility(View.GONE);
+ // 清空当前的FragmentList
+ fragmentList.clear();
+ for(int i = cache_chapter_range_min; i<= cache_chapter_range_max; i++) {
+ // 解析章节内容
+ //String title = chapterObjs.get(0).getIchapter().getTitle(); // 这种获取Title的内容错误的(API问题)
+ String title = chapterLinks.get(i).getTitle();
+ String content;
+ if(chapterObjs.get(i-cache_chapter_range_min) == null) {
+ content = "章节获取失败了呢!客官";
+ }
+ else content = chapterObjs.get(i-cache_chapter_range_min).getIchapter().getBody();
+ // 为段首添加缩进
+ content = "\u3000\u3000" + content;
+ content = content.replaceAll("\n", "\n\u3000\u3000");
+ // 新建对应章节内容帧
+ ReadPageFragment fragment = new ReadPageFragment();
+ // 给帧传数据
+ Bundle bundle = new Bundle();
+ bundle.putString("title", title);
+ bundle.putString("content", content);
+ bundle.putInt("day_or_night_status", day_or_night_status);
+ bundle.putInt("textSize", textSize);
+ fragment.setArguments(bundle);
+ // 将新加的帧放入队列中
+ fragmentList.add(fragment);
+ }
+ rxjava_update_page(2);
+ }
+
+
+ // 重载onConfigurationChanged函数处理横竖屏切换
+ // 使得不必重新回调Activity整个生命周期
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+
+ if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ //text_screen.append("\n 当前屏幕为横屏");
+ System.out.println("当前屏幕为横屏");
+ } else {
+ //text_screen.append("\n 当前屏幕为竖屏");
+ System.out.println("当前屏幕为竖屏");
+ }
+ if(is_vertical_screen == true) {
+
+ System.out.println("数据库中是竖屏");
+ } else {
+ System.out.println("数据库中是横屏");
+ }
+ // 重新设置屏幕宽高
+ get_screen_info();
+ super.onConfigurationChanged(newConfig);
+ Log.e("TAG", "onConfigurationChanged");
+ // setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); //设置横屏
+ }
+
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/RecomActivity.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/RecomActivity.java
new file mode 100644
index 0000000..946de0a
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/RecomActivity.java
@@ -0,0 +1,120 @@
+package com.example.Activity;
+
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Handler;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.List;
+
+import com.example.R;
+import com.example.RecyclerView.MyRecyclerViewAdapter;
+import com.example.RecyclerView.MyViewHolder;
+import com.example.Object.BookObj;
+import com.example.Object.RecomListObj;
+import com.example.Service.BookService;
+
+public class RecomActivity extends AppCompatActivity {
+
+ private List bookObjs;
+
+ private RecyclerView recyclerView;
+
+ private ImageView back;
+
+ private Handler mHandler = new Handler();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_recom);
+
+ // 获取同类书籍
+ Bundle bundle = getIntent().getExtras();
+ bookObjs = ((RecomListObj)bundle.getSerializable("list")).getBookObjs();
+
+ // 获取相关控件
+ back = findViewById(R.id.recom_back);
+ recyclerView = findViewById(R.id.recom_recyclerview);
+
+ // 内容填充
+ MyRecyclerViewAdapter adapter = new MyRecyclerViewAdapter(RecomActivity.this, R.layout.item_book, bookObjs) {
+ @Override
+ public void convert(MyViewHolder holder, BookObj bookObj) {
+ final ImageView imageView = holder.getView(R.id.item_book_cover);
+ TextView bookName = holder.getView(R.id.item_book_name);
+ TextView bookAuthor = holder.getView(R.id.item_book_author);
+ TextView bookType = holder.getView(R.id.item_book_type);
+ TextView bookIntro = holder.getView(R.id.item_book_intro);
+ bookName.setText(bookObj.getTitle());
+ bookType.setText(bookObj.getMajorCate());
+ bookAuthor.setText(bookObj.getAuthor());
+ String intro = bookObj.getLongIntro();
+ if (intro.length() > 50) intro = intro.substring(0, 50);
+ intro += "...";
+ bookIntro.setText(intro);
+
+ //通过网络获取书籍图标
+ final String iconURL = BookService.StaticsUrl + bookObj.getCover();
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ URL url = new URL(iconURL);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setConnectTimeout(10000);
+ if (connection.getResponseCode() == 200) {
+ InputStream inputStream = connection.getInputStream();
+ final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ imageView.setImageBitmap(bitmap);
+ }
+ });
+ }
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ }
+ }
+ }).start();
+ }
+ };
+ adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
+ @Override
+ public void onClick(int position) {
+ //跳转到书籍详情界面
+ Intent intent = new Intent(RecomActivity.this, BookDetailActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putSerializable("bookobj", bookObjs.get(position));
+ intent.putExtras(bundle);
+ startActivity(intent);
+ }
+
+ @Override
+ public void onLongClick(int position) {
+
+ }
+ });
+ recyclerView.setAdapter(adapter);
+ recyclerView.setLayoutManager(new LinearLayoutManager(RecomActivity.this));
+
+ back.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ });
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/SearchActivity.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/SearchActivity.java
new file mode 100644
index 0000000..f503caf
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/SearchActivity.java
@@ -0,0 +1,507 @@
+package com.example.Activity;
+
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.constraint.ConstraintLayout;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.SearchView;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import com.example.R;
+import com.example.RecyclerView.MyRecyclerViewAdapter;
+import com.example.RecyclerView.MyViewHolder;
+import com.example.Object.BookObj;
+import com.example.Object.SearchResultObj;
+import com.example.Service.BookService;
+
+import static com.example.DataBase.DatabaseControl.getInstance;
+import static com.example.Service.BookService.getBookService;
+
+public class SearchActivity extends AppCompatActivity {
+
+ private SearchView searchView;
+ private TextView cancelView;
+ private TextView text1;
+ private TextView text2;
+ private TextView text3;
+ private TextView text4;
+ private TextView text5;
+ private TextView text6;
+ private ImageView deleteView;
+ private ImageView freshView;
+ private ListView historyList;
+ private ListView fuzzyList;
+ private ConstraintLayout initialLayout;
+ private LinearLayout searchLayout;
+ private RecyclerView resultList;
+ private List histories;
+ private List tempFuzzy;
+ private List results;
+ private MyRecyclerViewAdapter recyclerViewAdapter;
+ private boolean isSubmit;
+ private boolean flag;
+ public Handler handler = new Handler();
+ private String[] hotBooks = {"一品娇宠","剑来","逆天邪神","神医嫡女","官梯",
+ "最强狂兵","无敌剑域","一世倾城","天骄战纪","元尊",
+ "天行","修罗武神","永夜君王","家有王妃初长成","神级奶爸",
+ "神医毒妃","战神狂飙","逆天邪神","神医嫡女","江山美色",
+ "圣墟","极品透视学生","正道潜龙","斗罗大陆","雪中悍刀行",
+ "枭臣","将夜","校花的贴身高手","大刁民","偷香高手",};
+
+
+ // 辅助函数:判断网络是否连接
+ public boolean isNetWorkConnected(Context context) {
+ if (context != null) {
+ ConnectivityManager mConnectivityManager = (ConnectivityManager) context
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
+ if (mNetworkInfo != null) {
+ return mNetworkInfo.isConnected();
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_search);
+ isSubmit = false;
+ flag = true; //用于同步问题的布尔变量
+ //初始化列表
+ histories = getInstance(getBaseContext()).getAllHistory();
+ tempFuzzy = new ArrayList<>();
+ results = new ArrayList<>();
+ //获取控件
+ freshView = findViewById(R.id.search_fresh_image);
+ cancelView = findViewById(R.id.search_cancel_text);
+ searchView = findViewById(R.id.search_search_searchView);
+ deleteView = findViewById(R.id.search_delete_image);
+ historyList = findViewById(R.id.search_history_list);
+ fuzzyList = findViewById(R.id.search_fuzzy_list);
+ resultList = findViewById(R.id.search_result_list);
+ initialLayout = findViewById(R.id.search_initial_layout);
+ searchLayout = findViewById(R.id.search_afters_layout);
+ text1 = findViewById(R.id.search_pop_text1);
+ text2 = findViewById(R.id.search_pop_text2);
+ text3 = findViewById(R.id.search_pop_text3);
+ text4 = findViewById(R.id.search_pop_text4);
+ text5 = findViewById(R.id.search_pop_text5);
+ text6 = findViewById(R.id.search_pop_text6);
+
+ //设置历史列表adapter
+ final ArrayAdapter historyAdapter = new ArrayAdapter<>(this,R.layout.item_listview,histories);
+ historyList.setAdapter(historyAdapter);
+ //设置结果列表adapter
+ recyclerViewAdapter = new MyRecyclerViewAdapter(SearchActivity.this,R.layout.item_book,results) {
+ @Override
+ public void convert(MyViewHolder holder, final SearchResultObj.book book) {
+ TextView name = holder.getView(R.id.item_book_name);
+ name.setText(book.getTitle());
+ TextView author = holder.getView(R.id.item_book_author);
+ author.setText(book.getAuthor());
+ TextView major = holder.getView(R.id.item_book_type);
+ major.setText(book.getCat());
+ TextView intro = holder.getView(R.id.item_book_intro);
+ String introString = book.getShortIntro();
+ if (introString.length() > 50){
+ introString = introString.substring(0,49)+"……";
+ }
+ intro.setText(introString);
+ final ImageView cover = holder.getView(R.id.item_book_cover);
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (isNetWorkConnected(MainActivity.getContext())) {
+ URL url = new URL(BookService.StaticsUrl + book.getCover());
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setConnectTimeout(10000);
+ if (connection.getResponseCode() == 200) {
+ InputStream inputStream = connection.getInputStream();
+ final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ cover.setImageBitmap(bitmap);
+ }
+ });
+ }
+ }
+ else{
+ Looper.prepare();
+ Toast.makeText(SearchActivity.this,"网络似乎出现了点问题",Toast.LENGTH_SHORT).show();
+ Looper.loop();
+ }
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ }
+ }
+ }).start();
+ }
+ };
+ recyclerViewAdapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
+ @Override
+ public void onClick(final int position) {
+ final Intent intent = new Intent(SearchActivity.this, BookDetailActivity.class);
+ final Bundle bundle = new Bundle();
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ if (isNetWorkConnected(MainActivity.getContext())) {
+ final BookObj t = getBookService().getBookById(results.get(position).get_id());
+ if (t != null)
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ bundle.putSerializable("bookobj", t);
+ intent.putExtras(bundle);
+ startActivity(intent);
+ }
+ });
+ }
+ else {
+ Looper.prepare();
+ Toast.makeText(SearchActivity.this,"网络似乎出现了点问题",Toast.LENGTH_SHORT).show();
+ Looper.loop();
+ }
+ }
+ }).start();
+ }
+
+ @Override
+ public void onLongClick(int position) {
+
+ }
+ });
+ resultList.setAdapter(recyclerViewAdapter);
+ resultList.setLayoutManager(new LinearLayoutManager(this));
+ //设置模糊关联列表adapter
+ final ArrayAdapter fuzzyAdapter = new ArrayAdapter<>(this,R.layout.item_listview2,tempFuzzy);
+ fuzzyList.setAdapter(fuzzyAdapter);
+
+
+ //设置热门搜索函数
+ text1.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String s = text1.getText().toString();
+ recordClick(s);
+ }
+ });
+ text2.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String s = text2.getText().toString();
+ recordClick(s);
+ }
+ });
+ text3.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String s = text3.getText().toString();
+ recordClick(s);
+ }
+ });
+ text4.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String s = text4.getText().toString();
+ recordClick(s);
+ }
+ });
+ text5.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String s = text5.getText().toString();
+ recordClick(s);
+ }
+ });
+ text6.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String s = text6.getText().toString();
+ recordClick(s);
+ }
+ });
+
+
+ //设置搜索函数
+ searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(final String s) {
+ isSubmit = true;
+ //添加历史
+ if (!histories.contains(s)){
+ histories.add(s);
+ getInstance(getBaseContext()).addSearchHistory(s);
+ }
+ //设置可见
+ searchLayout.setVisibility(View.VISIBLE);
+ fuzzyList.setVisibility(View.GONE);
+ resultList.setVisibility(View.VISIBLE);
+ //填充数据
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ if (isNetWorkConnected(MainActivity.getContext())) {
+ SearchResultObj tt = getBookService().getSearchResultObj(s, 0, 8);
+ results.clear();
+ if (tt != null) {
+ List t = tt.getBookList();
+ results.addAll(t);
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ recyclerViewAdapter.notifyDataSetChanged();
+ }
+ });
+ }
+ else {
+ Looper.prepare();
+ Toast.makeText(SearchActivity.this,"搜索不到相关内容",Toast.LENGTH_SHORT).show();
+ Looper.loop();
+ }
+ }
+ else {
+ Looper.prepare();
+ Toast.makeText(SearchActivity.this,"网络似乎出现了点问题",Toast.LENGTH_SHORT).show();
+ Looper.loop();
+ }
+ }
+ }).start();
+ recyclerViewAdapter.notifyDataSetChanged();
+ return false;
+ }
+
+ @Override
+ public boolean onQueryTextChange(final String s) {
+ //设置可见
+ if (!isSubmit) {
+ if (s.equals("")) {
+ initialLayout.setVisibility(View.VISIBLE);
+ searchLayout.setVisibility(View.GONE);
+ }
+ else {
+ initialLayout.setVisibility(View.GONE);
+ searchLayout.setVisibility(View.VISIBLE);
+ fuzzyList.setVisibility(View.VISIBLE);
+ resultList.setVisibility(View.GONE);
+ }
+ }
+ else {
+ if (s.equals("")) {
+ fuzzyList.setVisibility(View.GONE);
+ resultList.setVisibility(View.VISIBLE);
+ }
+ else {
+ fuzzyList.setVisibility(View.VISIBLE);
+ resultList.setVisibility(View.GONE);
+ }
+ }
+ //填充数据
+ if (!s.equals("")&&flag) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ flag = false;
+ if (isNetWorkConnected(MainActivity.getContext())) {
+ SearchResultObj tt = getBookService().getSearchResultObj(s, 0, 8);
+ List t = new ArrayList<>();
+ if (tt != null) {
+ List tss = tt.getBookList();
+ int size = tss.size();
+ for (int i = 0; i < size; i++)
+ t.add(tss.get(i).getTitle());
+ }
+ tempFuzzy.clear();
+ if (t.size() > 0)
+ tempFuzzy.addAll(t);
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ fuzzyAdapter.notifyDataSetChanged();
+ }
+ });
+ }
+ else {
+ Looper.prepare();
+ Toast.makeText(SearchActivity.this,"网络似乎出现了点问题",Toast.LENGTH_SHORT).show();
+ Looper.loop();
+ }
+ flag = true;
+ }
+ }).start();
+ fuzzyAdapter.notifyDataSetChanged();
+ }
+ return false;
+ }
+ });
+
+ //设置历史删除函数
+ deleteView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ getInstance(getBaseContext()).deleteHistory();
+ histories.clear();
+ historyAdapter.notifyDataSetChanged();
+ }
+ });
+
+ //设置历史点击函数
+ historyList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ final String s = histories.get(position);
+ recordClick(s);
+ }
+ });
+
+ //模糊搜索点击函数
+ fuzzyList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ final String s = tempFuzzy.get(position);
+ isSubmit = true;
+ //添加历史
+ if (!histories.contains(s)){
+ histories.add(s);
+ getInstance(getBaseContext()).addSearchHistory(s);
+ }
+ //设置可见
+ initialLayout.setVisibility(View.GONE);
+ searchLayout.setVisibility(View.VISIBLE);
+ fuzzyList.setVisibility(View.GONE);
+ resultList.setVisibility(View.VISIBLE);
+ //填充数据
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ if (isNetWorkConnected(MainActivity.getContext())) {
+ SearchResultObj tt = getBookService().getSearchResultObj(s, 0, 8);
+ List t = tt.getBookList();
+ results.clear();
+ if (t != null)
+ results.addAll(t);
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ recyclerViewAdapter.notifyDataSetChanged();
+ }
+ });
+ }
+ else {
+ Looper.prepare();
+ Toast.makeText(SearchActivity.this,"网络似乎出现了点问题",Toast.LENGTH_SHORT).show();
+ Looper.loop();
+ }
+ }
+ }).start();
+ recyclerViewAdapter.notifyDataSetChanged();
+ searchView.setQuery(s,true);
+ }
+ });
+ //取消按钮点击事件
+ cancelView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ });
+
+ //更换热门图书函数
+ freshView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ freshPopBook();
+ }
+ });
+ }
+ public void recordClick(final String s) {
+ isSubmit = true;
+ //设置可见
+ initialLayout.setVisibility(View.GONE);
+ searchLayout.setVisibility(View.VISIBLE);
+ fuzzyList.setVisibility(View.GONE);
+ resultList.setVisibility(View.VISIBLE);
+ //添加历史
+ if (!histories.contains(s)){
+ histories.add(s);
+ getInstance(getBaseContext()).addSearchHistory(s);
+ }
+ //填充数据
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ if (isNetWorkConnected(MainActivity.getContext())) {
+ SearchResultObj tt = getBookService().getSearchResultObj(s, 0, 8);
+ results.clear();
+ if (tt != null) {
+ List t = tt.getBookList();
+ results.addAll(t);
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ recyclerViewAdapter.notifyDataSetChanged();
+ }
+ });
+ }
+ else {
+ Looper.prepare();
+ Toast.makeText(SearchActivity.this,"搜索不到相关内容",Toast.LENGTH_SHORT).show();
+ Looper.loop();
+ }
+ }
+ else {
+ Looper.prepare();
+ Toast.makeText(SearchActivity.this,"网络似乎出现了点问题",Toast.LENGTH_SHORT).show();
+ Looper.loop();
+ }
+ }
+ }).start();
+ recyclerViewAdapter.notifyDataSetChanged();
+ searchView.setQuery(s,true);
+ }
+
+ public void freshPopBook() {
+ Random ra =new Random();
+ int t = ra.nextInt(29);
+ text1.setText(hotBooks[t]);
+ t = (t+1)%30;
+ text2.setText(hotBooks[t]);
+ t = (t+1)%30;
+ text3.setText(hotBooks[t]);
+ t = (t+1)%30;
+ text4.setText(hotBooks[t]);
+ t = (t+1)%30;
+ text5.setText(hotBooks[t]);
+ t = (t+1)%30;
+ text6.setText(hotBooks[t]);
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/text.puml b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/text.puml
new file mode 100644
index 0000000..ac2c2d3
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/text.puml
@@ -0,0 +1,11 @@
+@startuml
+'https://plantuml.com/sequence-diagram
+
+autonumber
+
+Alice -> Bob: Authentication Request
+Bob --> Alice: Authentication Response
+
+Alice -> Bob: Another authentication Request
+Alice <-- Bob: another authentication Response
+@enduml
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/DataBase/DatabaseControl.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/DataBase/DatabaseControl.java
new file mode 100644
index 0000000..81173d6
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/DataBase/DatabaseControl.java
@@ -0,0 +1,279 @@
+package com.example.DataBase;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.example.Activity.MainActivity;
+import com.example.R;
+import com.example.Object.ShelfBookObj;
+import com.example.Object.UserStatusObj;
+
+public class DatabaseControl extends SQLiteOpenHelper {
+ private static final String DB_NAME= "readerBase.db";
+ private static final String TABLE_NAME1 = "shelfbook_table";
+ private static final String TABLE_NAME2 = "categorybook_table";
+ private static final String TABLE_NAME3 = "status_table";
+ private static final int DB_VERSION = 1;
+
+
+ private static DatabaseControl instance = null;
+ public static DatabaseControl getInstance(Context context) {
+ if (instance == null) {
+ instance = new DatabaseControl(context);
+ }
+ return instance;
+ }
+
+ //byte[] 转 Bitmap
+ public Bitmap bytesToBitmap(byte[] b) {
+ if (b.length != 0) {
+ return BitmapFactory.decodeByteArray(b, 0, b.length);
+ } else {
+ return null;
+ }
+ }
+ //Bitmap → byte[]
+ public byte[] bitmapToBytes(Bitmap bm) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
+ return baos.toByteArray();
+ }
+ //这个list用于保存所有书架书籍信息
+ private List allShelfBook = null;
+ public List getAllShelfBook() {
+ return getAllShelfBookFromDB();
+ }
+
+ //从数据库中查询所有书架书目
+ private List getAllShelfBookFromDB() {
+ SQLiteDatabase db = getWritableDatabase();
+ Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME1, null);
+ List list = new ArrayList<>();
+ while (cursor.moveToNext()) {
+ String id = cursor.getString(cursor.getColumnIndex("_id"));
+ String major = cursor.getString(cursor.getColumnIndex("major"));
+ String author = cursor.getString(cursor.getColumnIndex("author"));
+ int readChapter = cursor.getInt(cursor.getColumnIndex("progress"));
+ int type = cursor.getInt(cursor.getColumnIndex("type"));
+ String name = cursor.getString(cursor.getColumnIndex("name"));
+ String address = cursor.getString(cursor.getColumnIndex("address"));
+ String description = cursor.getString(cursor.getColumnIndex("description"));
+ byte[] imageByte = cursor.getBlob(cursor.getColumnIndex("image"));
+ list.add(new ShelfBookObj(id,name, bytesToBitmap(imageByte),"",readChapter,address,type,description,author,major));
+ }
+ cursor.close();
+ db.close();
+ return list;
+ }
+ //根据book id删除数据
+ public void deleteShelfBook(String id) {
+ SQLiteDatabase db = getWritableDatabase();
+ db.delete(TABLE_NAME1, "_id = ?", new String[] { id });
+ }
+
+ public void addShelfBook(ShelfBookObj book) {
+ SQLiteDatabase db = getWritableDatabase();
+ ContentValues values = new ContentValues();
+ //开始添加第一条数据_id TEXT PRIMARY KEY, name TEXT, type INTEGER ,progress INTEGER, address TEXT,image BLOB, description TEXT
+ values.put("name",book.getName());
+ values.put("description",book.getDescription());
+ values.put("type",book.getType());
+ values.put("_id",book.getBookId());
+ values.put("author",book.getAuthor());
+ values.put("major",book.getMajor());
+ values.put("address",book.getAddress());
+ values.put("progress",book.getReadChapter());
+ values.put("image",bitmapToBytes(book.getIcon()));
+ db.insert(TABLE_NAME1,null,values);
+ db.close();
+ }
+
+ //获取多少条搜索历史
+ public int getHistoryCount() {
+ SQLiteDatabase db = getWritableDatabase();
+ Cursor cursor = db.query(TABLE_NAME2, null, null, null, null, null, null);
+ return cursor.getCount();
+ }
+
+ //更新阅读进度
+ public void updateProgress(int progress, String id) {
+ SQLiteDatabase db = getWritableDatabase();
+ ContentValues value = new ContentValues();
+ value.put("progress", progress);
+ db.update(TABLE_NAME1, value, "_id=?", new String[] { id });
+ db.close();
+ }
+
+ public List getAllHistory() {
+ SQLiteDatabase db = getWritableDatabase();
+ Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME2, null);
+ List list = new ArrayList<>();
+ while (cursor.moveToNext()) {
+ String content = cursor.getString(cursor.getColumnIndex("content"));
+ list.add(content);
+ }
+ cursor.close();
+ db.close();
+ return list;
+ }
+
+ //搜索历史添加(不超过10个)
+ public void addSearchHistory(String s) {
+ SQLiteDatabase db = getWritableDatabase();
+ if (getHistoryCount() > 9){
+ Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME2, null);
+ cursor.moveToFirst();
+ String name = cursor.getString(cursor.getColumnIndex("content"));
+ db.delete(TABLE_NAME2, "content=?", new String[] {name});
+ }
+ ContentValues cv = new ContentValues();
+ cv.put("content", s);
+ db.insert(TABLE_NAME2, null, cv);
+ db.close();
+ }
+
+ public boolean judgeBookExist(String id) {
+ SQLiteDatabase db = getWritableDatabase();
+ Cursor cursor = db.query(TABLE_NAME1, null, "_id=?", new String[] { id }, null, null, null);
+ return cursor.moveToFirst();
+ }
+
+ //删除搜索历史
+ public void deleteHistory() {
+ SQLiteDatabase db = getWritableDatabase();
+ db.execSQL("DELETE FROM " + TABLE_NAME2);
+ }
+
+ // 更新用户阅读器习惯的状态
+ public void updateStatus(int user_id, int hor_or_ver_screen) {
+ SQLiteDatabase db = getWritableDatabase();
+ ContentValues value = new ContentValues();
+ value.put("hor_or_ver_screen", hor_or_ver_screen);
+ db.update(TABLE_NAME3, value, "user_id=?", new String[] { Integer.toString(user_id)});
+ db.close();
+ }
+
+ // 获取用户阅读器习惯的横竖屏
+ public int get_Hor_Or_Ver_Screen_Status(int user_id) {
+ SQLiteDatabase db = getWritableDatabase();
+ String id = Integer.toString(user_id);
+ String sql = String.format("SELECT * FROM " + TABLE_NAME3 + " where user_id='%s'" , id);
+ Cursor cursor = db.rawQuery(sql, null);
+ int res = 1;
+ while (cursor.moveToNext()) {
+ res = cursor.getInt(cursor.getColumnIndex("hor_or_ver_screen"));
+ return res;
+ }
+ cursor.close();
+ db.close();
+ return res;
+ }
+
+ // 更新用户阅读器习惯的状态
+ public void updateStatus(int user_id, UserStatusObj u) {
+ SQLiteDatabase db = getWritableDatabase();
+ ContentValues value = new ContentValues();
+ value.put("hor_or_ver_screen", u.getHor_or_ver_screen()); // 1表示竖屏,0表示横屏
+ value.put("day_or_night_status", u.getDay_or_night_status()); // 0表示日间,1表示夜间
+ value.put("textSize", u.getTextSize()); // 字体大小
+ db.update(TABLE_NAME3, value, "user_id=?", new String[] { Integer.toString(user_id)});
+ db.close();
+ }
+
+ public UserStatusObj get_User_Status_Obj(int user_id) {
+ SQLiteDatabase db = getWritableDatabase();
+ String id = Integer.toString(user_id);
+ String sql = String.format("SELECT * FROM " + TABLE_NAME3 + " where user_id='%s'" , id);
+ Cursor cursor = db.rawQuery(sql, null);
+ UserStatusObj res = null;
+ while (cursor.moveToNext()) {
+ int hor_or_ver_screen = cursor.getInt(cursor.getColumnIndex("hor_or_ver_screen"));
+ int day_or_night_status = cursor.getInt(cursor.getColumnIndex("day_or_night_status"));
+ int textSize = cursor.getInt(cursor.getColumnIndex("textSize"));
+ res = new UserStatusObj(user_id, hor_or_ver_screen, day_or_night_status, textSize);
+ return res;
+ }
+ cursor.close();
+ db.close();
+ return res;
+ }
+
+
+
+
+ public DatabaseControl(Context context) {
+ super(context, DB_NAME, null, DB_VERSION );
+ }
+
+ @Override//创建数据库
+ public void onCreate(SQLiteDatabase sqLiteDatabase) {
+ //书架上的书,含书名、类型(本地还是网络)、阅读进度、资源地址、书的封面
+ String CREATE_TABLE1 = "CREATE TABLE if not exists "
+ + TABLE_NAME1
+ + " (_id TEXT PRIMARY KEY, name TEXT, type INTEGER ,progress INTEGER, address TEXT,image BLOB, description TEXT, author TEXT, major TEXT)";
+ //搜索历史
+ String CREATE_TABLE2 = "CREATE TABLE if not exists "
+ + TABLE_NAME2
+ + " (_id INTEGER PRIMARY KEY, content TEXT)";
+ // 阅读器状态保存
+ String CREATE_TABLE3 = "CREATE TABLE if not exists "
+ + TABLE_NAME3
+ + " (user_id INTEGER PRIMARY KEY, hor_or_ver_screen INTEGER, day_or_night_status INTEGER, textSize INTEGER)";
+ sqLiteDatabase.execSQL(CREATE_TABLE1);
+ sqLiteDatabase.execSQL(CREATE_TABLE2);
+ sqLiteDatabase.execSQL(CREATE_TABLE3);
+
+ Resources res = MainActivity.getContext().getResources();
+ Bitmap bitmap = BitmapFactory.decodeResource(res, R.mipmap.bookcover);
+ ContentValues values = new ContentValues();
+ ShelfBookObj book = new ShelfBookObj("5816b415b06d1d32157790b1","圣墟",bitmap,"",0,"default",0,"在破败中崛起,在寂灭中复苏。沧海成尘,雷电枯竭,那一缕幽雾又一次临近大地,世间的枷锁被打开了,一个全新的世界就此揭开神秘的一角……","辰东","玄幻");
+ //开始添加第一条数据_id TEXT PRIMARY KEY, name TEXT, type INTEGER ,progress INTEGER, address TEXT,image BLOB, description TEXT
+ values.put("name",book.getName());
+ values.put("description",book.getDescription());
+ values.put("type",book.getType());
+ values.put("_id",book.getBookId());
+ values.put("author",book.getAuthor());
+ values.put("major",book.getMajor());
+ values.put("address",book.getAddress());
+ values.put("progress",book.getReadChapter());
+ values.put("image",bitmapToBytes(book.getIcon()));
+ sqLiteDatabase.insert(TABLE_NAME1,null,values);
+ values.clear();
+ bitmap = BitmapFactory.decodeResource(res, R.mipmap.bookcover2);
+ book = new ShelfBookObj("59ba0dbb017336e411085a4e","元尊",bitmap,"",0,"default",0,"《斗破苍穹》《武动乾坤》之后全新力作,朝堂太子踏上了荆棘重生之路…","天蚕土豆","玄幻");
+ values.put("name",book.getName());
+ values.put("description",book.getDescription());
+ values.put("type",book.getType());
+ values.put("_id",book.getBookId());
+ values.put("author",book.getAuthor());
+ values.put("major",book.getMajor());
+ values.put("address",book.getAddress());
+ values.put("progress",book.getReadChapter());
+ values.put("image",bitmapToBytes(book.getIcon()));
+ sqLiteDatabase.insert(TABLE_NAME1,null,values);
+
+ // 往阅读器状态表格中保存一条初始阅读器状态
+ UserStatusObj u = new UserStatusObj(0,1,0,18);
+ values.clear();
+ values.put("user_id", 0); // 用户id为0,表示默认状态
+ values.put("hor_or_ver_screen", u.getHor_or_ver_screen()); // 1表示竖屏,0表示横屏
+ values.put("day_or_night_status", u.getDay_or_night_status()); // 0表示日间,1表示夜间
+ values.put("textSize", u.getTextSize()); // 字体大小
+ sqLiteDatabase.insert(TABLE_NAME3,null,values);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int ii) {
+
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/BookShelfFragment.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/BookShelfFragment.java
new file mode 100644
index 0000000..5a04c20
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/BookShelfFragment.java
@@ -0,0 +1,148 @@
+package com.example.Fragment;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.List;
+
+import com.example.R;
+import com.example.Activity.ReadPageActivity;
+import com.example.DataBase.DatabaseControl;
+import com.example.RecyclerView.MyRecyclerViewAdapter;
+import com.example.RecyclerView.MyViewHolder;
+import com.example.Object.ShelfBookObj;
+
+// 书架界面
+public class BookShelfFragment extends Fragment {
+ // Fragment的视图
+ View view;
+
+ // Fragment内的RecyclerView
+ RecyclerView recyclerView; // recyclerview
+ List myBooks; // recyclerview中的书籍数据
+ MyRecyclerViewAdapter adapter; // recyclerview 的 adapter
+
+ // book-item 项的各个控件
+ private ImageView book_cover_imageview_control;
+ private TextView book_name_textview_control;
+ private TextView book_author_textview_control;
+ private TextView book_type_textview_control;
+ private TextView book_intro_textview_control;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ // 获取 Fragment 的视图
+ view = inflater.inflate(R.layout.fragment_book_shelf, null);
+
+ // 获取书籍数据
+ getMyBooks();
+
+ // 设置页面的 RecyclerView
+ setRecyclerView();
+
+ // 返回视图
+ return view;
+ }
+
+ @Override
+ public void onResume() {
+ getMyBooks();
+ setRecyclerView();
+ //Toast.makeText(getActivity(), "进入Fragment" + " | " + myBooks.size(), Toast.LENGTH_SHORT).show();
+// System.out.println("onResume: " + myBooks.get(0).getReadChapter());
+ //System.out.println("横竖屏状态:MainActivity-BookShelfFragment: " + DatabaseControl.getInstance(getActivity()).get_Hor_Or_Ver_Screen_Status(0));
+ super.onResume();
+ }
+
+ // 获取书籍数据
+ private void getMyBooks() {
+ //Bitmap bitmap = ((BitmapDrawable)getResources().getDrawable(R.mipmap.bookcover)).getBitmap();
+ /*ShelfBookObj test = new ShelfBookObj("5816b415b06d1d32157790b1", "圣墟", bitmap, 0, "testAddress", 0, "testDescription");
+ DatabaseControl.getInstance(getActivity()).addShelfBook(test);*/
+ myBooks = DatabaseControl.getInstance(getActivity()).getAllShelfBook();
+ //System.out.println("getBookSize: " + myBooks.size());
+ }
+
+ // 设置页面的 RecyclerView
+ private void setRecyclerView() {
+ // 获取页面的 RecyclerView 控件
+ recyclerView = view.findViewById(R.id.fragment_book_shelf_recyclerview);
+
+ // 设置 RecyclerView 的布局方式
+ recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
+
+ // 设置 RecyclerAdapter
+ adapter = new MyRecyclerViewAdapter(getActivity(), R.layout.item_book, myBooks) {
+ @Override
+ public void convert(MyViewHolder holder, ShelfBookObj shelfBookObj) {
+ // 书名
+ TextView bookName = holder.getView(R.id.item_book_name);
+ bookName.setText(shelfBookObj.getName());
+ // 封面
+ ImageView imageView = holder.getView(R.id.item_book_cover);
+ imageView.setImageBitmap(shelfBookObj.getIcon());
+ // 作者
+ TextView author = holder.getView(R.id.item_book_author);
+ author.setText(shelfBookObj.getAuthor());
+ // 类型
+ TextView major = holder.getView(R.id.item_book_type);
+ major.setText(shelfBookObj.getMajor());
+ // 简介
+ TextView intro = holder.getView(R.id.item_book_intro);
+ String str = shelfBookObj.getDescription();
+ if (str.length() > 50) str = str.substring(0, 50);
+ str += "...";
+ intro.setText(str);
+ }
+ };
+ adapter.refresh(myBooks);
+ adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
+ @Override
+ public void onClick(int position) {
+ Intent intent = new Intent(getActivity(), ReadPageActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putString("bookid", myBooks.get(position).getBookId());
+ bundle.putInt("currentChapter", myBooks.get(position).getReadChapter());
+ bundle.putString("bookname", myBooks.get(position).getName());
+ System.out.println("传进去当前阅读章节数为:" + myBooks.get(position).getReadChapter());
+ intent.putExtras(bundle);
+ startActivity(intent);
+ }
+
+ @Override
+ public void onLongClick(final int position) {
+ // 长按弹出对话框
+ AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity());
+ dialog.setMessage("确定要从书架移除" + myBooks.get(position).getName() + "吗?");
+ dialog.setNegativeButton("NO", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+
+ }
+ });
+ dialog.setPositiveButton("YES", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ DatabaseControl.getInstance(getActivity()).deleteShelfBook(myBooks.get(position).getBookId());
+ getMyBooks();
+ setRecyclerView();
+ }
+ });
+ dialog.show();
+ }
+ });
+ recyclerView.setAdapter(adapter);
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/CategoryFragment.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/CategoryFragment.java
new file mode 100644
index 0000000..e312b4f
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/CategoryFragment.java
@@ -0,0 +1,96 @@
+package com.example.Fragment;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.view.ViewPager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.example.R;
+
+// 分类的界面
+public class CategoryFragment extends Fragment {
+ private RadioGroup RG;
+ private RadioButton maleRB;
+ private RadioButton femaleRB;
+ private ViewPager viewPager;
+ private List fragmentList = new ArrayList<>();
+ private TabFragmentPagerAdapter fragmentPagerAdapter;
+
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.fragment_category, null);
+ //初始化控件
+ RG = view.findViewById(R.id.category_RG);
+ viewPager = view.findViewById(R.id.category_viewPager);
+ maleRB = view.findViewById(R.id.category_RB_male);
+ femaleRB = view.findViewById(R.id.category_RB_female);
+
+ //初始化Fragment
+ fragmentList.clear();
+ MaleInCategoryFragment maleFragment = new MaleInCategoryFragment();
+ MaleInCategoryFragment femaleFragment = new MaleInCategoryFragment();
+ Bundle bundle1 = new Bundle();
+ bundle1.putBoolean("isMale", true);
+ maleFragment.setArguments(bundle1);
+ fragmentList.add(maleFragment);
+ Bundle bundle2 = new Bundle();
+ bundle2.putBoolean("isMale", false);
+ femaleFragment.setArguments(bundle2);
+ fragmentList.add(femaleFragment);
+
+ viewPager.setOnPageChangeListener(new MyPagerChangeListener());
+ fragmentPagerAdapter = new TabFragmentPagerAdapter(getChildFragmentManager(), fragmentList);
+ viewPager.setAdapter(fragmentPagerAdapter);
+ viewPager.setCurrentItem(0);
+ viewPager.setOffscreenPageLimit(1);
+
+ RG.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ switch (checkedId) {
+ case R.id.category_RB_male:
+ viewPager.setCurrentItem(0);
+ break;
+ case R.id.category_RB_female:
+ viewPager.setCurrentItem(1);
+ break;
+ }
+ }
+ });
+
+ return view;
+ }
+
+ //设置一个ViewPager的监听事件,左右滑动ViewPager时进行处理
+ public class MyPagerChangeListener implements ViewPager.OnPageChangeListener {
+ @Override
+ public void onPageScrollStateChanged(int arg0) {
+ }
+
+ @Override
+ public void onPageScrolled(int arg0, float arg1, int arg2) {
+ }
+
+ @Override
+ public void onPageSelected(int arg0) {
+ switch (arg0) {
+ case 0:
+ maleRB.setChecked(true);
+ break;
+ case 1:
+ femaleRB.setChecked(true);
+ break;
+ }
+ }
+ }
+
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/DetailCategoryFragment.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/DetailCategoryFragment.java
new file mode 100644
index 0000000..b15d5f3
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/DetailCategoryFragment.java
@@ -0,0 +1,320 @@
+package com.example.Fragment;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.annotation.NonNull;
+import android.support.v4.app.Fragment;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ProgressBar;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.example.Activity.BookDetailActivity;
+import com.example.R;
+import com.example.RecyclerView.CateRecyclerViewAdapter;
+import com.example.Object.AllRankingObj;
+import com.example.Object.BookObj;
+import com.example.Object.CategoryObj;
+import com.example.Object.SingleRankingObj;
+import com.example.Service.BookService;
+
+// 具体分类和榜单的Fragment
+public class DetailCategoryFragment extends Fragment {
+ private boolean isRanking; //排行榜/具体分类
+ private boolean isMale; //男生/女生
+ private String title; //榜单名/类型名
+ private String type; //具体榜单/具体类型
+
+ private RecyclerView recyclerView;
+ private ProgressBar progressBar;
+ private SwipeRefreshLayout swipeRefreshLayout;
+ private List bookObjList = new ArrayList<>();
+ private CateRecyclerViewAdapter recyclerViewAdapter;
+
+ //具体榜单的id
+ private String rankingid = "";
+
+ private int total; //书籍总数
+ private int lastVisibleItem = 0;
+ private final int PAGE_COUNT = 10;
+
+ Handler handler = new Handler();
+ BookService bookService = BookService.getBookService();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.isRanking = getArguments().getBoolean("isRanking");
+ this.isMale = getArguments().getBoolean("isMale");
+ if (isRanking == false) {
+ Log.d("type in args:", getArguments().getString("type"));
+ switch (getArguments().getString("type")) {
+ case "热门":
+ this.type = "hot";
+ break;
+ case "新书":
+ this.type = "new";
+ break;
+ case "好评":
+ this.type = "reputation";
+ break;
+ case "完结":
+ this.type = "over";
+ break;
+ }
+ }
+ else this.type = getArguments().getString("type");
+ this.title = getArguments().getString("title");
+
+ initBookList();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.fragment_detail_category, null);
+
+ progressBar = view.findViewById(R.id.detail_category_progressBar);
+ swipeRefreshLayout = view.findViewById(R.id.detail_category_swipeRefresh);
+
+ //设置RecyclerView
+ recyclerView = view.findViewById(R.id.detail_category_recyclerView);
+ recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
+ recyclerViewAdapter = new CateRecyclerViewAdapter(getBookList(0, PAGE_COUNT), getActivity(), getBookList(0, PAGE_COUNT).size() > 0 ? true : false, isRanking);
+ recyclerViewAdapter.setOnItemClickListener(new CateRecyclerViewAdapter.OnItemClickListener() {
+ @Override
+ public void onClick(int position) {
+ //跳转到书籍详情界面
+ Intent intent = new Intent(getActivity(), BookDetailActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putSerializable("bookobj", bookObjList.get(position));
+ intent.putExtras(bundle);
+ startActivity(intent);
+ }
+ });
+ recyclerView.setAdapter(recyclerViewAdapter);
+
+ //设置下拉显示的动画颜色
+ swipeRefreshLayout.setColorSchemeColors(Color.RED, Color.BLUE);
+ //下拉刷新的回调事件
+ swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ //数据刷新
+ initBookList();
+ }
+ });
+
+ //设置滑动监听器
+ recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
+ super.onScrollStateChanged(recyclerView, newState);
+ // 在newState为滑到底部时
+ if (newState == RecyclerView.SCROLL_STATE_IDLE) {
+ // 如果没有隐藏footView,那么最后一个条目的位置就比我们的getItemCount少1
+ if (recyclerViewAdapter.isFadeTips() == false && lastVisibleItem + 1 == recyclerViewAdapter.getItemCount()) {
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ // 然后调用updateRecyclerview方法更新RecyclerView
+ updateRecyclerView(recyclerViewAdapter.getLastPosition(), recyclerViewAdapter.getLastPosition() + PAGE_COUNT);
+ }
+ }, 500);
+ }
+
+ // 如果隐藏了提示条,我们又上拉加载时,那么最后一个条目就要比getItemCount要少2
+ if (recyclerViewAdapter.isFadeTips() == true && lastVisibleItem + 2 == recyclerViewAdapter.getItemCount()) {
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ // 然后调用updateRecyclerview方法更新RecyclerView
+ updateRecyclerView(recyclerViewAdapter.getLastPosition(), recyclerViewAdapter.getLastPosition() + PAGE_COUNT);
+ }
+ }, 500);
+ }
+ }
+ }
+
+ @Override
+ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+ super.onScrolled(recyclerView, dx, dy);
+ // 在滑动完成后,拿到最后一个可见的item的位置
+ LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
+ lastVisibleItem = layoutManager.findLastVisibleItemPosition();
+ }
+ });
+
+ return view;
+ }
+
+ void initBookList() {
+ bookObjList.clear();
+ //检查网络连接
+ ConnectivityManager connect = (ConnectivityManager)getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo info = connect.getActiveNetworkInfo();
+ if (info == null || !info.isAvailable()) {
+ Toast.makeText(getActivity(), "网络连接状况:未连接", Toast.LENGTH_LONG).show();
+ return;
+ }
+ if (isRanking) getRankingBookList();
+ else getCateBookList();
+ }
+
+ //获取排行榜书单
+ void getRankingBookList() {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ AllRankingObj allRankingObj = bookService.getAllRankingObj();
+ if (allRankingObj == null || allRankingObj.isOk() == false) {
+ Looper.prepare();
+ Toast.makeText(getContext(), "获取数据失败", Toast.LENGTH_LONG).show();
+ Looper.loop();
+ Log.d("error", "获取全部排行榜失败");
+ return;
+ }
+ //获取具体榜单的id
+ if (isMale) { //男生
+ for (AllRankingObj.subClass subClass : allRankingObj.getMaleList()) {
+ if (subClass.getShortTitle().equals(title)) {
+ if (title.equals("热搜榜")) rankingid = subClass.getId();
+ else {
+ if (type.equals("周榜")) rankingid = subClass.getId();
+ else if (type.equals("月榜")) rankingid = subClass.getMonthRank();
+ else if (type.equals("总榜")) rankingid = subClass.getTotalRank();
+ else {
+ System.exit(1);
+ Log.d("error", "榜单名错误!");
+ }
+ }
+ break;
+ }
+ }
+ }
+ else { //女生
+ for (AllRankingObj.subClass subClass : allRankingObj.getFemaleList()) {
+ if (subClass.getShortTitle().equals(title)) {
+ if (title.equals("热搜榜")) rankingid = subClass.getId();
+ else {
+ if (type.equals("周榜")) rankingid = subClass.getId();
+ else if (type.equals("月榜")) rankingid = subClass.getMonthRank();
+ else if (type.equals("总榜")) rankingid = subClass.getTotalRank();
+ else {
+ System.exit(1);
+ Log.d("error", "榜单名不符!");
+ }
+ }
+ break;
+ }
+ }
+ }
+ //得到id后再获取具体榜单的书籍信息
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ SingleRankingObj singleRankingObj = bookService.getSingleRankingObj(rankingid);
+ if (singleRankingObj == null || singleRankingObj.isOk() == false) {
+ Looper.prepare();
+ Toast.makeText(getContext(), "获取失败", Toast.LENGTH_LONG).show();
+ Looper.loop();
+ Log.d("error", "获取单一排行榜失败");
+ return;
+ }
+ List objList = singleRankingObj.getRanking().getBookList();
+ total = singleRankingObj.getRanking().getTotal();
+ for (int i = 0; i < objList.size(); ++i) {
+ BookObj bookObj = objList.get(i);
+ String intro = bookObj.getShortIntro();
+ if (intro.length() > 50) intro = intro.substring(0, 50);
+ intro += "...";
+ bookObj.setShortIntro(intro);
+ bookObjList.add(bookObj);
+ }
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ updateRecyclerView(0, PAGE_COUNT);
+ progressBar.setVisibility(View.GONE);
+ //数据加载完毕时取消动画
+ swipeRefreshLayout.setRefreshing(false);
+ Toast.makeText(getActivity(), "数据刷新完成", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ }).start();
+ }
+ }).start();
+ }
+
+ //获取具体分类书单
+ void getCateBookList() {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ String gender = (isMale == true) ? "male" : "female";
+ Log.d("type:", "" + type);
+ final CategoryObj categoryObj = bookService.getBooksByCategoty(type, title, 0, 30000, gender);
+ if (categoryObj == null || categoryObj.isOk() == false) {
+ Looper.prepare();
+ Toast.makeText(getContext(), "获取数据失败", Toast.LENGTH_LONG).show();
+ Looper.loop();
+ Log.d("error", "获取主题书单列表失败");
+ return;
+ }
+ total = categoryObj.getTotal();
+ for (BookObj bookObj : categoryObj.getBooks()) {
+ if (bookObj.getShortIntro().length() > 50){
+ String intro = bookObj.getShortIntro();
+ intro = intro.substring(0, 50);
+ intro += "...";
+ bookObj.setShortIntro(intro);
+ }
+ bookObjList.add(bookObj);
+ }
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ //Toast.makeText(getActivity(), "" + bookObjList.size() + " | " + total + " | " + categoryObj.getBooks().size(), Toast.LENGTH_SHORT).show();
+ updateRecyclerView(0, PAGE_COUNT);
+ progressBar.setVisibility(View.GONE);
+ //数据加载完毕时取消动画
+ swipeRefreshLayout.setRefreshing(false);
+ Toast.makeText(getActivity(), "数据刷新完成", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ }).start();
+ }
+
+ private void updateRecyclerView(int fromIndex, int toIndex) {
+ List newDatas = getBookList(fromIndex, toIndex);
+ if (newDatas.size() > 0) {
+ recyclerViewAdapter.updateList(newDatas, true);
+ } else {
+ recyclerViewAdapter.updateList(null, false);
+ }
+ }
+
+ List getBookList(int from, int to) {
+ List newList = new ArrayList<>();
+ for (int i = from; i < to && i < bookObjList.size(); ++i) {
+ newList.add(bookObjList.get(i));
+ }
+ return newList;
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/MaleInCategoryFragment.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/MaleInCategoryFragment.java
new file mode 100644
index 0000000..4e7e087
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/MaleInCategoryFragment.java
@@ -0,0 +1,272 @@
+package com.example.Fragment;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+import android.os.Looper;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.example.Activity.CategoryActivity;
+import com.example.R;
+import com.example.RecyclerView.CategoryRecyObj;
+import com.example.RecyclerView.MyRecyclerViewAdapter;
+import com.example.RecyclerView.MyViewHolder;
+import com.example.Object.ClassificationObj1;
+import com.example.Object.ClassificationObj2;
+import com.example.Service.BookService;
+
+import static android.app.ProgressDialog.show;
+
+// 分类(男生/女生)界面
+public class MaleInCategoryFragment extends Fragment {
+ // Fragment 的 视图
+ View view;
+
+ // Fragment内的RecyclerView
+ RecyclerView recyclerView; // recyclerview
+ List myCategories; // recyclerview中的书籍数据
+ MyRecyclerViewAdapter adapter; // recyclerview 的 adapter
+
+ // 判断是女性分类还是男性分类
+ boolean isMale = true;
+
+ // 分类数据OBJ
+ private ClassificationObj1 classificationObj1;
+ private ClassificationObj2 classificationObj2;
+
+ // bookservice 类 (用单例模式获取)
+ private BookService bookService;
+
+ // 一级分类(写死)
+ public static String[] maleCategoriesName = {"玄幻", "奇幻", "武侠", "仙侠", "都市", "职场", "历史", "军事", "游戏", "竞技", "科幻", "灵异", "同人", "轻小说"};
+ public static String[] femaleCategoriesName = {"古代言情", "现代言情", "青春校园", "纯爱", "玄幻奇幻", "武侠仙侠", "科幻", "游戏竞技", "悬疑灵异", "同人", "女尊", "莉莉"};
+ String[] maleCategoriesBookCount = {"(56万本)", "(6.3万本)", "(4.8万本)", "(15万本)", "(38万本)", "(1.8万本)", "(7.9万本)", "(1.6万本)", "(8.9万本)", "(6648本)", "(13万本)", "(5.3万本)", "(4.6万本)", "(9761本)"};
+ String[] femaleCategoriesBookCount = {"(57万本)", "(71万本)", "(15万本)", "(13万本)", "(15万本)", "(7.8万本)", "(1.8万本)", "(6553本)", "(2.0万本)", "(12万本)", "(2.2万本)", "(2.6万本)"};
+
+
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // 获取传给Fragment的参数
+ Bundle bundle = getArguments();
+ this.isMale = bundle.getBoolean("isMale");
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ // 获取 Fragment 视图
+ view = inflater.inflate(R.layout.fragment_male_in_category, null);
+
+ // 获取分类数据
+ getMyCategories();
+
+ // 设置 RecyclerView
+ setRecyclerView();
+
+ // Inflate the layout for this fragment
+ return view;
+ }
+
+
+
+
+ // 设置 RecyclerView
+ private void setRecyclerView() {
+ // 获取页面的 RecyclerView 控件
+ recyclerView = view.findViewById(R.id.fragment_male_in_category_recyclerview);
+
+ // 设置 RecyclerView 的布局方式
+ recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2));
+
+ // 设置 Adapter 配置
+ adapter = new MyRecyclerViewAdapter(getActivity(), R.layout.item_category, myCategories) {
+ @Override
+ public void convert(MyViewHolder holder, CategoryRecyObj categoryRecyObj) {
+ TextView categoryName = holder.getView(R.id.item_category_name);
+ categoryName.setText(categoryRecyObj.getCategoryName());
+ TextView categoryBookCount = holder.getView(R.id.item_category_count);
+ categoryBookCount.setText(categoryRecyObj.getBookCount());
+ }
+ };
+
+ // 每个主类按钮的点击响应处理
+ adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
+ @Override
+ public void onClick(int position) {
+ //跳转具体分类界面
+ Intent intent = new Intent(getActivity(), CategoryActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putBoolean("isRanking", false);
+ bundle.putBoolean("isMale", isMale);
+ if (isMale) bundle.putString("title", maleCategoriesName[position]);
+ else bundle.putString("title", femaleCategoriesName[position]);
+ intent.putExtras(bundle);
+ startActivity(intent);
+
+ /*System.out.println("onClick");
+
+ // 分类信息尚未获取,调用BookService去获取
+ if(classificationObj2 == null) {
+ boolean isNetWorkConnected = isNetWorkConnected(getActivity());
+ // 有网络
+ if(isNetWorkConnected) {
+ System.out.println("网络连接状况:已连接");
+ // 调用子线程进行访问,获取一级、二级分类信息
+ Thread thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ classificationObj2 = bookService.getClassification2();
+ Looper.prepare();
+ if(classificationObj2 == null) {
+ Toast.makeText(getActivity(), "还是获取失败啊啊啊啊", Toast.LENGTH_SHORT).show();
+ }
+ Looper.loop();
+ }
+ });
+ thread.start();
+
+ }
+ // 无网络
+ else {
+ System.out.println("网络连接状况:未连接");
+ Toast.makeText(getActivity(), "网络连接状况:未连接", Toast.LENGTH_SHORT).show();
+ }
+ }
+ // 已经获取过分类信息
+ else {
+ // 获取点击到的一级分类以及对应的二级分类数据
+ String major;
+ String[] mins;
+ if(isMale) {
+ major = maleCategoriesName[position];
+ mins = classificationObj2.getMaleList().get(position).getMins();
+ }
+ else {
+ major = femaleCategoriesName[position];
+ mins = classificationObj2.getFemaleList().get(position).getMins();
+ }
+ // 获取失败
+ if(major == null || mins == null) {
+ Toast.makeText(getActivity(), "获取失败", Toast.LENGTH_SHORT).show();
+ }
+ // 获取数据成功
+ else {
+ //Toast.makeText(getActivity(), major + "二级分类框弹出", Toast.LENGTH_SHORT).show();
+ // 弹出一个二级分类框
+ Dialog dialog = new Dialog(getActivity());
+ dialog.setContentView(R.layout.dialog_category);
+ // 二级分类RecyclerView
+ RecyclerView dialog_recyclerview = dialog.findViewById(R.id.dialog_category_recyclerview);
+ // 二级分类数据初始化
+ List dialog_categories = new ArrayList<>();
+ for(int i = 0; i < mins.length; i++)
+ dialog_categories.add(new CategoryRecyObj(mins[i], ""));
+
+ // 设置 Adapter
+ MyRecyclerViewAdapter dialog_adapter = new MyRecyclerViewAdapter(getActivity(), R.layout.item_category, dialog_categories) {
+ @Override
+ public void convert(MyViewHolder holder, CategoryRecyObj categoryRecyObj) {
+ TextView categoryName = holder.getView(R.id.item_category_name);
+ categoryName.setText(categoryRecyObj.getCategoryName());
+ TextView categoryBookCount = holder.getView(R.id.item_category_count);
+ categoryBookCount.setVisibility(View.GONE);
+ }
+ };
+ // 适配 Adapter
+ dialog_recyclerview.setAdapter(dialog_adapter);
+ // 设置 RecyclerView 布局
+ dialog_recyclerview.setLayoutManager(new LinearLayoutManager(getActivity()));
+
+ // 设置 dialog 属性并显示
+ dialog.setCancelable(true);
+ dialog.show();
+ }
+
+
+
+ }*/
+ }
+
+ @Override
+ public void onLongClick(int position) {
+
+ }
+ });
+
+ // 给 RecyclerView 适配 Adapter
+ recyclerView.setAdapter(adapter);
+
+ }
+
+ // 获取分类数据
+ private void getMyCategories() {
+ boolean isNetWorkConnected = isNetWorkConnected(getActivity());
+ bookService = BookService.getBookService();
+ if(isNetWorkConnected) {
+ System.out.println("网络连接状况:已连接");
+ // 调用子线程进行访问,获取一级、二级分类信息
+ Thread thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ classificationObj2 = bookService.getClassification2();
+ Looper.prepare();
+ if(classificationObj2 == null) {
+ Toast.makeText(getActivity(), "获取失败", Toast.LENGTH_SHORT).show();
+ }
+ Looper.loop();
+ }
+ });
+ thread.start();
+ }
+ else {
+ System.out.println("网络连接状况:未连接");
+ Toast.makeText(getActivity(), "网络连接状况:未连接", Toast.LENGTH_SHORT).show();
+ }
+ myCategories = new ArrayList<>();
+ // 男生向小说分类
+ if(isMale) {
+ for(int i = 0; i < maleCategoriesName.length; i++) {
+ CategoryRecyObj c = new CategoryRecyObj(maleCategoriesName[i], maleCategoriesBookCount[i]);
+ myCategories.add(c);
+ }
+ }
+ // 女生向小说分类
+ else {
+ for(int i = 0; i < femaleCategoriesName.length; i++) {
+ CategoryRecyObj c = new CategoryRecyObj(femaleCategoriesName[i], femaleCategoriesBookCount[i]);
+ myCategories.add(c);
+ }
+ }
+ }
+
+ // 辅助函数:判断网络是否连接
+ public boolean isNetWorkConnected(Context context) {
+ if (context != null) {
+ ConnectivityManager mConnectivityManager = (ConnectivityManager) context
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
+ if (mNetworkInfo != null) {
+ return mNetworkInfo.isConnected();
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/RankingFragment.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/RankingFragment.java
new file mode 100644
index 0000000..276e50b
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/RankingFragment.java
@@ -0,0 +1,131 @@
+package com.example.Fragment;
+
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.example.Activity.CategoryActivity;
+import com.example.R;
+import com.example.RecyclerView.MyRecyclerViewAdapter;
+import com.example.RecyclerView.MyViewHolder;
+
+// 排行榜界面
+public class RankingFragment extends Fragment {
+ private boolean isMale; //男生/女生
+ private int color1 = Color.parseColor("#F5D6D6");//最热榜
+ private int color2 = Color.parseColor("#D8F8C2");//热搜榜
+ private int color3 = Color.parseColor("#F9EBB0");//潜力榜
+ private int color4 = Color.parseColor("#DBB5F4");//留存榜
+ private int color5 = Color.parseColor("#CEFDFD");//完结榜
+
+ private RecyclerView recyclerView;
+ private List list = new ArrayList<>();
+ private MyRecyclerViewAdapter adapter;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Bundle bundle = getArguments();
+ this.isMale = bundle.getBoolean("isMale");
+ if (isMale) {
+ list.add("最热榜");
+ list.add("热搜榜");
+ list.add("潜力榜");
+ list.add("留存榜");
+ list.add("完结榜");
+ }
+ else {
+ list.add("热搜榜");
+ list.add("留存榜");
+ list.add("最热榜");
+ list.add("潜力榜");
+ list.add("完结榜");
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.fragment_ranking, null);
+ recyclerView = view.findViewById(R.id.ranking_recycler);
+ //设置recyclerView的显示
+ recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
+ adapter = new MyRecyclerViewAdapter(getActivity(), R.layout.item_ranking, list) {
+ @Override
+ public void convert(MyViewHolder holder, String type) {
+ Bitmap bitmap = null;
+ int color = color1;
+ switch (type) {
+ case "最热榜":
+ if (isMale) bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.male_icon1, null);
+ else bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.female_icon1, null);
+ color = color1;
+ break;
+ case "热搜榜":
+ if (isMale) bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.male_icon2, null);
+ else bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.female_icon2, null);
+ color = color2;
+ break;
+ case "潜力榜":
+ if (isMale) bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.male_icon3, null);
+ else bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.female_icon3, null);
+ color = color3;
+ break;
+ case "留存榜":
+ if (isMale) bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.male_icon4, null);
+ else bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.female_icon4, null);
+ color = color4;
+ break;
+ case "完结榜":
+ if (isMale) bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.male_icon5, null);
+ else bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.female_icon5, null);
+ color = color5;
+ break;
+ }
+ ImageView imageView = holder.getView(R.id.ranking_item_image);
+ imageView.setImageBitmap(bitmap);
+ TextView textView = holder.getView(R.id.ranking_item_text);
+ textView.setText(type);
+ RelativeLayout layout = holder.getView(R.id.ranking_item_right);
+ layout.setBackgroundColor(color);
+ }
+ };
+ //设置RecyclerView的点击响应事件
+ adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
+ @Override
+ public void onClick(int position) {
+ //跳转到对应榜单界面
+ Intent intent = new Intent(getActivity(), CategoryActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putBoolean("isRanking", true);
+ bundle.putBoolean("isMale", isMale);
+ bundle.putString("title", list.get(position));
+ intent.putExtras(bundle);
+ startActivity(intent);
+ }
+
+ @Override
+ public void onLongClick(int position) {
+
+ }
+ });
+ recyclerView.setAdapter(adapter);
+
+ return view;
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/ReadPageFragment.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/ReadPageFragment.java
new file mode 100644
index 0000000..77652d7
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/ReadPageFragment.java
@@ -0,0 +1,73 @@
+package com.example.Fragment;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import com.example.R;
+
+// 阅读界面的Fragment
+public class ReadPageFragment extends Fragment {
+ // 页面数据
+ private String title; //章节名
+ private String content; //本章内容
+ int day_or_night_status; //日间或夜间模式
+ int textSize; //字体大小
+
+ // 帧页面View
+ View view;
+ // 帧页面控件
+ private TextView titile_control; // 标题
+ private TextView content_control; // 阅读页内容
+ private FrameLayout whole_layout_control; // 整个框页面
+
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.content = getArguments().getString("content");
+ this.title = getArguments().getString("title");
+ this.day_or_night_status = getArguments().getInt("day_or_night_status");
+ this.textSize = getArguments().getInt("textSize");
+ //System.out.println("日间夜间:" + day_or_night_status);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ // 获取帧页面View
+ view = inflater.inflate(R.layout.fragment_read_page, null);
+
+ // 获取页面控件
+ init_page_control();
+
+ // 设置页面内容
+ init_page_info();
+
+ //todo
+ return view;
+ }
+
+ private void init_page_info() {
+ titile_control.setText(title); // 设置标题
+ content_control.setText(content); // 设置阅读页内容
+ content_control.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
+ if(day_or_night_status == 0) {
+ whole_layout_control.setBackgroundColor(getResources().getColor(R.color.PapayaWhip));
+ }
+ else whole_layout_control.setBackgroundColor(getResources().getColor(R.color.nightBackGround));
+ //progress_control.setText(Integer.toString(currentChapter+1) + "/" + Integer.toString(totalChapter+1));
+ }
+
+ private void init_page_control() {
+ titile_control = view.findViewById(R.id.fragment_read_page_title);
+ content_control = view.findViewById(R.id.fragment_read_page_content);
+ whole_layout_control = view.findViewById(R.id.fragment_read_page_whole_layout);
+ //progress_control = view.findViewById(R.id.fragment_read_page_process);
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/TabFragmentPagerAdapter.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/TabFragmentPagerAdapter.java
new file mode 100644
index 0000000..644a71a
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/TabFragmentPagerAdapter.java
@@ -0,0 +1,28 @@
+package com.example.Fragment;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+
+import java.util.List;
+// 碎片适配器
+public class TabFragmentPagerAdapter extends FragmentPagerAdapter {
+ private FragmentManager fm;
+ private List list;
+
+ public TabFragmentPagerAdapter(FragmentManager fm, List list) {
+ super(fm);
+ this.fm = fm;
+ this.list = list;
+ }
+
+ @Override
+ public Fragment getItem(int i) {
+ return list.get(i);
+ }
+
+ @Override
+ public int getCount() {
+ return list.size();
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/TabFragmentStatePagerAdapter.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/TabFragmentStatePagerAdapter.java
new file mode 100644
index 0000000..509abe0
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/TabFragmentStatePagerAdapter.java
@@ -0,0 +1,33 @@
+package com.example.Fragment;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.view.PagerAdapter;
+
+import java.util.List;
+// 碎片状态适配器
+public class TabFragmentStatePagerAdapter extends android.support.v4.app.FragmentStatePagerAdapter {
+ private FragmentManager fm;
+ private List list;
+
+ public TabFragmentStatePagerAdapter(FragmentManager fm, List list) {
+ super(fm);
+ this.fm = fm;
+ this.list = list;
+ }
+
+ @Override
+ public int getItemPosition(Object object) {
+ return PagerAdapter.POSITION_NONE;
+ }
+
+ @Override
+ public Fragment getItem(int i) {
+ return list.get(i);
+ }
+
+ @Override
+ public int getCount() {
+ return list.size();
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/AllRankingObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/AllRankingObj.java
new file mode 100644
index 0000000..9706e25
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/AllRankingObj.java
@@ -0,0 +1,89 @@
+package com.example.Object;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+
+public class AllRankingObj {
+
+ // 男生
+ @SerializedName("male")
+ private List maleList;
+
+ // 女生
+ @SerializedName("female")
+ private List femaleList;
+
+ @SerializedName("ok")
+ private boolean ok;
+
+ public List getMaleList() {
+ return maleList;
+ }
+
+ public List getFemaleList() {
+ return femaleList;
+ }
+
+ public boolean isOk() {
+ return ok;
+ }
+
+ public class subClass {
+ // 周榜id
+ @SerializedName("_id")
+ private String id;
+
+ // 排行榜全名
+ @SerializedName("title")
+ private String title;
+
+ // 排行榜大图标
+ @SerializedName("cover")
+ private String cover;
+
+ @SerializedName("collapse")
+ private boolean collapse;
+
+ // 月榜id
+ @SerializedName("monthRank")
+ private String monthRank;
+
+ // 总榜id
+ @SerializedName("totalRank")
+ private String totalRank;
+
+ // 排行榜简称
+ @SerializedName("shortTitle")
+ private String shortTitle;
+
+ public String getId() {
+ return id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getCover() {
+ return cover;
+ }
+
+ public boolean isCollapse() {
+ return collapse;
+ }
+
+ public String getMonthRank() {
+ return monthRank;
+ }
+
+ public String getTotalRank() {
+ return totalRank;
+ }
+
+ public String getShortTitle() {
+ return shortTitle;
+ }
+ }
+
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/BookObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/BookObj.java
new file mode 100644
index 0000000..dfc3907
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/BookObj.java
@@ -0,0 +1,166 @@
+package com.example.Object;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.io.Serializable;
+
+// 书籍的对象
+public class BookObj implements Serializable {
+ // 书籍id
+ @SerializedName("_id")
+ private String id;
+
+ // 书籍标题
+ @SerializedName("title")
+ private String title;
+
+ // 书籍作者
+ @SerializedName("author")
+ private String author;
+
+ // 书籍介绍
+ @SerializedName("longIntro")
+ private String longIntro;
+
+ // 书籍简介
+ @SerializedName("shortIntro")
+ private String shortIntro;
+
+ // 书籍封面图
+ @SerializedName("cover")
+ private String cover;
+
+ @SerializedName("site")
+ private String site;
+
+ // 书籍一级分类
+ @SerializedName("majorCate")
+ private String majorCate;
+
+ // 书籍二级分类
+ @SerializedName("minorCate")
+ private String minorCate;
+
+ @SerializedName("sizetype")
+ private int sizetype;
+
+ @SerializedName("contentType")
+ private String contentType;
+
+ @SerializedName("allowMonthly")
+ private boolean allowMonthly;
+
+ @SerializedName("banned")
+ private int banned;
+
+ // 最近关注人数
+ @SerializedName("latelyFollower")
+ private int latelyFollower;
+
+ // 字数
+ @SerializedName("wordCount")
+ private int wordCount;
+
+ // 留存率
+ @SerializedName("retentionRatio")
+ private float retentionRatio;
+
+ // 最新章节
+ @SerializedName("lastChapter")
+ private String lastChapter;
+
+ @SerializedName("updated")
+ private String updated;
+
+ // 性别
+ @SerializedName("gender")
+ private String[] gender;
+
+ // 标签
+ @SerializedName("tags")
+ private String[] tags;
+
+ public String getId() {
+ return id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ public String getShortIntro() {
+ return shortIntro;
+ }
+
+ public void setShortIntro(String shortIntro) {
+ this.shortIntro = shortIntro;
+ }
+
+ public String getCover() {
+ return cover;
+ }
+
+ public String getSite() {
+ return site;
+ }
+
+ public String getMajorCate() {
+ return majorCate;
+ }
+
+ public String getMinorCate() {
+ return minorCate;
+ }
+
+ public int getSizetype() {
+ return sizetype;
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public boolean isAllowMonthly() {
+ return allowMonthly;
+ }
+
+ public String getLongIntro() {
+ return longIntro;
+ }
+
+ public String[] getGender() {
+ return gender;
+ }
+
+ public int getBanned() {
+ return banned;
+ }
+
+ public int getLatelyFollower() {
+ return latelyFollower;
+ }
+
+ public float getRetentionRatio() {
+ return retentionRatio;
+ }
+
+ public String getLastChapter() {
+ return lastChapter;
+ }
+
+ public String[] getTags() {
+ return tags;
+ }
+
+ public int getWordCount() {
+ return wordCount;
+ }
+
+ public String getUpdated() {
+ return updated;
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/CategoryObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/CategoryObj.java
new file mode 100644
index 0000000..21b5f6e
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/CategoryObj.java
@@ -0,0 +1,31 @@
+package com.example.Object;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+
+public class CategoryObj {
+ // 书籍总数
+ @SerializedName("total")
+ private int total;
+
+ // 书籍列表
+ @SerializedName("books")
+ private List books;
+
+ // 获取结果
+ @SerializedName("ok")
+ private boolean ok;
+
+ public int getTotal() {
+ return total;
+ }
+
+ public List getBooks() {
+ return books;
+ }
+
+ public boolean isOk() {
+ return ok;
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterLinkObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterLinkObj.java
new file mode 100644
index 0000000..771f848
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterLinkObj.java
@@ -0,0 +1,42 @@
+package com.example.Object;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.io.Serializable;
+
+public class ChapterLinkObj implements Serializable {
+ // 章节链接
+ @SerializedName("link")
+ private String link;
+
+ // 章节标题
+ @SerializedName("title")
+ private String title;
+
+ // 是否不可读
+ @SerializedName("unreadable")
+ private boolean unreadable;
+
+ public ChapterLinkObj() {
+ super();
+ }
+
+ public ChapterLinkObj(String _link, String _title, boolean _unreadable) {
+ link = _link;
+ title = _title;
+ unreadable = _unreadable;
+ }
+
+
+ public String getLink() {
+ return link;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public boolean isUnreadable() {
+ return unreadable;
+ }
+}
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterLinks.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterLinks.java
new file mode 100644
index 0000000..a01515b
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterLinks.java
@@ -0,0 +1,12 @@
+package com.example.Object;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class ChapterLinks implements Serializable {
+ public List chapterLinkList;
+
+ public List getChapterLinkList() {
+ return chapterLinkList;
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterObj.java
new file mode 100644
index 0000000..af626a8
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterObj.java
@@ -0,0 +1,43 @@
+package com.example.Object;
+
+import com.google.gson.annotations.SerializedName;
+
+// 获取章节内容返回结果
+public class ChapterObj {
+ // 请求结果
+ @SerializedName("ok")
+ private boolean ok;
+
+ @SerializedName("chapter")
+ private Chapter ichapter;
+
+ public boolean isOk() {
+ return ok;
+ }
+
+ public Chapter getIchapter() {
+ return ichapter;
+ }
+
+ /*
+ * 章节详情
+ */
+ public class Chapter {
+ // 章节标题
+ @SerializedName("title")
+ private String title;
+
+ // 章节内容
+ @SerializedName("body")
+ private String body;
+
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getBody() {
+ return body;
+ }
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ClassificationObj1.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ClassificationObj1.java
new file mode 100644
index 0000000..975cf85
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ClassificationObj1.java
@@ -0,0 +1,90 @@
+package com.example.Object;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+
+// 获取一级分类返回结果
+public class ClassificationObj1 {
+ // male分类
+ @SerializedName("male")
+ private List maleList;
+
+ // female分类
+ @SerializedName("female")
+ private List femaleList;
+
+ // picture分类
+ @SerializedName("picture")
+ private List picList;
+
+ @SerializedName("press")
+ private List pressList;
+
+ @SerializedName("ok")
+ private boolean ok;
+
+ public List getMaleList() {
+ return maleList;
+ }
+
+ public List getFemaleList() {
+ return femaleList;
+ }
+
+ public List getPicList() {
+ return picList;
+ }
+
+ public List getPressList() {
+ return pressList;
+ }
+
+ public boolean isOk() {
+ return ok;
+ }
+
+ // 一级分类
+ public class SubClass1 {
+ // 名称
+ @SerializedName("name")
+ private String name;
+
+ // 书籍数量
+ @SerializedName("bookCount")
+ private int bookCount;
+
+ // monthlyCount?
+ @SerializedName("monthlyCount")
+ private int monthlyCount;
+
+ // 分类图标
+ @SerializedName("icon")
+ private String icon;
+
+ // 封面图链接
+ @SerializedName("bookCover")
+ private String[] bookCover;
+
+ public String getName() {
+ return name;
+ }
+
+ public int getBookCount() {
+ return bookCount;
+ }
+
+ public int getMonthlyCount() {
+ return monthlyCount;
+ }
+
+ public String getIcon() {
+ return icon;
+ }
+
+ public String[] getBookCover() {
+ return bookCover;
+ }
+ }
+
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ClassificationObj2.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ClassificationObj2.java
new file mode 100644
index 0000000..ec449c0
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ClassificationObj2.java
@@ -0,0 +1,58 @@
+package com.example.Object;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+
+public class ClassificationObj2 {
+ @SerializedName("male")
+ private List maleList;
+
+ @SerializedName("female")
+ private List femaleList;
+
+ @SerializedName("picture")
+ private List picList;
+
+ @SerializedName("press")
+ private List pressList;
+
+ @SerializedName("ok")
+ private boolean ok;
+
+ public List getMaleList() {
+ return maleList;
+ }
+
+ public List getFemaleList() {
+ return femaleList;
+ }
+
+ public List getPicList() {
+ return picList;
+ }
+
+ public List getPressList() {
+ return pressList;
+ }
+
+ public boolean isOk() {
+ return ok;
+ }
+
+ public class SubClass2 {
+ @SerializedName("major")
+ private String major;
+
+ @SerializedName("mins")
+ private String[] mins;
+
+ public String getMajor() {
+ return major;
+ }
+
+ public String[] getMins() {
+ return mins;
+ }
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/CptListObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/CptListObj.java
new file mode 100644
index 0000000..5399d21
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/CptListObj.java
@@ -0,0 +1,64 @@
+package com.example.Object;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+
+// 获取章节列表返回结果
+public class CptListObj {
+ // 请求结果
+ @SerializedName("ok")
+ private boolean ok;
+
+ @SerializedName("mixToc")
+ private mixToc imixToc;
+
+ public boolean isOk() {
+ return ok;
+ }
+
+ public mixToc getImixToc() {
+ return imixToc;
+ }
+
+ /*
+ * 章节列表
+ */
+ public class mixToc {
+ @SerializedName("_id")
+ private String _id;
+ // 书籍id
+ @SerializedName("book")
+ private String book;
+ // 章节数
+ @SerializedName("chaptersCount1")
+ private int chaptersCount;
+ // 章节列表
+ @SerializedName("chapters")
+ public List chapterLinks;
+ // 更新时间
+ @SerializedName("updated")
+ private String updated;
+
+ public String get_id() {
+ return _id;
+ }
+
+ public String getBook() {
+ return book;
+ }
+
+ public int getChaptersCount() {
+ return chaptersCount;
+ }
+
+ public List getChapterLinks() {
+ return chapterLinks;
+ }
+
+ public String getUpdated() {
+ return updated;
+ }
+
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/FuzzySearchResultObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/FuzzySearchResultObj.java
new file mode 100644
index 0000000..3e213c8
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/FuzzySearchResultObj.java
@@ -0,0 +1,26 @@
+package com.example.Object;
+
+import com.google.gson.annotations.SerializedName;
+
+public class FuzzySearchResultObj {
+ @SerializedName("code")
+ private int code;
+
+ @SerializedName("msg")
+ private String msg;
+
+ @SerializedName("data")
+ private String[] data;
+
+ public int getCode() {
+ return code;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+
+ public String[] getData() {
+ return data;
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/RecomListObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/RecomListObj.java
new file mode 100644
index 0000000..602a8b8
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/RecomListObj.java
@@ -0,0 +1,16 @@
+package com.example.Object;
+
+import java.io.Serializable;
+import java.util.List;
+//
+public class RecomListObj implements Serializable {
+ private List bookObjs;
+
+ public RecomListObj(List bookObjs) {
+ this.bookObjs = bookObjs;
+ }
+
+ public List getBookObjs() {
+ return bookObjs;
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/SearchResultObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/SearchResultObj.java
new file mode 100644
index 0000000..88f496d
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/SearchResultObj.java
@@ -0,0 +1,185 @@
+package com.example.Object;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+// 搜索结果对象
+public class SearchResultObj {
+ // 书籍列表
+ @SerializedName("books")
+ private List bookList;
+
+ // 总数
+ @SerializedName("total")
+ private int total;
+
+ @SerializedName("ok")
+ private boolean ok;
+
+ public List getBookList() {
+ return bookList;
+ }
+
+ public int getTotal() {
+ return total;
+ }
+
+ public boolean isOk() {
+ return ok;
+ }
+
+ public class book {
+ // 书籍id
+ @SerializedName("_id")
+ private String _id;
+
+ @SerializedName("hasCp")
+ private boolean hasCp;
+
+ // 书名
+ @SerializedName("title")
+ private String title;
+
+ @SerializedName("aliases")
+ private String aliases;
+
+ // 一级分类
+ @SerializedName("cat")
+ private String cat;
+
+ // 作者
+ @SerializedName("author")
+ private String author;
+
+ @SerializedName("site")
+ private String site;
+
+ // 封面
+ @SerializedName("cover")
+ private String cover;
+
+ // 简介
+ @SerializedName("shortIntro")
+ private String shortIntro;
+
+ // 最新章节
+ @SerializedName("lastChapter")
+ private String lastChapter;
+
+ // 留存率
+ @SerializedName("retentionRatio")
+ private float retentionRatio;
+
+ @SerializedName("banned")
+ private int banned;
+
+ @SerializedName("allowMonthly")
+ private boolean allowMonthly;
+
+ // 关注人数
+ @SerializedName("latelyFollower")
+ private int latelyFollower;
+
+ // 字数
+ @SerializedName("wordCount")
+ private int wordCount;
+
+ // 类型
+ @SerializedName("contentType")
+ private String contentType;
+
+ @SerializedName("superscript")
+ private String superscript;
+
+ @SerializedName("sizetype")
+ private int sizetype;
+
+ @SerializedName("highlight")
+ private highlight mhighlight;
+
+ public String get_id() {
+ return _id;
+ }
+
+ public boolean isHasCp() {
+ return hasCp;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getAliases() {
+ return aliases;
+ }
+
+ public String getCat() {
+ return cat;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ public String getSite() {
+ return site;
+ }
+
+ public String getCover() {
+ return cover;
+ }
+
+ public String getShortIntro() {
+ return shortIntro;
+ }
+
+ public String getLastChapter() {
+ return lastChapter;
+ }
+
+ public float getRetentionRatio() {
+ return retentionRatio;
+ }
+
+ public int getBanned() {
+ return banned;
+ }
+
+ public boolean isAllowMonthly() {
+ return allowMonthly;
+ }
+
+ public int getLatelyFollower() {
+ return latelyFollower;
+ }
+
+ public int getWordCount() {
+ return wordCount;
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public String getSuperscript() {
+ return superscript;
+ }
+
+ public int getSizetype() {
+ return sizetype;
+ }
+
+ public highlight getMhighlight() {
+ return mhighlight;
+ }
+
+ public class highlight {
+ @SerializedName("title")
+ private String[] title;
+
+ public String[] getTitle() {
+ return title;
+ }
+ }
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ShelfBookObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ShelfBookObj.java
new file mode 100644
index 0000000..7cea380
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ShelfBookObj.java
@@ -0,0 +1,109 @@
+package com.example.Object;
+
+import android.graphics.Bitmap;
+// 书架书籍对象
+public class ShelfBookObj {
+ String bookId; //id
+ private Bitmap icon; //图标
+ private String iconURL; //图标网络url
+ private String name; //书名
+ private String description; //描述
+ private String author; //作者
+ private String major; //一级分类
+ int type; //0代表网络图片,1代表本地图片
+ private String address; //本地书籍url
+ private int readChapter; //阅读到的章节
+
+ public ShelfBookObj(String bookId, String name, Bitmap icon, String iconURL, int readChapter, String address,int type,String description,String author, String major) {
+ this.bookId = bookId;
+ this.name = name;
+ this.icon = icon;
+ this.iconURL = iconURL;
+ this.readChapter = readChapter;
+ this.address = address;
+ this.type = type;
+ this.description = description;
+ this.author = author;
+ this.major = major;
+ }
+
+ public String getIconURL() {
+ return iconURL;
+ }
+
+ public void setIconURL(String iconURL) {
+ this.iconURL = iconURL;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Bitmap getIcon() {
+ return icon;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setIcon(Bitmap icon) {
+ this.icon = icon;
+ }
+
+ public int getReadChapter() {
+ return readChapter;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public void setReadChapter(int readChapter) {
+ this.readChapter = readChapter;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public void setType(int type) {
+ this.type = type;
+ }
+
+ public String getBookId() {
+ return bookId;
+ }
+
+ public void setBookId(String bookId) {
+ this.bookId = bookId;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ public void setAuthor(String author) {
+ this.author = author;
+ }
+
+ public String getMajor() {
+ return major;
+ }
+
+ public void setMajor(String major) {
+ this.major = major;
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/SingleRankingObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/SingleRankingObj.java
new file mode 100644
index 0000000..ba30d4d
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/SingleRankingObj.java
@@ -0,0 +1,175 @@
+package com.example.Object;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+// 单独排行对象
+public class SingleRankingObj {
+ @SerializedName("ranking")
+ private Ranking ranking;
+
+ @SerializedName("ok")
+ private boolean ok;
+
+ public Ranking getRanking() {
+ return ranking;
+ }
+
+ public boolean isOk() {
+ return ok;
+ }
+
+ public class Ranking {
+ // 周榜id
+ @SerializedName("_id")
+ private String _id;
+
+ // 更新时间
+ @SerializedName("updated")
+ private String updated;
+
+ // 排行榜全名
+ @SerializedName("title")
+ private String title;
+
+ @SerializedName("tag")
+ private String tag;
+
+ // 排行榜大图标
+ @SerializedName("cover")
+ private String cover;
+
+ // 排行榜小图标
+ @SerializedName("icon")
+ private String icon;
+
+ @SerializedName("__v")
+ private String __v;
+
+ // 月榜id
+ @SerializedName("monthRank")
+ private String monthRank;
+
+ // 总榜id
+ @SerializedName("totalRank")
+ private String totalRank;
+
+ // 排行榜简称
+ @SerializedName("shortTitle")
+ private String shortTitle;
+
+ @SerializedName("created")
+ private String created;
+
+ @SerializedName("biTag")
+ private String biTag;
+
+ @SerializedName("isSub")
+ private boolean isSub;
+
+ @SerializedName("collapse")
+ private boolean collapse;
+
+ @SerializedName("new")
+ private boolean _new;
+
+ // 性别
+ @SerializedName("gender")
+ private String gender;
+
+ @SerializedName("priority")
+ private int priority;
+
+ // 书籍列表
+ @SerializedName("books")
+ private List bookList;
+
+ // 周榜id
+ @SerializedName("id")
+ private String id;
+
+ // 总数
+ @SerializedName("total")
+ private int total;
+
+ public String get_id() {
+ return _id;
+ }
+
+ public String getUpdated() {
+ return updated;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
+ public String getCover() {
+ return cover;
+ }
+
+ public String getIcon() {
+ return icon;
+ }
+
+ public String get__v() {
+ return __v;
+ }
+
+ public String getMonthRank() {
+ return monthRank;
+ }
+
+ public String getTotalRank() {
+ return totalRank;
+ }
+
+ public String getShortTitle() {
+ return shortTitle;
+ }
+
+ public String getCreated() {
+ return created;
+ }
+
+ public String getBiTag() {
+ return biTag;
+ }
+
+ public boolean isSub() {
+ return isSub;
+ }
+
+ public boolean isCollapse() {
+ return collapse;
+ }
+
+ public boolean is_new() {
+ return _new;
+ }
+
+ public String getGender() {
+ return gender;
+ }
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public List getBookList() {
+ return bookList;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public int getTotal() {
+ return total;
+ }
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/UserStatusObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/UserStatusObj.java
new file mode 100644
index 0000000..7f81871
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/UserStatusObj.java
@@ -0,0 +1,48 @@
+package com.example.Object;
+// 用户状态对象
+public class UserStatusObj {
+ int user_id;
+ int hor_or_ver_screen;
+ int day_or_night_status;
+ int textSize;
+
+ public UserStatusObj(int user_id, int hor_or_ver_screen, int day_or_night_status, int textSize) {
+ this.user_id = user_id;
+ this.hor_or_ver_screen = hor_or_ver_screen;
+ this.day_or_night_status = day_or_night_status;
+ this.textSize = textSize;
+ }
+
+ public int getDay_or_night_status() {
+ return day_or_night_status;
+ }
+
+ public int getHor_or_ver_screen() {
+ return hor_or_ver_screen;
+ }
+
+ public int getTextSize() {
+ return textSize;
+ }
+
+ public int getUser_id() {
+ return user_id;
+ }
+
+ public void setDay_or_night_status(int dat_or_night_status) {
+ this.day_or_night_status = dat_or_night_status;
+ }
+
+ public void setHor_or_ver_screen(int hor_or_ver_screen) {
+ this.hor_or_ver_screen = hor_or_ver_screen;
+ }
+
+ public void setTextSize(int textSize) {
+ this.textSize = textSize;
+ }
+
+ public void setUser_id(int user_id) {
+ this.user_id = user_id;
+ }
+}
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/CateRecyclerViewAdapter.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/CateRecyclerViewAdapter.java
new file mode 100644
index 0000000..413070a
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/CateRecyclerViewAdapter.java
@@ -0,0 +1,222 @@
+package com.example.RecyclerView;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.annotation.NonNull;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.example.R;
+import com.example.Object.BookObj;
+import com.example.Service.BookService;
+
+// 用于排行榜、分类界面的RecyclerView的Adapter
+public class CateRecyclerViewAdapter extends RecyclerView.Adapter {
+ private Context context;
+ private List data;
+ private boolean isRanking;
+ private OnItemClickListener onItemClickListener;
+
+ private int normalType = 0; // 第一种ViewType,正常的item
+ private int footType = 1; // 第二种ViewType,底部的提示View
+
+ private boolean hasMore = true; // 变量,是否有更多数据
+ private boolean fadeTips = false; // 变量,是否隐藏了底部的提示
+
+ private Handler mHandler = new Handler(Looper.getMainLooper()); //获取主线程的Handler
+
+
+ public CateRecyclerViewAdapter(List data, Context context, boolean hasMore, boolean isRanking) {
+ this.data = data;
+ this.context = context;
+ this.hasMore = hasMore;
+ this.isRanking = isRanking;
+ }
+
+ public boolean isFadeTips() {
+ return fadeTips;
+ }
+
+ @NonNull
+ @Override
+ public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
+ //根据不同的ViewType绑定不同的布局文件
+ if (viewType == normalType) {
+ MyViewHolder holder = MyViewHolder.get(context, viewGroup, R.layout.item_book);
+ holder.setNormalTypeType(true);
+ return holder;
+ }
+ else {
+ MyViewHolder holder = MyViewHolder.get(context, viewGroup, R.layout.recycler_footer_view);
+ holder.setNormalTypeType(false);
+ return holder;
+ }
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull final MyViewHolder holder, int position) {
+ if (data.isEmpty()) return;
+ if (holder.isNormalType() == true) {//是正常的布局
+ BookObj bookObj = data.get(position);
+ if (isRanking && !data.isEmpty()) {
+ ImageView rankingImg = holder.getView(R.id.item_book_rankingImg);
+ if (position == 0) {//排行榜第一名
+ rankingImg.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), R.mipmap.first, null));
+ rankingImg.setVisibility(View.VISIBLE);
+ } else if (position == 1) {//排行榜第二名
+ rankingImg.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), R.mipmap.second, null));
+ rankingImg.setVisibility(View.VISIBLE);
+ } else if (position == 2) {//排行榜第三名
+ rankingImg.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), R.mipmap.third, null));
+ rankingImg.setVisibility(View.VISIBLE);
+ }
+ else rankingImg.setVisibility(View.GONE);
+ }
+ final ImageView imageView = holder.getView(R.id.item_book_cover);
+ TextView bookName = holder.getView(R.id.item_book_name);
+ TextView bookAuthor = holder.getView(R.id.item_book_author);
+ TextView bookType = holder.getView(R.id.item_book_type);
+ TextView bookIntro = holder.getView(R.id.item_book_intro);
+ TextView followers = holder.getView(R.id.item_book_followers);
+ TextView retention = holder.getView(R.id.item_book_retention);
+ int num = bookObj.getLatelyFollower();
+ if (num < 10000) {
+ followers.setText(bookObj.getLatelyFollower() + "人追");
+ }
+ else {
+ num /= 10000;
+ followers.setText(num + "万人追");
+ }
+ followers.setVisibility(View.VISIBLE);
+ retention.setText(bookObj.getRetentionRatio() + "%留存率");
+ retention.setVisibility(View.VISIBLE);
+ bookName.setText(bookObj.getTitle());
+ bookType.setText(bookObj.getMajorCate());
+ bookAuthor.setText(bookObj.getAuthor());
+ bookIntro.setText(bookObj.getShortIntro());
+
+ //通过网络获取书籍图标
+ final String iconURL = BookService.StaticsUrl + bookObj.getCover();
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ URL url = new URL(iconURL);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setConnectTimeout(10000);
+ if (connection.getResponseCode() == 200) {
+ InputStream inputStream = connection.getInputStream();
+ final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ imageView.setImageBitmap(bitmap);
+ }
+ });
+ }
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ }
+ }}).start();
+ }
+ else {//是提示加载信息的布局
+ final ProgressBar progressBar = holder.getView(R.id.footer_view_progessBar);
+ final TextView tips = holder.getView(R.id.footer_view_text);
+ tips.setVisibility(View.VISIBLE);
+ progressBar.setVisibility(View.VISIBLE);
+ // 只有获取数据为空时,hasMore为false,所以当我们拉到底部时基本都会首先显示“正在加载更多...”
+ if (hasMore == true) {
+ // 不隐藏footView提示
+ fadeTips = false;
+ if (data.size() > 0) {
+ // 如果查询数据发现增加之后,就显示正在加载更多数据
+ tips.setText("正在加载更多数据...");
+ progressBar.setVisibility(View.VISIBLE);
+ }
+ } else {
+ if (data.size() > 0) {
+ // 如果查询数据发现并没有增加时,就显示没有更多数据了
+ tips.setText("没有更多数据了");
+ // 隐藏提示条
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ // 隐藏提示条
+ tips.setVisibility(View.GONE);
+ progressBar.setVisibility(View.GONE);
+ // 将fadeTips设置true
+ fadeTips = true;
+ // hasMore设为true是为了让再次拉到底时,会先显示正在加载更多
+ hasMore = true;
+ }
+ }, 500);
+ }
+ }
+ }
+ //设置监听器
+ if (onItemClickListener != null) {
+ holder.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ onItemClickListener.onClick(holder.getAdapterPosition());
+ }
+ });
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return data.size() + 1;
+ }
+
+ //获取列表中数据源的最后一个位置
+ public int getLastPosition() {
+ return data.size();
+ }
+
+ // 根据条目位置返回ViewType,以供onCreateViewHolder方法内获取不同的Holder
+ @Override
+ public int getItemViewType(int position) {
+ if (position == getItemCount() - 1) {
+ return footType;
+ } else {
+ return normalType;
+ }
+ }
+
+ //下拉刷新时,通过暴露方法将数据源置为空
+ public void resetDatas() {
+ data = new ArrayList<>();
+ }
+
+ //更新数据源,并修改hasMore的值,如果有增加数据,hasMore为true,否则为false
+ public void updateList(List newDatas, boolean hasMore) {
+ // 在原有的数据之上增加新数据
+ if (newDatas != null) {
+ data.addAll(newDatas);
+ }
+ this.hasMore = hasMore;
+ notifyDataSetChanged();
+ }
+
+ public interface OnItemClickListener{
+ void onClick(int position);
+ }
+ public void setOnItemClickListener(OnItemClickListener _onItemClickListener) {
+ this.onItemClickListener = _onItemClickListener;
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/CategoryRecyObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/CategoryRecyObj.java
new file mode 100644
index 0000000..550a2fa
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/CategoryRecyObj.java
@@ -0,0 +1,27 @@
+package com.example.RecyclerView;
+// 分类的实体
+public class CategoryRecyObj {
+ private String categoryName;
+ private String bookCount;
+
+ public CategoryRecyObj(String categoryName, String bookCount) {
+ this.categoryName = categoryName;
+ this.bookCount = bookCount;
+ }
+
+ public String getBookCount() {
+ return bookCount;
+ }
+
+ public String getCategoryName() {
+ return categoryName;
+ }
+
+ public void setBookCount(String bookCount) {
+ this.bookCount = bookCount;
+ }
+
+ public void setCategoryName(String categoryName) {
+ this.categoryName = categoryName;
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/MyRecyclerViewAdapter.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/MyRecyclerViewAdapter.java
new file mode 100644
index 0000000..557b210
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/MyRecyclerViewAdapter.java
@@ -0,0 +1,72 @@
+package com.example.RecyclerView;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.view.ViewGroup;
+import java.util.List;
+
+public abstract class MyRecyclerViewAdapter extends RecyclerView.Adapter {
+ private Context context;
+ private int layoutId;
+ private List data;
+ private OnItemClickListener onItemClickListener;
+
+ //构造函数
+ public MyRecyclerViewAdapter(Context _context, int _layoutId, List _data){
+ context = _context;
+ layoutId = _layoutId;
+ data = _data;
+ }
+
+ //创建自定的ViewHolder和绑定ViewHolder
+ @Override
+ public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ MyViewHolder holder = MyViewHolder.get(context, parent, layoutId);
+ return holder;
+ }
+
+ @Override
+ public void onBindViewHolder(final MyViewHolder holder, int position) {
+ convert(holder, data.get(position)); // convert函数需要重写,下面会讲
+ if (onItemClickListener != null) {
+ holder.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ onItemClickListener.onClick(holder.getAdapterPosition());
+ }
+ });
+ holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View view) {
+ onItemClickListener.onLongClick(holder.getAdapterPosition());
+ return false;
+ }
+ });
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ if (data == null)
+ return 0;
+ return data.size();
+ }
+
+ public abstract void convert(final MyViewHolder holder, final T t);
+
+
+ public interface OnItemClickListener{
+ void onClick(int position);
+ void onLongClick(int position);
+ }
+
+ public void setOnItemClickListener(OnItemClickListener _onItemClickListener) {
+ this.onItemClickListener = _onItemClickListener;
+ }
+
+ public void refresh(List list) {
+ this.data = list;
+ notifyDataSetChanged();
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/MyViewHolder.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/MyViewHolder.java
new file mode 100644
index 0000000..2ffa576
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/MyViewHolder.java
@@ -0,0 +1,47 @@
+package com.example.RecyclerView;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+// ViewHolder用来复用列表中的控件
+public class MyViewHolder extends RecyclerView.ViewHolder {
+ private SparseArray views;
+ private View view;
+ private boolean isNormalType;
+
+ public void setNormalTypeType(boolean type) {
+ this.isNormalType = type;
+ }
+
+ public boolean isNormalType() {
+ return isNormalType;
+ }
+
+ public MyViewHolder(Context _context, View _view, ViewGroup _viewGroup){
+ super(_view);
+ view = _view;
+ views = new SparseArray();
+ }
+
+ public static MyViewHolder get(Context _context, ViewGroup _viewGroup, int _layoutId) {
+ View _view = LayoutInflater.from(_context).inflate(_layoutId, _viewGroup, false);
+ MyViewHolder holder = new MyViewHolder(_context, _view, _viewGroup);
+ return holder;
+ }
+
+ public T getView(int _viewId) {
+ View _view = views.get(_viewId);
+ if (_view == null) {
+ // 创建view
+ _view = view.findViewById(_viewId);
+ // 将view存入views
+ views.put(_viewId, _view);
+ }
+ return (T)_view;
+ }
+
+}
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/RankRecyObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/RankRecyObj.java
new file mode 100644
index 0000000..03a447f
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/RankRecyObj.java
@@ -0,0 +1,27 @@
+package com.example.RecyclerView;
+
+import android.graphics.Bitmap;
+// 排行榜实体类
+public class RankRecyObj {
+ private Bitmap image;
+ private String name;
+ private int color;
+
+ public RankRecyObj(Bitmap image, String name, int color) {
+ this.image = image;
+ this.name = name;
+ this.color = color;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Bitmap getImage() {
+ return image;
+ }
+
+ public int getColor() {
+ return color;
+ }
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Service/BookService.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Service/BookService.java
new file mode 100644
index 0000000..7b6eb55
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Service/BookService.java
@@ -0,0 +1,311 @@
+package com.example.Service;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.TimeUnit;
+
+import com.example.Object.AllRankingObj;
+import com.example.Object.BookObj;
+import com.example.Object.CategoryObj;
+import com.example.Object.ChapterObj;
+import com.example.Object.ClassificationObj1;
+import com.example.Object.ClassificationObj2;
+import com.example.Object.CptListObj;
+import com.example.Object.FuzzySearchResultObj;
+import com.example.Object.SearchResultObj;
+import com.example.Object.SingleRankingObj;
+import okhttp3.OkHttpClient;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+
+public class BookService {
+ public static String ApiUrl = "http://api.zhuishushenqi.com";
+ public static String StaticsUrl = "http://statics.zhuishushenqi.com";
+ public static String ChapterUrl = "http://chapter2.zhuishushenqi.com";
+ public static String FuzzySearchUrl = "https://www.apiopen.top";
+
+ private static BookService bookService = new BookService();
+
+ public static synchronized BookService getBookService() {
+ return bookService;
+ }
+
+ OkHttpClient build = new OkHttpClient.Builder()
+ .connectTimeout(2, TimeUnit.SECONDS)
+ .readTimeout(2, TimeUnit.SECONDS)
+ .writeTimeout(2, TimeUnit.SECONDS)
+ .build();
+
+ // 用于API访问
+ Retrofit retrofitForApi = new Retrofit.Builder()
+ .baseUrl(ApiUrl)
+ // 设置json数据解析器
+ .addConverterFactory(GsonConverterFactory.create())
+ // RxJava封装OkHttp的Call函数,本质还是利用OkHttp请求数据
+ .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+ .client(build)
+ .build();
+
+ // 用于图片访问
+ Retrofit retrofitForStatics = new Retrofit.Builder()
+ .baseUrl(StaticsUrl)
+ // 设置json数据解析器
+ .addConverterFactory(GsonConverterFactory.create())
+ // RxJava封装OkHttp的Call函数,本质还是利用OkHttp请求数据
+ .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+ .client(build)
+ .build();
+
+ // 用于章节访问
+ Retrofit retrofitForChapter = new Retrofit.Builder()
+ .baseUrl(ChapterUrl)
+ // 设置json数据解析器
+ .addConverterFactory(GsonConverterFactory.create())
+ // RxJava封装OkHttp的Call函数,本质还是利用OkHttp请求数据
+ .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+ .client(build)
+ .build();
+
+ Retrofit retrofitForFuzzySearch = new Retrofit.Builder()
+ .baseUrl(FuzzySearchUrl)
+ .addConverterFactory(GsonConverterFactory.create())
+ .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
+ .client(build)
+ .build();
+
+ // 用于访问api
+ private UrlService ApiService = retrofitForApi.create(UrlService.class);
+
+ // 用于访问图片
+ private UrlService StaticsService = retrofitForStatics.create(UrlService.class);
+
+ // 用于访问章节
+ private UrlService ChapterService = retrofitForChapter.create(UrlService.class);
+
+ // 用于模糊搜索
+ private UrlService FuzzySearchService = retrofitForFuzzySearch.create(UrlService.class);
+
+ // 所有排行榜
+ private AllRankingObj allRankingObj;
+
+ // 单一排行榜
+ private SingleRankingObj singleRankingObj;
+
+ // 一级分类
+ private ClassificationObj1 classificationObj1;
+
+ // 二级分类
+ private ClassificationObj2 classificationObj2;
+
+ // 书籍列表
+ private CategoryObj categoryObj;
+
+ // 书籍详情
+ private BookObj bookObj;
+
+ // 章节列表
+ private CptListObj cptListObj;
+
+ // 章节内容
+ private ChapterObj chapterObj;
+
+ // 书籍搜索结果
+ private SearchResultObj searchResultObj;
+
+ // 模糊搜索结果
+ private FuzzySearchResultObj fuzzySearchResultObj;
+
+ /*
+ * 获取所有排行榜
+ * @param 无
+ * @return AllRankingObj
+ */
+
+ public AllRankingObj getAllRankingObj() {
+ Response response = null;
+ try {
+ response = ApiService.getAllRanking().execute();
+ allRankingObj = response.body();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return allRankingObj;
+ }
+
+ /*
+ * 获取单一排行榜
+ * @param rankingId String _id 周榜、monthRank 月榜、totalRank 总榜 可从AllRankingObj中获得
+ * @return SingleRankingObj
+ */
+
+ public SingleRankingObj getSingleRankingObj(String rankingId) {
+ Response response = null;
+ try {
+ response = ApiService.getSingleRanking(rankingId).execute();
+ singleRankingObj = response.body();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return singleRankingObj;
+ }
+
+ /*
+ * 获取一级分类
+ * @param 无
+ * @return ClassificationObj1
+ */
+
+ public ClassificationObj1 getClassification1() {
+ Response response = null;
+ try {
+ response = ApiService.getClassificationObj1().execute();
+ classificationObj1 = response.body();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return classificationObj1;
+ }
+
+ /*
+ * 获取二级分类
+ * @param 无
+ * @return ClassificationObj2
+ */
+
+ public ClassificationObj2 getClassification2() {
+ Response response = null;
+ try {
+ response = ApiService.getClassificationObj2().execute();
+ classificationObj2 = response.body();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return classificationObj2;
+ }
+
+ /*
+ * 获取主题书单列表
+ * @param type String hot(热门)、new(新书)、reputation(好评)、over(完结)
+ * major String 玄幻 可以从一级分类获得
+ * start String 起始位置,从0开始
+ * limit String 获取数量限制 20
+ * gender String 性别 male、female
+ * @return CategoryObj
+ * 示例 bookService.getBooksByCategoty("hot", "玄幻", "0", "20", "male");
+ */
+
+ public CategoryObj getBooksByCategoty(String type, String major, int start, int limit, String gender) {
+ Response response = null;
+ try {
+ response = ApiService.getBooksByCategory(type, major, start, limit, gender).execute();
+ categoryObj = response.body();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return categoryObj;
+ }
+
+ public BookObj getBookById(String bookid) {
+ Response response = null;
+ try {
+ response = ApiService.getBookById(bookid).execute();
+ bookObj = response.body();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return bookObj;
+ }
+
+ /*
+ * 获取章节列表
+ * @param String bookid 书籍id,可从CategoryObj中获得
+ * @return CptListObj 章节列表对象
+ */
+
+ public CptListObj getChaptersByBookId(String bookid) {
+ Response response = null;
+ try {
+ response = ApiService.getChapters(bookid).execute();
+ cptListObj = response.body();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return cptListObj;
+ }
+
+ /*
+ * 获取章节内容
+ * @param String link 章节链接,可从CptListObj中获得
+ * @return ChapterObj 章节对象
+ */
+
+ public ChapterObj getChapterByLink(String link) {
+ Response response = null;
+ try {
+ response = ChapterService.getChapter(link).execute();
+ chapterObj = response.body();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return chapterObj;
+ }
+
+ /*
+ * 获取书籍搜索结果
+ * @param query String 关键词
+ * start 结果开始位置
+ * limit 结果最大数量
+ * @return SearchResultObj 搜索结果对象
+ */
+ public SearchResultObj getSearchResultObj(String query, int start, int limit) {
+ Response response = null;
+ try {
+ response = ApiService.getSearchResult(query, start, limit).execute();
+ searchResultObj = response.body();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return searchResultObj;
+ }
+
+ /*
+ * 获取书籍模糊搜索结果
+ * @param name String 关键词
+ * @return FuzzyResultObjs 模糊搜索结果对象
+ */
+ public FuzzySearchResultObj getFuzzySearchResult(String name) {
+ Response response = null;
+ try {
+ response = FuzzySearchService.getFuzzySearchResult(name).execute();
+ fuzzySearchResultObj = response.body();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return fuzzySearchResultObj;
+ }
+
+ /*
+ * 获取图片
+ * @param path
+ * @return Bitmap 图片
+ */
+ public Bitmap getImg(String path) {
+ Response response = null;
+ Bitmap bitmap = null;
+ try {
+ response = StaticsService.getImg(path).execute();
+ InputStream is = response.body();
+ bitmap = BitmapFactory.decodeStream(is);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return bitmap;
+ }
+
+}
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Service/UrlService.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Service/UrlService.java
new file mode 100644
index 0000000..853a46a
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Service/UrlService.java
@@ -0,0 +1,116 @@
+package com.example.Service;
+
+import java.io.InputStream;
+
+import com.example.Object.AllRankingObj;
+import com.example.Object.BookObj;
+import com.example.Object.CategoryObj;
+import com.example.Object.ChapterObj;
+import com.example.Object.ClassificationObj1;
+import com.example.Object.ClassificationObj2;
+import com.example.Object.CptListObj;
+import com.example.Object.FuzzySearchResultObj;
+import com.example.Object.SearchResultObj;
+import com.example.Object.SingleRankingObj;
+import retrofit2.Call;
+import retrofit2.http.GET;
+import retrofit2.http.Path;
+import retrofit2.http.Query;
+
+public interface UrlService {
+ /*
+ * 获取所有排行榜
+ * @param 无
+ * @return Call
+ */
+ @GET("/ranking/gender")
+ Call getAllRanking();
+
+ /*
+ * 获取单一排行榜
+ * @param rankingId String _id 周榜、monthRank 月榜、totalRank 总榜
+ * @return Call
+ */
+ @GET("/ranking/{rankingId}")
+ Call getSingleRanking(@Path("rankingId") String rankingId);
+
+
+ /*
+ * 获取一级分类
+ * @param 无
+ * @return Call
+ */
+ @GET("/cats/lv2/statistics")
+ Call getClassificationObj1();
+
+ /*
+ * 获取二级分类
+ * @param 无
+ * @return Call
+ */
+ @GET("/cats/lv2")
+ Call getClassificationObj2();
+
+ /*
+ * 获取主题书单列表
+ * @param type String hot(热门)、new(新书)、reputation(好评)、over(完结)
+ * major String 玄幻
+ * start String 起始位置,从0开始
+ * limit String 限制获取数量 20
+ * gender String 性别 male、female
+ * @return Call
+ */
+ @GET("/book/by-categories")
+ Call getBooksByCategory(@Query("type") String type, @Query("major") String major, @Query("start") int start, @Query("limit") int limit, @Query("gender") String gender);
+
+ /*
+ * 获取书籍详情
+ * @param bookid String 书籍id
+ * @return Call 书籍对象
+ */
+ @GET("/book/{bookid}")
+ Call getBookById(@Path("bookid") String bookid);
+
+ /*
+ * 获取章节列表
+ * @param bookid 书籍id
+ * @return Call
+ */
+ @GET("/mix-atoc/{bookid}?view=chapters")
+ Call getChapters(@Path("bookid") String bookid);
+
+ /*
+ * 获取章节内容
+ * @param link 章节链接
+ * @return Call 章节对象
+ */
+ @GET("/chapter/{link}")
+ Call getChapter(@Path("link") String link);
+
+ /*
+ * 获取书籍搜索结果
+ * @param name String 书名
+ * start int 结果开始位置
+ * limit int 结果数量限制
+ * @return Call 搜索结果对象
+ */
+ @GET("/book/fuzzy-search")
+ Call getSearchResult(@Query("query") String query, @Query("start") int start, @Query("limit") int limit);
+
+ /*
+ * 获取模糊搜索结果
+ * @param name 关键字
+ * @return Call 模糊搜索结果对象
+ */
+ @GET("/novelSearchApi")
+ Call getFuzzySearchResult(@Query("name") String name);
+
+ /*
+ * 获取图片
+ * @param path
+ * @return Call 图片
+ */
+ @GET("{path}")
+ Call getImg(@Path("path") String path);
+
+}
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/buttonstyle.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/buttonstyle.xml
new file mode 100644
index 0000000..655f7df
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/buttonstyle.xml
@@ -0,0 +1,19 @@
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/card_edge.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/card_edge.xml
new file mode 100644
index 0000000..2ea983b
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/card_edge.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/ic_launcher_background.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/ic_launcher_background.xml
new file mode 100644
index 0000000..d5fccc5
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..c7bd21d
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/selector_tab_text_color.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/selector_tab_text_color.xml
new file mode 100644
index 0000000..855c238
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/selector_tab_text_color.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/textview_border_blue.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/textview_border_blue.xml
new file mode 100644
index 0000000..a0277ab
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/textview_border_blue.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/textview_border_green.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/textview_border_green.xml
new file mode 100644
index 0000000..46dbae0
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/textview_border_green.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/buttonstyle.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/buttonstyle.xml
new file mode 100644
index 0000000..655f7df
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/buttonstyle.xml
@@ -0,0 +1,19 @@
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/card_edge.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/card_edge.xml
new file mode 100644
index 0000000..2ea983b
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/card_edge.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/ic_launcher_background.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..d5fccc5
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/ic_launcher_foreground.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 0000000..c7bd21d
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/selector_tab_text_color.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/selector_tab_text_color.xml
new file mode 100644
index 0000000..855c238
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/selector_tab_text_color.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/textview_border_blue.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/textview_border_blue.xml
new file mode 100644
index 0000000..a0277ab
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/textview_border_blue.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/textview_border_green.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/textview_border_green.xml
new file mode 100644
index 0000000..46dbae0
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/textview_border_green.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_book_detail.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_book_detail.xml
new file mode 100644
index 0000000..2b91e6a
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_book_detail.xml
@@ -0,0 +1,280 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_category.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_category.xml
new file mode 100644
index 0000000..b920159
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_category.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_main.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..af3b464
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_read_page.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_read_page.xml
new file mode 100644
index 0000000..001a20c
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_read_page.xml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_recom.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_recom.xml
new file mode 100644
index 0000000..2acf3dd
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_recom.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_search.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_search.xml
new file mode 100644
index 0000000..15dba40
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_search.xml
@@ -0,0 +1,295 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/catalog_dialog.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/catalog_dialog.xml
new file mode 100644
index 0000000..eec9683
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/catalog_dialog.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/dialog_category.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/dialog_category.xml
new file mode 100644
index 0000000..51e9193
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/dialog_category.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/dialog_text_setting.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/dialog_text_setting.xml
new file mode 100644
index 0000000..1559c36
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/dialog_text_setting.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_book_shelf.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_book_shelf.xml
new file mode 100644
index 0000000..26696dc
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_book_shelf.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_category.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_category.xml
new file mode 100644
index 0000000..7f9768f
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_category.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_detail_category.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_detail_category.xml
new file mode 100644
index 0000000..2a762ad
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_detail_category.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_male_in_category.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_male_in_category.xml
new file mode 100644
index 0000000..e41a845
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_male_in_category.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_ranking.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_ranking.xml
new file mode 100644
index 0000000..0749e22
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_ranking.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_read_page.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_read_page.xml
new file mode 100644
index 0000000..bfa2c46
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/fragment_read_page.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_book.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_book.xml
new file mode 100644
index 0000000..b0cbdd7
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_book.xml
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_catalog.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_catalog.xml
new file mode 100644
index 0000000..ec716ff
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_catalog.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_category.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_category.xml
new file mode 100644
index 0000000..514395b
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_category.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_listview.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_listview.xml
new file mode 100644
index 0000000..baa9dbd
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_listview.xml
@@ -0,0 +1,16 @@
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_listview2.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_listview2.xml
new file mode 100644
index 0000000..8b1704a
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_listview2.xml
@@ -0,0 +1,15 @@
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_ranking.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_ranking.xml
new file mode 100644
index 0000000..b20f73b
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/item_ranking.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/recycler_footer_view.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/recycler_footer_view.xml
new file mode 100644
index 0000000..cdf5cd8
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/recycler_footer_view.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/back.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/back.png
new file mode 100644
index 0000000..1ec43a9
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/back.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/battery.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/battery.png
new file mode 100644
index 0000000..b080969
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/battery.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/bookcover.jpg b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/bookcover.jpg
new file mode 100644
index 0000000..481cfe7
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/bookcover.jpg differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/bookcover2.jpg b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/bookcover2.jpg
new file mode 100644
index 0000000..98622d8
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/bookcover2.jpg differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/bookshelf.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/bookshelf.png
new file mode 100644
index 0000000..07f32d2
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/bookshelf.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/bookshelf_red.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/bookshelf_red.png
new file mode 100644
index 0000000..52ca108
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/bookshelf_red.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/catalog.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/catalog.png
new file mode 100644
index 0000000..10aba26
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/catalog.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/catalog_icon.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/catalog_icon.png
new file mode 100644
index 0000000..82fd999
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/catalog_icon.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/category.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/category.png
new file mode 100644
index 0000000..b5baa0a
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/category.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/category_red.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/category_red.png
new file mode 100644
index 0000000..cf9dca2
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/category_red.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/daytime.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/daytime.png
new file mode 100644
index 0000000..ba8f2df
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/daytime.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/delete.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/delete.png
new file mode 100644
index 0000000..9348460
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/delete.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/download.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/download.png
new file mode 100644
index 0000000..b41b3ee
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/download.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_black.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_black.png
new file mode 100644
index 0000000..1b71cc9
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_black.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon1.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon1.png
new file mode 100644
index 0000000..2e7b97e
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon1.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon2.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon2.png
new file mode 100644
index 0000000..6e3ccf8
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon2.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon3.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon3.png
new file mode 100644
index 0000000..be1b1c9
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon3.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon4.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon4.png
new file mode 100644
index 0000000..42505a2
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon4.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon5.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon5.png
new file mode 100644
index 0000000..afb3ae5
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_icon5.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_red.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_red.png
new file mode 100644
index 0000000..57b8fbf
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/female_red.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/first.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/first.png
new file mode 100644
index 0000000..51aef95
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/first.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/fresh.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/fresh.png
new file mode 100644
index 0000000..e15f096
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/fresh.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/heatfire.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/heatfire.png
new file mode 100644
index 0000000..b7c28aa
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/heatfire.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/history.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/history.png
new file mode 100644
index 0000000..dec9d19
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/history.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/horizontal_screen.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/horizontal_screen.png
new file mode 100644
index 0000000..b02bab8
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/horizontal_screen.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/ic_launcher.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a2f5908
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1b52399
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/icon.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/icon.png
new file mode 100644
index 0000000..ed48171
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/icon.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_black.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_black.png
new file mode 100644
index 0000000..3a4a935
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_black.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_blue.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_blue.png
new file mode 100644
index 0000000..bfeceba
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_blue.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon1.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon1.png
new file mode 100644
index 0000000..ff94d6c
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon1.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon2.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon2.png
new file mode 100644
index 0000000..66a7409
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon2.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon3.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon3.png
new file mode 100644
index 0000000..f2d3457
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon3.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon4.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon4.png
new file mode 100644
index 0000000..d070ad2
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon4.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon5.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon5.png
new file mode 100644
index 0000000..9084474
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/male_icon5.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/minus.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/minus.png
new file mode 100644
index 0000000..a56c7ad
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/minus.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/nighttime.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/nighttime.png
new file mode 100644
index 0000000..6c9877d
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/nighttime.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number1.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number1.png
new file mode 100644
index 0000000..06f8269
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number1.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number2.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number2.png
new file mode 100644
index 0000000..01e418a
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number2.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number3.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number3.png
new file mode 100644
index 0000000..127293d
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number3.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number4.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number4.png
new file mode 100644
index 0000000..b4bd6e6
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number4.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number5.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number5.png
new file mode 100644
index 0000000..ef592bb
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number5.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number6.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number6.png
new file mode 100644
index 0000000..f573363
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/number6.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/plus.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/plus.png
new file mode 100644
index 0000000..ab1c927
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/plus.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/ranking.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/ranking.png
new file mode 100644
index 0000000..cd99cc7
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/ranking.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/ranking_red.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/ranking_red.png
new file mode 100644
index 0000000..26f0ae4
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/ranking_red.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/search.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/search.png
new file mode 100644
index 0000000..5ff5df3
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/search.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/second.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/second.png
new file mode 100644
index 0000000..33ce3cf
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/second.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/textsize.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/textsize.png
new file mode 100644
index 0000000..dcd35b2
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/textsize.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/third.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/third.png
new file mode 100644
index 0000000..9904f33
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/third.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/vertical_screen.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/vertical_screen.png
new file mode 100644
index 0000000..607f7e4
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-hdpi/vertical_screen.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-mdpi/ic_launcher.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..ff10afd
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..115a4c7
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..dcd3cd8
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..459ca60
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..8ca12fe
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..8e19b41
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b824ebd
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..4c19a13
Binary files /dev/null and b/202014040130tangjiefeng_Reader/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/values/colors.xml b/202014040130tangjiefeng_Reader/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..e2229ac
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/values/colors.xml
@@ -0,0 +1,14 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+ #000000
+ #2B2B2B
+ #FF0000
+ #FFFFFF
+ #CCCCCC
+ #FFEFD5
+ #191970
+ #444444
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/values/strings.xml b/202014040130tangjiefeng_Reader/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..36b03fa
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+ NovelReader
+
+
+ Hello blank fragment
+
diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/values/styles.xml b/202014040130tangjiefeng_Reader/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..649e526
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/main/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
diff --git a/202014040130tangjiefeng_Reader/app/src/test/java/com/example/ExampleUnitTest.java b/202014040130tangjiefeng_Reader/app/src/test/java/com/example/ExampleUnitTest.java
new file mode 100644
index 0000000..6860eed
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/app/src/test/java/com/example/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.example;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/202014040130tangjiefeng_Reader/build.gradle b/202014040130tangjiefeng_Reader/build.gradle
new file mode 100644
index 0000000..f4de9cf
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/build.gradle
@@ -0,0 +1,45 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+
+ repositories {
+ // maven库
+ def cn = "http://maven.aliyun.com/nexus/content/groups/public/"
+ def abroad = "http://central.maven.org/maven2/"
+ // 先从url中下载jar若没有找到,则在artifactUrls中寻找
+ maven {
+ url cn
+ artifactUrls abroad
+ }
+ maven { url "http://maven.aliyun.com/nexus/content/repositories/jcenter"}
+ // 保留google源
+ google()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.6.1'
+
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ // maven库
+ def cn = "http://maven.aliyun.com/nexus/content/groups/public/"
+ def abroad = "http://central.maven.org/maven2/"
+ // 先从url中下载jar若没有找到,则在artifactUrls中寻找
+ maven {
+ url cn
+ artifactUrls abroad
+ }
+ maven { url "http://maven.aliyun.com/nexus/content/repositories/jcenter"}
+ // 保留google源
+ google()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/202014040130tangjiefeng_Reader/gradle.properties b/202014040130tangjiefeng_Reader/gradle.properties
new file mode 100644
index 0000000..743d692
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/gradle.properties
@@ -0,0 +1,13 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
diff --git a/202014040130tangjiefeng_Reader/gradle/wrapper/gradle-wrapper.jar b/202014040130tangjiefeng_Reader/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..7a3265e
Binary files /dev/null and b/202014040130tangjiefeng_Reader/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/202014040130tangjiefeng_Reader/gradle/wrapper/gradle-wrapper.properties b/202014040130tangjiefeng_Reader/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..b748500
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Dec 20 13:25:52 CST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
diff --git a/202014040130tangjiefeng_Reader/gradlew b/202014040130tangjiefeng_Reader/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/202014040130tangjiefeng_Reader/gradlew.bat b/202014040130tangjiefeng_Reader/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/202014040130tangjiefeng_Reader/img/Fragment.jpg b/202014040130tangjiefeng_Reader/img/Fragment.jpg
new file mode 100644
index 0000000..468ab0b
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/Fragment.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/activity.jpg b/202014040130tangjiefeng_Reader/img/activity.jpg
new file mode 100644
index 0000000..e0e4f8c
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/activity.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/control.jpg b/202014040130tangjiefeng_Reader/img/control.jpg
new file mode 100644
index 0000000..fc97e7c
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/control.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/icon.png b/202014040130tangjiefeng_Reader/img/icon.png
new file mode 100644
index 0000000..ed48171
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/icon.png differ
diff --git a/202014040130tangjiefeng_Reader/img/obj.jpg b/202014040130tangjiefeng_Reader/img/obj.jpg
new file mode 100644
index 0000000..df0ee3d
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/obj.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/recylerview.jpg b/202014040130tangjiefeng_Reader/img/recylerview.jpg
new file mode 100644
index 0000000..95138b0
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/recylerview.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/service.jpg b/202014040130tangjiefeng_Reader/img/service.jpg
new file mode 100644
index 0000000..05369cb
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/service.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/书架.jpg b/202014040130tangjiefeng_Reader/img/书架.jpg
new file mode 100644
index 0000000..8165c4a
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/书架.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/分类.jpg b/202014040130tangjiefeng_Reader/img/分类.jpg
new file mode 100644
index 0000000..a74511c
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/分类.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/分类界面.jpg b/202014040130tangjiefeng_Reader/img/分类界面.jpg
new file mode 100644
index 0000000..0231ccb
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/分类界面.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/排行榜.jpg b/202014040130tangjiefeng_Reader/img/排行榜.jpg
new file mode 100644
index 0000000..bc300a4
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/排行榜.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/排行榜界面.jpg b/202014040130tangjiefeng_Reader/img/排行榜界面.jpg
new file mode 100644
index 0000000..3df590e
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/排行榜界面.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/搜索界面.jpg b/202014040130tangjiefeng_Reader/img/搜索界面.jpg
new file mode 100644
index 0000000..6423695
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/搜索界面.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/相关书籍界面.jpg b/202014040130tangjiefeng_Reader/img/相关书籍界面.jpg
new file mode 100644
index 0000000..50d0570
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/相关书籍界面.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/详情界面.jpg b/202014040130tangjiefeng_Reader/img/详情界面.jpg
new file mode 100644
index 0000000..619fa4a
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/详情界面.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/阅读.jpg b/202014040130tangjiefeng_Reader/img/阅读.jpg
new file mode 100644
index 0000000..bb53559
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/阅读.jpg differ
diff --git a/202014040130tangjiefeng_Reader/img/项目结构.png b/202014040130tangjiefeng_Reader/img/项目结构.png
new file mode 100644
index 0000000..454a048
Binary files /dev/null and b/202014040130tangjiefeng_Reader/img/项目结构.png differ
diff --git a/202014040130tangjiefeng_Reader/settings.gradle b/202014040130tangjiefeng_Reader/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/202014040130tangjiefeng_Reader/settings.gradle
@@ -0,0 +1 @@
+include ':app'