├── .gitignore
├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── delsart
│ │ └── bookdownload
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── delsart
│ │ │ └── bookdownload
│ │ │ ├── MsgType.java
│ │ │ ├── MyApplication.java
│ │ │ ├── SplashActivity.java
│ │ │ ├── Url.java
│ │ │ ├── adapter
│ │ │ ├── ItemAdapter.java
│ │ │ ├── MyItemAdapter.java
│ │ │ └── PagerAdapter.java
│ │ │ ├── bean
│ │ │ ├── DownloadBean.java
│ │ │ └── NovelBean.java
│ │ │ ├── custom
│ │ │ ├── CustomTextView.java
│ │ │ ├── MyCustomItem.java
│ │ │ ├── MyViewTypeManager.java
│ │ │ └── ScrollAwareFABBehavior.java
│ │ │ ├── glide
│ │ │ └── MyGlideModule.java
│ │ │ ├── handler
│ │ │ ├── MyCrashHandler.java
│ │ │ ├── MyHandler.java
│ │ │ └── OnHandleMessageCallback.java
│ │ │ ├── service
│ │ │ ├── AiXiaService.java
│ │ │ ├── BaseService.java
│ │ │ ├── BlahService.java
│ │ │ ├── DongManZhiJiaService.java
│ │ │ ├── EpubeeService.java
│ │ │ ├── M360DService.java
│ │ │ ├── QiShuService.java
│ │ │ ├── ShuYuZheService.java
│ │ │ ├── XiaoShuWuService.java
│ │ │ ├── ZhiXuanService.java
│ │ │ └── ZhouDuService.java
│ │ │ ├── ui
│ │ │ ├── activity
│ │ │ │ ├── AboutActivity.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── SettingsActivity.java
│ │ │ │ └── UsedOpenSource.java
│ │ │ └── fragment
│ │ │ │ ├── AiXiaFragment.java
│ │ │ │ ├── BaseFragment.java
│ │ │ │ ├── BlahFragment.java
│ │ │ │ ├── DongManZhiJiaFragment.java
│ │ │ │ ├── M360DFragment.java
│ │ │ │ ├── QiShuFragment.java
│ │ │ │ ├── ShuYuZheFragment.java
│ │ │ │ ├── XiaoShuWuFragment.java
│ │ │ │ ├── ZhiXuanFragment.java
│ │ │ │ └── ZhouDuFragment.java
│ │ │ └── utils
│ │ │ └── StatusBarUtils.java
│ └── res
│ │ ├── anim
│ │ └── enter_anim.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── item_custom.xml
│ │ ├── item_list.xml
│ │ ├── recycler_view.xml
│ │ ├── view_dialog.xml
│ │ ├── view_no_found.xml
│ │ ├── view_no_search.xml
│ │ └── view_searching.xml
│ │ ├── menu
│ │ └── menu.xml
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_to_top.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ ├── ic_no_found.png
│ │ └── ic_no_search.png
│ │ ├── values-v23
│ │ └── styles.xml
│ │ ├── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ │ └── xml
│ │ └── settinglayout.xml
│ └── test
│ └── java
│ └── com
│ └── delsart
│ └── bookdownload
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── 更新日志.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Android Studio Navigation editor temp files
30 | .navigation/
31 |
32 | # Android Studio captures folder
33 | captures/
34 |
35 | # Intellij
36 | *.iml
37 | .idea/workspace.xml
38 | .idea/tasks.xml
39 | .idea/gradle.xml
40 | .idea/dictionaries
41 | .idea/libraries
42 |
43 | # Keystore files
44 | *.jks
45 |
46 | # External native build folder generated in Android Studio 2.2 and later
47 | .externalNativeBuild
48 |
49 | # Google Services (e.g. APIs or Firebase)
50 | google-services.json
51 |
52 | # Freeline
53 | freeline.py
54 | freeline/
55 | freeline_project_description.json
56 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
19 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Bookster
2 | 聚合类书籍搜索软件
3 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "26.0.1"
6 | defaultConfig {
7 | applicationId "com.delsart.bookdownload"
8 | minSdkVersion 14
9 | targetSdkVersion 25
10 | versionCode 151
11 | versionName "1.51"
12 | resConfigs "zh"
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled true
18 | shrinkResources true
19 | zipAlignEnabled true
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | compile fileTree(dir: 'libs', include: ['*.jar'])
27 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
28 | exclude group: 'com.android.support', module: 'support-annotations'
29 | })
30 | compile 'com.android.support:appcompat-v7:25.3.1'
31 | compile 'com.android.support:design:25.3.1'
32 | compile 'org.jsoup:jsoup:1.10.1'
33 | compile 'com.github.daniel-stoneuk:material-about-library:2.1.0'
34 | compile 'com.mikepenz:iconics-core:2.8.2@aar'
35 | compile 'com.mikepenz:community-material-typeface:1.7.22.1@aar'
36 | compile 'com.android.support:support-v4:25.3.1'
37 | compile 'moe.feng:AlipayZeroSdk:1.1'
38 | compile 'com.github.bumptech.glide:glide:4.0.0-RC1'
39 | annotationProcessor 'com.github.bumptech.glide:compiler:4.0.0-RC1'
40 | compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.22'
41 | testCompile 'junit:junit:4.12'
42 | // debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
43 | // releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
44 | // testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
45 | }
46 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\star\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
27 |
28 | -optimizationpasses 5
29 | -dontusemixedcaseclassnames
30 | -dontskipnonpubliclibraryclasses
31 | -dontskipnonpubliclibraryclassmembers
32 | -dontpreverify
33 | -verbose
34 | -printmapping proguardMapping.txt
35 | -optimizations !code/simplification/cast,!field/*,!class/merging/*
36 | -keepattributes *Annotation*,InnerClasses
37 | -keepattributes Signature
38 | -keepattributes SourceFile,LineNumberTable
39 |
40 | -ignorewarnings
41 |
42 |
43 | # fresco
44 | # Keep our interfaces so they can be used by other ProGuard rules.
45 | # See http://sourceforge.net/p/proguard/bugs/466/
46 | -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip
47 |
48 | # Do not strip any method/class that is annotated with @DoNotStrip
49 | -keep @com.facebook.common.internal.DoNotStrip class *
50 | -keepclassmembers class * {
51 | @com.facebook.common.internal.DoNotStrip *;
52 | }
53 |
54 | # Keep native methods
55 | -keepclassmembers class * {
56 | native ;
57 | }
58 |
59 | -dontwarn okio.**
60 | -dontwarn com.squareup.okhttp.**
61 | -dontwarn okhttp3.**
62 | -dontwarn javax.annotation.**
63 | -dontwarn com.android.volley.toolbox.**
64 | -dontwarn com.facebook.infer.**
65 |
66 | # MeiZuFingerprint
67 | -keep class com.fingerprints.service.** { *; }
68 |
69 | # SmsungFingerprint
70 | -keep class com.samsung.android.sdk.** { *; }
71 |
72 | #jsoup
73 | -keep class org.jsoup.** { *; }
74 |
75 | #okio
76 | -dontwarn okio.**
77 |
78 | #okhttp
79 | -dontwarn javax.annotation.Nullable
80 | -dontwarn javax.annotation.ParametersAreNonnullByDefault
81 |
82 | #retrofit
83 | -dontwarn retrofit2.**
84 | -keep class retrofit2.** { *; }
85 | # Platform calls Class.forName on types which do not exist on Android to determine platform.
86 | -dontnote retrofit2.Platform
87 | # Platform used when running on Java 8 VMs. Will not be used at runtime.
88 | -dontwarn retrofit2.Platform$Java8
89 | # Retain generic type information for use by reflection by converters and adapters.
90 | -keepattributes Signature
91 | # Retain declared checked exceptions for use by a Proxy instance.
92 | -keepattributes Exceptions
93 |
94 | #Glide
95 | -keep public class * implements com.bumptech.glide.module.GlideModule
96 | -keep public class * extends com.bumptech.glide.AppGlideModule
97 | -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
98 | **[] $VALUES;
99 | public *;
100 | }
101 |
102 | #evenbus
103 | -keepclassmembers class ** {
104 | @org.greenrobot.eventbus.Subscribe ;
105 | }
106 | -keep enum org.greenrobot.eventbus.ThreadMode { *; }
107 |
108 | -keep public class * extends android.app.Activity
109 | -keep public class * extends android.app.Application
110 | -keep public class * extends android.app.Service
111 | -keep public class * extends android.content.BroadcastReceiver
112 | -keep public class * extends android.content.ContentProvider
113 | -keep public class * extends android.app.backup.BackupAgentHelper
114 | -keep public class * extends android.preference.Preference
115 | -keep public class * extends android.view.View
116 | -keep public class com.android.vending.licensing.ILicensingService
117 | -keep class android.support.** {*;}
118 |
119 | -keepclasseswithmembernames class * {
120 | native ;
121 | }
122 | -keepclassmembers class * extends android.app.Activity{
123 | public void *(android.view.View);
124 | }
125 | -keepclassmembers enum * {
126 | public static **[] values();
127 | public static ** valueOf(java.lang.String);
128 | }
129 | -keep public class * extends android.view.View{
130 | *** get*();
131 | void set*(***);
132 | public (android.content.Context);
133 | public (android.content.Context, android.util.AttributeSet);
134 | public (android.content.Context, android.util.AttributeSet, int);
135 | }
136 | -keepclasseswithmembers class * {
137 | public (android.content.Context, android.util.AttributeSet);
138 | public (android.content.Context, android.util.AttributeSet, int);
139 | }
140 | -keep class * implements android.os.Parcelable {
141 | public static final android.os.Parcelable$Creator *;
142 | }
143 | -keepclassmembers class * implements java.io.Serializable {
144 | static final long serialVersionUID;
145 | private static final java.io.ObjectStreamField[] serialPersistentFields;
146 | private void writeObject(java.io.ObjectOutputStream);
147 | private void readObject(java.io.ObjectInputStream);
148 | java.lang.Object writeReplace();
149 | java.lang.Object readResolve();
150 | }
151 | -keep class **.R$* {
152 | *;
153 | }
154 | -keepclassmembers class * {
155 | void *(**On*Event);
156 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/delsart/bookdownload/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.delsart.bookdownload", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
16 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
29 |
30 |
31 |
35 |
39 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/MsgType.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload;
2 |
3 |
4 | public interface MsgType {
5 | int ERROR = 0;
6 | int SUCCESS = 1;
7 | int RESULT = 1;
8 | int LOAD_MORE_VIEW = 2;
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/MyApplication.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.Application;
5 | import android.content.Context;
6 | import android.preference.PreferenceManager;
7 |
8 | import com.delsart.bookdownload.handler.MyCrashHandler;
9 |
10 | /**
11 | * Created by Delsart on 2017/7/30.
12 | */
13 | public class MyApplication extends Application {
14 | @SuppressLint("StaticFieldLeak")
15 | private static Context context;
16 |
17 | public static Context getContext() {
18 | return context;
19 | }
20 |
21 | @Override
22 | public void onCreate() {
23 | // LeakCanary.install(this);
24 | context = getApplicationContext();
25 | // MyCrashHandler myCrashHandler = MyCrashHandler.getInstance();
26 | // myCrashHandler.init(getApplicationContext());
27 | }
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/SplashActivity.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 |
7 | import com.delsart.bookdownload.ui.activity.MainActivity;
8 |
9 | /**
10 | * Created by Delsart on 2017/8/11.
11 | */
12 |
13 | public class SplashActivity extends AppCompatActivity {
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState) {
16 |
17 | super.onCreate(savedInstanceState);
18 |
19 | startActivity(new Intent(this, MainActivity.class));
20 |
21 | finish();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/Url.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload;
2 |
3 |
4 | public interface Url {
5 | String PC_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36";
6 | String MOBBILE_AGENT = "Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A365 Safari/600.1.4";
7 |
8 | String ZHIXUAN = "http://www.zxcs8.com/?keyword=";
9 | String ZHOUDU = "http://www.ireadweek.com/index.php/Index/bookList.html?keyword=";
10 | String M360D = "http://www.360dxs.com/list.html?keyword=";
11 | String SHUYUZHE = "https://book.shuyuzhe.com/search/";
12 | String XIAOSHUWU = "http://mebook.cc/page/0?s=";
13 | String QISHU = "http://zhannei.baidu.com/cse/search?s=2672242722776283010&nsid=&q=";
14 | String AIXIA = "http://m.ixdzs.com/search?k=";
15 | String BLAH = "http://blah.me/search?q=";
16 | String DONGMANZHIJIA="http://s.acg.dmzj.com/lnovelsum/search.php?s=";
17 | }
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/adapter/ItemAdapter.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.adapter;
2 |
3 | import android.support.v7.widget.RecyclerView;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.TextView;
8 |
9 | import com.delsart.bookdownload.R;
10 | import com.delsart.bookdownload.bean.NovelBean;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 |
16 | public class ItemAdapter extends RecyclerView.Adapter {
17 |
18 | private List mList;
19 |
20 | public ItemAdapter() {
21 | mList = new ArrayList<>();
22 | }
23 |
24 | @Override
25 | public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
26 | return new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false));
27 | }
28 |
29 | @Override
30 | public void onBindViewHolder(MyViewHolder holder, int position) {
31 | NovelBean bean = mList.get(position);
32 | holder.mTextViewName.setText(bean.getName());
33 | holder.mTextViewInfo.setText(bean.getShowText());
34 | }
35 |
36 | @Override
37 | public int getItemCount() {
38 | return mList.size();
39 | }
40 |
41 | public void clear() {
42 | int size = mList.size();
43 | mList.clear();
44 | notifyItemRangeRemoved(0, size);
45 | }
46 |
47 | public void add(List beans) {
48 | int size = mList.size();
49 | mList.addAll(beans);
50 | notifyItemRangeInserted(size, beans.size());
51 | }
52 |
53 | static class MyViewHolder extends RecyclerView.ViewHolder {
54 | private TextView mTextViewName;
55 | private TextView mTextViewInfo;
56 |
57 | public MyViewHolder(View itemView) {
58 | super(itemView);
59 | mTextViewInfo = (TextView) itemView.findViewById(R.id.text_view_info);
60 | mTextViewName = (TextView) itemView.findViewById(R.id.text_view_name);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/adapter/MyItemAdapter.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.adapter;
2 |
3 | import com.chad.library.adapter.base.BaseQuickAdapter;
4 | import com.chad.library.adapter.base.BaseViewHolder;
5 | import com.delsart.bookdownload.R;
6 | import com.delsart.bookdownload.bean.NovelBean;
7 |
8 | /**
9 | * Created by Delsart on 2017/8/1.
10 | */
11 |
12 | public class MyItemAdapter extends BaseQuickAdapter {
13 | private int color;
14 | public MyItemAdapter(int color) {
15 | super(R.layout.item_list);
16 | this.color=color;
17 | }
18 |
19 | @Override
20 | protected void convert(BaseViewHolder viewHolder, NovelBean bean) {
21 | viewHolder.setText(R.id.text_view_name, bean.getName())
22 | .setText(R.id.text_view_info, bean.getShowText())
23 | .setBackgroundColor(R.id.text_view_name,color)
24 | .setBackgroundColor(R.id.text_view_info,color);
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/adapter/PagerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.adapter;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.support.v4.app.FragmentManager;
5 | import android.support.v4.app.FragmentStatePagerAdapter;
6 |
7 | import com.delsart.bookdownload.ui.fragment.BaseFragment;
8 |
9 | import java.util.List;
10 |
11 | public class PagerAdapter extends FragmentStatePagerAdapter {
12 | private final List mFragments;
13 | private final List mFragmentTitles;
14 |
15 | public PagerAdapter(FragmentManager fm, List fragments, List titles) {
16 | super(fm);
17 | this.mFragments = fragments;
18 | this.mFragmentTitles = titles;
19 | }
20 |
21 | public void setTop(int pos) {
22 | mFragments.get(pos).toTop();
23 | }
24 |
25 | @Override
26 | public Fragment getItem(int position) {
27 | return mFragments.get(position);
28 | }
29 |
30 | @Override
31 | public int getCount() {
32 | return mFragments.size();
33 | }
34 |
35 | public void remove() {
36 | if (mFragments.size() > 0) {
37 | mFragments.remove(0);
38 | mFragmentTitles.remove(0);
39 | notifyDataSetChanged();
40 | }
41 | }
42 |
43 | public List getFragments() {
44 | return mFragments;
45 | }
46 |
47 | @Override
48 | public CharSequence getPageTitle(int position) {
49 | return mFragmentTitles.get(position);
50 | }
51 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/bean/DownloadBean.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.bean;
2 |
3 | /**
4 | * Created by Delsart on 2017/8/2.
5 | */
6 |
7 | public class DownloadBean {
8 | String type;
9 |
10 | String url;
11 |
12 | public DownloadBean(String type, String url) {
13 | this.type = type;
14 | this.url = url;
15 | }
16 |
17 | public DownloadBean() {
18 | }
19 |
20 | public String getType() {
21 | return type;
22 | }
23 |
24 | public String getUrl() {
25 | return url;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/bean/NovelBean.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.bean;
2 |
3 | public class NovelBean {
4 | private String name;
5 | private String time;
6 | private String info;
7 | private String category;
8 | private String status;
9 | private String author;
10 | private String words;
11 | private String pic;
12 | private String showText;
13 | private String downloadFromUrl;
14 |
15 | public NovelBean(String name, String time, String info, String category, String status, String author, String words, String pic, String downloadFromUrl) {
16 | this.name = name;
17 | this.time = time;
18 | this.info = info;
19 | this.category = category;
20 | this.status = status;
21 | this.author = author;
22 | this.words = words;
23 | this.pic = pic;
24 | this.downloadFromUrl = downloadFromUrl;
25 |
26 | this.showText = (author.equals("") ? "" : author + "\n") +
27 | (category.equals("") ? "" : category + "\n") +
28 | (words.equals("") ? "" : words + "\n") +
29 | (status.equals("") ? "" : status + "\n") +
30 | (time.equals("") ? "" : time + "\n") +
31 | (info.equals("") ? "\n" + "无简介" : "\n" + info);
32 | }
33 |
34 | public String getDownloadFromUrl() {
35 | return downloadFromUrl;
36 | }
37 |
38 | public String getName() {
39 | return name;
40 | }
41 |
42 | public String getTime() {
43 | return time;
44 | }
45 |
46 | public String getInfo() {
47 | return info;
48 | }
49 |
50 | public String getCategory() {
51 | return category;
52 | }
53 |
54 | public String getStatus() {
55 | return status;
56 | }
57 |
58 | public String getAuthor() {
59 | return author;
60 | }
61 |
62 | public String getWords() {
63 | return words;
64 | }
65 |
66 | public String getPic() {
67 | return pic;
68 | }
69 |
70 |
71 | public String getShowText() {
72 | return showText;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/custom/CustomTextView.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.custom;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.support.annotation.ColorInt;
7 | import android.util.AttributeSet;
8 | import android.util.Log;
9 |
10 | /**
11 | * Created by Delsart on 2017/7/28.
12 | */
13 |
14 | public class CustomTextView extends android.support.v7.widget.AppCompatTextView {
15 |
16 | private Paint mPaint;
17 | private int mColor;
18 |
19 | @Override
20 | public void setBackgroundColor(@ColorInt int color) {
21 | mColor =color;
22 | mPaint.setColor(mColor);
23 | }
24 |
25 | public CustomTextView(Context context) {
26 | super(context);
27 | initPaint(context);
28 | }
29 |
30 | public CustomTextView(Context context, AttributeSet attrs) {
31 | super(context, attrs);
32 | initPaint(context);
33 | }
34 |
35 | public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) {
36 | super(context, attrs, defStyleAttr);
37 | initPaint(context);
38 | }
39 |
40 | private void initPaint(Context context) {
41 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
42 | mPaint.setStrokeWidth(2.5f);
43 | mPaint.setColor(mColor);
44 | }
45 |
46 |
47 | @Override
48 | protected void onDraw(Canvas canvas) {
49 | int w = getWidth();
50 | int h = getHeight();
51 | canvas.clipRect(0, 0, w, h);
52 | super.onDraw(canvas);
53 | canvas.drawLine(0, h, w, h, mPaint);
54 | canvas.drawLine(w, h / 1.8f, w, h, mPaint);
55 | canvas.drawLine(0, h / 1.2f, 0, h, mPaint);
56 |
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/custom/MyCustomItem.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.custom;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.os.Build;
6 | import android.support.annotation.DrawableRes;
7 | import android.support.annotation.IntDef;
8 | import android.support.annotation.StringRes;
9 | import android.text.Html;
10 | import android.util.TypedValue;
11 | import android.view.Gravity;
12 | import android.view.View;
13 | import android.widget.ImageView;
14 | import android.widget.LinearLayout;
15 | import android.widget.TextView;
16 |
17 | import com.danielstone.materialaboutlibrary.holders.MaterialAboutItemViewHolder;
18 | import com.danielstone.materialaboutlibrary.items.MaterialAboutItem;
19 | import com.delsart.bookdownload.R;
20 |
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 |
24 | import static android.view.View.GONE;
25 |
26 | /**
27 | * Created by Delsart on 2017/7/24.
28 | */
29 |
30 | public class MyCustomItem extends MaterialAboutItem {
31 |
32 | public static final int GRAVITY_TOP = 0;
33 | public static final int GRAVITY_MIDDLE = 1;
34 | public static final int GRAVITY_BOTTOM = 2;
35 | private CharSequence text = null;
36 | private int textRes = 0;
37 | private CharSequence subText = null;
38 | private int subTextRes = 0;
39 | private Drawable icon = null;
40 | private int iconRes = 0;
41 | private boolean showIcon = true;
42 | private int iconGravity = GRAVITY_MIDDLE;
43 | private MyCustomItem.OnClickListener onClickListener = null;
44 | private MyCustomItem(Builder builder) {
45 | this.text = builder.text;
46 | this.textRes = builder.textRes;
47 |
48 | this.subText = builder.subText;
49 | this.subTextRes = builder.subTextRes;
50 |
51 | this.icon = builder.icon;
52 | this.iconRes = builder.iconRes;
53 |
54 | this.showIcon = builder.showIcon;
55 |
56 | this.iconGravity = builder.iconGravity;
57 |
58 | this.onClickListener = builder.onClickListener;
59 | }
60 |
61 | public MyCustomItem(CharSequence text, CharSequence subText, Drawable icon, OnClickListener onClickListener) {
62 | this.text = text;
63 | this.subText = subText;
64 | this.icon = icon;
65 | this.onClickListener = onClickListener;
66 | }
67 |
68 | public MyCustomItem(CharSequence text, CharSequence subText, Drawable icon) {
69 | this.text = text;
70 | this.subText = subText;
71 | this.icon = icon;
72 | }
73 |
74 | public MyCustomItem(int textRes, int subTextRes, int iconRes, OnClickListener onClickListener) {
75 | this.textRes = textRes;
76 | this.subTextRes = subTextRes;
77 | this.iconRes = iconRes;
78 | this.onClickListener = onClickListener;
79 | }
80 |
81 | public MyCustomItem(int textRes, int subTextRes, int iconRes) {
82 | this.textRes = textRes;
83 | this.subTextRes = subTextRes;
84 | this.iconRes = iconRes;
85 | }
86 |
87 | public static MaterialAboutItemViewHolder getViewHolder(View view) {
88 | return new MyCustomItemViewHolder(view);
89 | }
90 |
91 | public static void setupItem(MyCustomItemViewHolder holder, MyCustomItem item, Context context) {
92 | CharSequence text = item.getText();
93 | int textRes = item.getTextRes();
94 |
95 | holder.text.setVisibility(View.VISIBLE);
96 | if (text != null) {
97 | holder.text.setText(text);
98 | } else if (textRes != 0) {
99 | holder.text.setText(textRes);
100 | } else {
101 | holder.text.setVisibility(GONE);
102 | }
103 |
104 | CharSequence subText = item.getSubText();
105 | int subTextRes = item.getSubTextRes();
106 |
107 | holder.subText.setVisibility(View.VISIBLE);
108 | if (subText != null) {
109 | holder.subText.setText(subText);
110 | } else if (subTextRes != 0) {
111 | holder.subText.setText(subTextRes);
112 | } else {
113 | holder.subText.setVisibility(GONE);
114 | }
115 |
116 | if (item.shouldShowIcon()) {
117 | holder.icon.setVisibility(View.VISIBLE);
118 | Drawable drawable = item.getIcon();
119 | int drawableRes = item.getIconRes();
120 | if (drawable != null) {
121 | holder.icon.setImageDrawable(drawable);
122 | } else if (drawableRes != 0) {
123 | holder.icon.setImageResource(drawableRes);
124 | }
125 | } else {
126 | holder.icon.setVisibility(GONE);
127 | }
128 |
129 | LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) holder.icon.getLayoutParams();
130 | switch (item.getIconGravity()) {
131 | case MyCustomItem.GRAVITY_TOP:
132 | params.gravity = Gravity.TOP;
133 | break;
134 | case MyCustomItem.GRAVITY_MIDDLE:
135 | params.gravity = Gravity.CENTER_VERTICAL;
136 | break;
137 | case MyCustomItem.GRAVITY_BOTTOM:
138 | params.gravity = Gravity.BOTTOM;
139 | break;
140 | }
141 | holder.icon.setLayoutParams(params);
142 |
143 | int pL = 0, pT = 0, pR = 0, pB = 0;
144 | if (Build.VERSION.SDK_INT < 21) {
145 | pL = holder.view.getPaddingLeft();
146 | pT = holder.view.getPaddingTop();
147 | pR = holder.view.getPaddingRight();
148 | pB = holder.view.getPaddingBottom();
149 | }
150 |
151 | if (item.getOnClickListener() != null) {
152 | TypedValue outValue = new TypedValue();
153 | context.getTheme().resolveAttribute(R.attr.selectableItemBackground, outValue, true);
154 | holder.view.setBackgroundResource(outValue.resourceId);
155 | holder.onClickListener = item.getOnClickListener();
156 | holder.view.setSoundEffectsEnabled(true);
157 | } else {
158 | TypedValue outValue = new TypedValue();
159 | context.getTheme().resolveAttribute(R.attr.selectableItemBackground, outValue, false);
160 | holder.view.setBackgroundResource(outValue.resourceId);
161 | holder.onClickListener = null;
162 | holder.view.setSoundEffectsEnabled(false);
163 | }
164 |
165 | if (Build.VERSION.SDK_INT < 21) {
166 | holder.view.setPadding(pL, pT, pR, pB);
167 | }
168 | }
169 |
170 | @Override
171 | public int getType() {
172 | return MyViewTypeManager.CUSTOM_ITEM;
173 | }
174 |
175 | public CharSequence getText() {
176 | return text;
177 | }
178 |
179 | public int getTextRes() {
180 | return textRes;
181 | }
182 |
183 | public CharSequence getSubText() {
184 | return subText;
185 | }
186 |
187 | public int getSubTextRes() {
188 | return subTextRes;
189 | }
190 |
191 | public Drawable getIcon() {
192 | return icon;
193 | }
194 |
195 | public int getIconRes() {
196 | return iconRes;
197 | }
198 |
199 | public boolean shouldShowIcon() {
200 | return showIcon;
201 | }
202 |
203 | @IconGravity
204 | public int getIconGravity() {
205 | return iconGravity;
206 | }
207 |
208 | public MyCustomItem.OnClickListener getOnClickListener() {
209 | return onClickListener;
210 | }
211 |
212 | public interface OnClickListener {
213 | void onClick();
214 |
215 | }
216 |
217 | @Retention(RetentionPolicy.SOURCE)
218 | @IntDef({GRAVITY_TOP, GRAVITY_MIDDLE, GRAVITY_BOTTOM})
219 | public @interface IconGravity {
220 | }
221 |
222 | public static class MyCustomItemViewHolder extends MaterialAboutItemViewHolder implements View.OnClickListener {
223 | public final View view;
224 | public final ImageView icon;
225 | public final TextView text;
226 | public final TextView subText;
227 | public MyCustomItem.OnClickListener onClickListener;
228 |
229 | MyCustomItemViewHolder(View view) {
230 | super(view);
231 | this.view = view;
232 | icon = (ImageView) view.findViewById(R.id.mal_item_image);
233 | text = (TextView) view.findViewById(R.id.mal_item_text);
234 | subText = (TextView) view.findViewById(R.id.mal_action_item_subtext);
235 |
236 | view.setOnClickListener(this);
237 | onClickListener = null;
238 | }
239 |
240 | @Override
241 | public void onClick(View v) {
242 | if (onClickListener != null) {
243 | onClickListener.onClick();
244 | }
245 | }
246 | }
247 |
248 | public static class Builder {
249 |
250 | MyCustomItem.OnClickListener onClickListener;
251 | private CharSequence text = null;
252 | @StringRes
253 | private int textRes = 0;
254 | private CharSequence subText = null;
255 | @StringRes
256 | private int subTextRes = 0;
257 | private Drawable icon = null;
258 | @DrawableRes
259 | private int iconRes = 0;
260 | private boolean showIcon = true;
261 | @IconGravity
262 | private int iconGravity = GRAVITY_MIDDLE;
263 |
264 | public Builder text(CharSequence text) {
265 | this.text = text;
266 | this.textRes = 0;
267 | return this;
268 | }
269 |
270 | public Builder text(@StringRes int text) {
271 | this.textRes = text;
272 | this.text = null;
273 | return this;
274 | }
275 |
276 | public Builder subText(CharSequence subText) {
277 | this.subText = subText;
278 | this.subTextRes = 0;
279 | return this;
280 | }
281 |
282 | public Builder subText(@StringRes int subTextRes) {
283 | this.subText = null;
284 | this.subTextRes = subTextRes;
285 | return this;
286 | }
287 |
288 | public Builder subTextHtml(String subTextHtml) {
289 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
290 | this.subText = Html.fromHtml(subTextHtml, Html.FROM_HTML_MODE_LEGACY);
291 | } else {
292 | //noinspection deprecation
293 | this.subText = Html.fromHtml(subTextHtml);
294 | }
295 | this.subTextRes = 0;
296 | return this;
297 | }
298 |
299 | public Builder icon(Drawable icon) {
300 | this.icon = icon;
301 | this.iconRes = 0;
302 | return this;
303 | }
304 |
305 | public Builder icon(@DrawableRes int iconRes) {
306 | this.icon = null;
307 | this.iconRes = iconRes;
308 | return this;
309 | }
310 |
311 | public Builder showIcon(boolean showIcon) {
312 | this.showIcon = showIcon;
313 | return this;
314 | }
315 |
316 | public Builder setIconGravity(@IconGravity int iconGravity) {
317 | this.iconGravity = iconGravity;
318 | return this;
319 | }
320 |
321 | public Builder setOnClickListener(MyCustomItem.OnClickListener onClickListener) {
322 | this.onClickListener = onClickListener;
323 | return this;
324 | }
325 |
326 | public MyCustomItem build() {
327 | return new MyCustomItem(this);
328 | }
329 | }
330 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/custom/MyViewTypeManager.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.custom;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 |
6 | import com.danielstone.materialaboutlibrary.holders.MaterialAboutItemViewHolder;
7 | import com.danielstone.materialaboutlibrary.items.MaterialAboutActionItem;
8 | import com.danielstone.materialaboutlibrary.items.MaterialAboutItem;
9 | import com.danielstone.materialaboutlibrary.items.MaterialAboutTitleItem;
10 | import com.danielstone.materialaboutlibrary.util.ViewTypeManager;
11 | import com.delsart.bookdownload.R;
12 |
13 |
14 | /**
15 | * Created by Delsart on 2017/7/24.
16 | */
17 | public class MyViewTypeManager extends ViewTypeManager {
18 | public static final int ACTION_ITEM = ViewTypeManager.ItemType.ACTION_ITEM;
19 | public static final int TITLE_ITEM = ViewTypeManager.ItemType.TITLE_ITEM;
20 | public static final int CUSTOM_ITEM = 10;
21 | public static final int ACTION_LAYOUT = ViewTypeManager.ItemLayout.ACTION_LAYOUT;
22 | public static final int TITLE_LAYOUT = ViewTypeManager.ItemLayout.TITLE_LAYOUT;
23 | public static final int CUSTOM_LAYOUT = R.layout.item_custom;
24 |
25 |
26 | public int getLayout(int itemType) {
27 | switch (itemType) {
28 | case ACTION_ITEM:
29 | return ACTION_LAYOUT;
30 | case TITLE_ITEM:
31 | return TITLE_LAYOUT;
32 | case CUSTOM_ITEM:
33 | return CUSTOM_LAYOUT;
34 | default:
35 | return -1;
36 | }
37 | }
38 |
39 | public MaterialAboutItemViewHolder getViewHolder(int itemType, View view) {
40 | switch (itemType) {
41 | case ACTION_ITEM:
42 | return MaterialAboutActionItem.getViewHolder(view);
43 | case TITLE_ITEM:
44 | return MaterialAboutTitleItem.getViewHolder(view);
45 | case CUSTOM_ITEM:
46 | return MyCustomItem.getViewHolder(view);
47 | default:
48 | return null;
49 | }
50 | }
51 |
52 | public void setupItem(int itemType, MaterialAboutItemViewHolder holder, MaterialAboutItem item, Context context) {
53 | switch (itemType) {
54 | case ACTION_ITEM:
55 | MaterialAboutActionItem.setupItem((MaterialAboutActionItem.MaterialAboutActionItemViewHolder) holder, (MaterialAboutActionItem) item, context);
56 | break;
57 | case TITLE_ITEM:
58 | MaterialAboutTitleItem.setupItem((MaterialAboutTitleItem.MaterialAboutTitleItemViewHolder) holder, (MaterialAboutTitleItem) item, context);
59 | break;
60 | case CUSTOM_ITEM:
61 | MyCustomItem.setupItem((MyCustomItem.MyCustomItemViewHolder) holder, (MyCustomItem) item, context);
62 | break;
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/custom/ScrollAwareFABBehavior.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.custom;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.NonNull;
5 | import android.support.design.widget.CoordinatorLayout;
6 | import android.support.design.widget.FloatingActionButton;
7 | import android.support.v4.view.ViewCompat;
8 | import android.support.v4.view.ViewPropertyAnimatorListener;
9 | import android.support.v4.view.animation.FastOutSlowInInterpolator;
10 | import android.util.AttributeSet;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.view.animation.Interpolator;
14 |
15 | public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
16 | private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();
17 | private boolean mIsAnimatingOut = false;
18 |
19 | public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
20 | super();
21 | }
22 |
23 | @Override
24 | public boolean onStartNestedScroll(@NonNull final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
25 | @NonNull final View directTargetChild, @NonNull final View target, final int nestedScrollAxes) {
26 | return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
27 | || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
28 | }
29 |
30 | @Override
31 | public void onNestedScroll(@NonNull final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
32 | @NonNull final View target, final int dxConsumed, final int dyConsumed,
33 | final int dxUnconsumed, final int dyUnconsumed) {
34 | super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
35 | if (dyConsumed > 0 && !this.mIsAnimatingOut && child.getVisibility() == View.VISIBLE) {
36 | animateOut(child);
37 | } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
38 | animateIn(child);
39 | }
40 | }
41 |
42 | private void animateOut(final FloatingActionButton button) {
43 | ViewCompat.animate(button).translationY(button.getHeight() + getMarginBottom(button)).setInterpolator(INTERPOLATOR).withLayer()
44 | .setListener(new ViewPropertyAnimatorListener() {
45 | public void onAnimationStart(View view) {
46 | ScrollAwareFABBehavior.this.mIsAnimatingOut = true;
47 | }
48 |
49 | public void onAnimationCancel(View view) {
50 | ScrollAwareFABBehavior.this.mIsAnimatingOut = false;
51 | }
52 |
53 | public void onAnimationEnd(View view) {
54 | ScrollAwareFABBehavior.this.mIsAnimatingOut = false;
55 | view.setVisibility(View.INVISIBLE);
56 | }
57 | }).start();
58 | }
59 |
60 | private void animateIn(FloatingActionButton button) {
61 | button.setVisibility(View.VISIBLE);
62 | ViewCompat.animate(button).translationY(0)
63 | .setInterpolator(INTERPOLATOR).withLayer().setListener(null)
64 | .start();
65 | }
66 |
67 | private int getMarginBottom(View v) {
68 | int marginBottom = 0;
69 | final ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
70 | if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
71 | marginBottom = ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin;
72 | }
73 | return marginBottom;
74 | }
75 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/glide/MyGlideModule.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.glide;
2 |
3 | import android.content.Context;
4 |
5 | import com.bumptech.glide.GlideBuilder;
6 | import com.bumptech.glide.annotation.GlideModule;
7 | import com.bumptech.glide.load.engine.cache.ExternalCacheDiskCacheFactory;
8 | import com.bumptech.glide.module.AppGlideModule;
9 |
10 | @GlideModule
11 | public class MyGlideModule extends AppGlideModule {
12 | @Override
13 | public void applyOptions(Context context, GlideBuilder builder) {
14 | int diskCacheSizeBytes = 1024 * 1024 * 16;
15 | builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, diskCacheSizeBytes));
16 | }
17 |
18 | @Override
19 | public boolean isManifestParsingEnabled() {
20 | return false;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/handler/MyCrashHandler.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.handler;
2 |
3 | import android.content.ClipboardManager;
4 | import android.content.Context;
5 | import android.os.Looper;
6 | import android.support.v7.app.AlertDialog;
7 | import android.widget.Toast;
8 |
9 | import com.delsart.bookdownload.MyApplication;
10 | import com.delsart.bookdownload.ui.activity.MainActivity;
11 |
12 | /**
13 | * Created by Delsart on 2017/8/7.
14 | */
15 |
16 | public class MyCrashHandler implements Thread.UncaughtExceptionHandler {
17 |
18 | private static MyCrashHandler instance;
19 | Thread.UncaughtExceptionHandler mDefaultHandler;
20 | public static MyCrashHandler getInstance() {
21 | if (instance == null) {
22 | instance = new MyCrashHandler();
23 | }
24 | return instance;
25 | }
26 |
27 | public void init(Context ctx) {
28 | mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
29 | Thread.setDefaultUncaughtExceptionHandler(this);
30 | }
31 |
32 | @Override
33 | public void uncaughtException(Thread t, Throwable e) {
34 | Looper.prepare();
35 | StringBuffer sb=new StringBuffer();
36 | StackTraceElement[] stackTrace = e.getStackTrace();
37 | for (StackTraceElement stackTraceElement : stackTrace) {
38 | sb.append(stackTraceElement.toString());
39 | sb.append("\nfile: ");
40 | sb.append(stackTraceElement.getFileName());
41 | sb.append("\nclass: ");
42 | sb.append(stackTraceElement.getClassName());
43 | sb.append("\nmethod: ");
44 | sb.append(stackTraceElement.getMethodName());
45 | sb.append("\nline: ");
46 | sb.append(stackTraceElement.getLineNumber());
47 | sb.append("\n—————————————————\n");
48 | }
49 | Toast.makeText(MyApplication.getContext(),"Oops!出现错误!\n已将错误日志复制到粘贴板,请向作者反馈\n\n"+sb,Toast.LENGTH_LONG).show();
50 | Toast.makeText(MyApplication.getContext(),"Oops!出现错误!\n已将错误日志复制到粘贴板,请向作者反馈\n\n"+sb,Toast.LENGTH_LONG).show();
51 | ClipboardManager cmb = (ClipboardManager)MyApplication.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
52 | cmb.setText(sb);
53 |
54 | //android.os.Process.killProcess(android.os.Process.myPid());
55 | //System.exit(0);
56 | Looper.loop();
57 |
58 |
59 |
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/handler/MyHandler.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.handler;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 |
6 | import java.lang.ref.WeakReference;
7 |
8 |
9 | public class MyHandler extends Handler {
10 |
11 | private final WeakReference mReference;
12 | private OnHandleMessageCallback onHandleMessageCallback;
13 |
14 | public MyHandler(T t) {
15 | mReference = new WeakReference<>(t);
16 | }
17 |
18 | public void setOnHandleMessageCallback(OnHandleMessageCallback onHandleMessageCallback) {
19 | this.onHandleMessageCallback = onHandleMessageCallback;
20 | }
21 |
22 | @Override
23 | public void handleMessage(Message msg) {
24 | T t = mReference.get();
25 | if (t != null && onHandleMessageCallback != null) {
26 | onHandleMessageCallback.handleMessage(t, msg);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/handler/OnHandleMessageCallback.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.handler;
2 |
3 |
4 | import android.os.Message;
5 |
6 | public interface OnHandleMessageCallback {
7 | void handleMessage(T t, Message msg);
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/service/AiXiaService.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.service;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 |
6 | import com.delsart.bookdownload.MsgType;
7 | import com.delsart.bookdownload.Url;
8 | import com.delsart.bookdownload.bean.DownloadBean;
9 | import com.delsart.bookdownload.bean.NovelBean;
10 |
11 | import org.jsoup.Jsoup;
12 | import org.jsoup.nodes.Document;
13 | import org.jsoup.nodes.Element;
14 | import org.jsoup.select.Elements;
15 |
16 | import java.io.IOException;
17 | import java.util.ArrayList;
18 | import java.util.concurrent.CountDownLatch;
19 |
20 | public class AiXiaService extends BaseService {
21 | private final Handler mHandler;
22 | private int mPage;
23 | private String mBaseUrl;
24 | private CountDownLatch latch;
25 | private ArrayList list = new ArrayList<>();
26 |
27 | public AiXiaService(Handler handler, String keywords) {
28 | super(handler, keywords);
29 | this.mHandler = handler;
30 | mPage = 1;
31 | mBaseUrl = Url.AIXIA + keywords + "&page=";
32 | }
33 |
34 | @Override
35 | public void get() {
36 | new Thread(new Runnable() {
37 | @Override
38 | public void run() {
39 | try {
40 | list.clear();
41 | Elements select = Jsoup.connect(mBaseUrl + mPage)
42 | .timeout(10000)
43 | .ignoreContentType(true)
44 | .ignoreHttpErrors(true)
45 | .userAgent(Url.MOBBILE_AGENT)
46 | .get()
47 | .select("body > div.list > li > a");
48 | latch = new CountDownLatch(select.size());
49 | for (Element element : select) {
50 | runInSameTime(element);
51 | }
52 | latch.await();
53 | mPage++;
54 | Message msg = mHandler.obtainMessage();
55 | msg.what = MsgType.SUCCESS;
56 | msg.obj = list;
57 | mHandler.sendMessage(msg);
58 | } catch (IOException e) {
59 | e.printStackTrace();
60 | Message msg = mHandler.obtainMessage();
61 | msg.what = MsgType.ERROR;
62 | mHandler.sendMessage(msg);
63 | } catch (InterruptedException e) {
64 | e.printStackTrace();
65 | }
66 | }
67 | }).start();
68 | }
69 |
70 | private void runInSameTime(final Element element) throws IOException {
71 | mExecutorService.submit(new Runnable() {
72 | @Override
73 | public void run() {
74 | String url = element.attr("abs:href");
75 | try {
76 | Document document = Jsoup.connect(url)
77 | .ignoreContentType(true)
78 | .ignoreHttpErrors(true)
79 | .userAgent(Url.MOBBILE_AGENT)
80 | .get();
81 | String name = document.select("body > div:nth-child(2) > h1").text();
82 | String time = document.select("body > div:nth-child(3) > li:nth-child(6)").text();
83 | String info = document.select("body > div.intro > li").text();
84 | String category = document.select("body > div:nth-child(3) > li:nth-child(2)").text();
85 | String status = document.select("body > div:nth-child(3) > li:nth-child(5)").text();
86 | String author = document.select("body > div:nth-child(3) > li:nth-child(1)").text();
87 | String words = document.select("body > div:nth-child(3) > li:nth-child(3)").text();
88 | String pic = "";
89 | NovelBean no = new NovelBean(name, time, info, category, status, author, words, pic, url);
90 | list.add(no);
91 | } catch (IOException e) {
92 | e.printStackTrace();
93 | }
94 | latch.countDown();
95 | }
96 | });
97 | }
98 |
99 |
100 | @Override
101 | public ArrayList getDownloadurls(final String url) throws InterruptedException {
102 | latch = new CountDownLatch(1);
103 | final ArrayList urls = new ArrayList<>();
104 | mExecutorService.submit(new Runnable() {
105 | @Override
106 | public void run() {
107 | try {
108 | Elements elements = Jsoup.connect(url)
109 | .timeout(10000)
110 | .ignoreContentType(true)
111 | .ignoreHttpErrors(true)
112 | .userAgent(Url.MOBBILE_AGENT)
113 | .get()
114 | .select("body > div:nth-child(5)");
115 | String u1 = elements.select("li:nth-child(2) > a").attr("abs:href");
116 | String u1n = elements.select("li:nth-child(2) > a").text();
117 | String u2 = elements.select("li:nth-child(3) > a").attr("abs:href");
118 | String u2n = elements.select("li:nth-child(3) > a").text();
119 | urls.add(new DownloadBean(u1n, u1));
120 | urls.add(new DownloadBean(u2n, u2));
121 | } catch (IOException e) {
122 | e.printStackTrace();
123 | }
124 | latch.countDown();
125 | }
126 | });
127 | latch.await();
128 | return urls;
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/service/BaseService.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.service;
2 |
3 |
4 | import android.os.Handler;
5 |
6 | import com.delsart.bookdownload.bean.DownloadBean;
7 |
8 | import java.io.UnsupportedEncodingException;
9 | import java.util.ArrayList;
10 | import java.util.concurrent.ExecutorService;
11 | import java.util.concurrent.Executors;
12 |
13 | public abstract class BaseService {
14 | public ExecutorService mExecutorService= Executors.newFixedThreadPool(4);
15 | public BaseService(Handler handler, String keywords) {
16 | }
17 |
18 | public static String toUtf8(String str) {
19 | String result = null;
20 | try {
21 | result = new String(str.getBytes("UTF-8"), "UTF-8");
22 | } catch (UnsupportedEncodingException e) {
23 | // TODO Auto-generated catch block
24 | e.printStackTrace();
25 | }
26 | return result;
27 | }
28 |
29 | public void reLoad(){
30 | get();
31 | }
32 | public abstract void get();
33 |
34 | public abstract ArrayList getDownloadurls(String url) throws InterruptedException;
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/service/BlahService.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.service;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 |
6 | import com.delsart.bookdownload.MsgType;
7 | import com.delsart.bookdownload.Url;
8 | import com.delsart.bookdownload.bean.DownloadBean;
9 | import com.delsart.bookdownload.bean.NovelBean;
10 |
11 | import org.jsoup.Jsoup;
12 | import org.jsoup.nodes.Document;
13 | import org.jsoup.nodes.Element;
14 | import org.jsoup.select.Elements;
15 |
16 | import java.io.IOException;
17 | import java.util.ArrayList;
18 | import java.util.List;
19 | import java.util.concurrent.CountDownLatch;
20 |
21 | public class BlahService extends BaseService {
22 | private static String TAG = "test";
23 | private final Handler mHandler;
24 | private int mPage;
25 | private String mBaseUrl;
26 | private CountDownLatch latch;
27 | private ArrayList list = new ArrayList<>();
28 |
29 | public BlahService(Handler handler, String keywords) {
30 | super(handler, keywords);
31 | this.mHandler = handler;
32 | mPage = 1;
33 | mBaseUrl = Url.BLAH + keywords + "&page=";
34 | }
35 | String lasts="";
36 | @Override
37 | public void get() {
38 | new Thread(new Runnable() {
39 | @Override
40 | public void run() {
41 | try {
42 | list.clear();
43 | Elements select = Jsoup.connect(mBaseUrl + mPage)
44 | .timeout(10000)
45 | .ignoreContentType(true)
46 | .ignoreHttpErrors(true)
47 | .userAgent(Url.MOBBILE_AGENT)
48 | .get()
49 | .select("div.ok-book-item").select("a.okShowInfoModal");
50 | latch = new CountDownLatch(select.size());
51 | for (int i = 0; i < select.size(); i++) {
52 | runInSameTime(select.get(i));
53 | }
54 | latch.await();
55 | if (select.toString().equals(lasts))
56 | list.clear();
57 | lasts=select.toString();
58 |
59 | mPage++;
60 | Message msg = mHandler.obtainMessage();
61 | msg.what = MsgType.SUCCESS;
62 | msg.obj = list;
63 | mHandler.sendMessage(msg);
64 | } catch (IOException e) {
65 | e.printStackTrace();
66 | Message msg = mHandler.obtainMessage();
67 | msg.what = MsgType.ERROR;
68 | mHandler.sendMessage(msg);
69 | } catch (InterruptedException e) {
70 | e.printStackTrace();
71 | }
72 | }
73 | }).start();
74 | }
75 |
76 | private void runInSameTime(final Element element) throws IOException {
77 | mExecutorService.submit(new Runnable() {
78 | @Override
79 | public void run() {
80 | String url = element.attr("abs:href");
81 | try {
82 | Document document = Jsoup.connect(url)
83 | .ignoreContentType(true)
84 | .ignoreHttpErrors(true)
85 | .userAgent(Url.MOBBILE_AGENT)
86 | .get();
87 |
88 | String name = document.select("#okBookShow > div.ok-book-base-info > div.row > div.col-sm-8.ok-book-info > div.ok-book-meta > h1").text();
89 | String time = "";
90 | String info = "";
91 | Elements elements = document.select("#okBookShow > div.ok-book-base-info > div.row > div.col-sm-8.ok-book-info > div.ok-book-meta > div.ok-book-desc > div.ok-book-meta-content").select("p");
92 | for (int i = 0; i < elements.size(); i++) {
93 |
94 |
95 | if (!elements.get(i).text().equals(""))
96 | info = info + elements.get(i).text() + "\n\n";
97 |
98 |
99 | }
100 | String category = document.select("#okBookShow > div.ok-book-base-info > div.row > div.col-sm-8.ok-book-info > div.ok-book-meta > div.ok-book-subjects").text();
101 | String status = "";
102 | String author = document.select("#okBookShow > div.ok-book-base-info > div.row > div.col-sm-8.ok-book-info > div.ok-book-meta > div.row > div > div").text();
103 | String words = "";
104 | String pic = document.select("#okBookShow > div.ok-book-base-info > div.row > div.col-sm-4 > div > img").attr("abs:src");
105 | NovelBean no = new NovelBean(name, time, info, category, status, author, words, pic, url);
106 | list.add(no);
107 | } catch (IOException e) {
108 | e.printStackTrace();
109 | }
110 |
111 | latch.countDown();
112 | }
113 | });
114 | }
115 |
116 |
117 | @Override
118 | public ArrayList getDownloadurls(final String url) throws InterruptedException {
119 | latch = new CountDownLatch(1);
120 | final ArrayList urls = new ArrayList<>();
121 | mExecutorService.submit(new Runnable() {
122 | @Override
123 | public void run() {
124 | try {
125 | Document document = Jsoup.connect(url)
126 | .timeout(10000)
127 | .ignoreContentType(true)
128 | .ignoreHttpErrors(true)
129 | .userAgent(Url.MOBBILE_AGENT)
130 | .get();
131 |
132 | Elements elements = document.select("#okBookShow > div.ok-book-base-info > div.row > div.col-sm-8.ok-book-info > div.ok-book-opt > div > div.col-md-5.ok-book-download > div a");
133 | if (elements != null) {
134 | for (Element element : elements) {
135 | urls.add(new DownloadBean(element.text(), element.attr("abs:href")));
136 | }
137 | }
138 |
139 | } catch (IOException e) {
140 | e.printStackTrace();
141 | }
142 |
143 | latch.countDown();
144 | }
145 | });
146 | latch.await();
147 | return urls;
148 | }
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/service/DongManZhiJiaService.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.service;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 | import android.util.Log;
6 |
7 | import com.delsart.bookdownload.MsgType;
8 | import com.delsart.bookdownload.Url;
9 | import com.delsart.bookdownload.bean.DownloadBean;
10 | import com.delsart.bookdownload.bean.NovelBean;
11 |
12 | import org.json.JSONArray;
13 | import org.json.JSONException;
14 | import org.json.JSONObject;
15 | import org.jsoup.Jsoup;
16 | import org.jsoup.select.Elements;
17 |
18 | import java.io.IOException;
19 | import java.util.ArrayList;
20 | import java.util.concurrent.CountDownLatch;
21 | import java.util.regex.Matcher;
22 | import java.util.regex.Pattern;
23 |
24 | public class DongManZhiJiaService extends BaseService {
25 | private final Handler mHandler;
26 | private int mPage;
27 | private String mBaseUrl;
28 | private CountDownLatch latch;
29 | private ArrayList list = new ArrayList<>();
30 | final String MAINURL = "http://q.dmzj.com";
31 |
32 | public DongManZhiJiaService(Handler handler, String keywords) {
33 | super(handler, keywords);
34 | this.mHandler = handler;
35 | mPage = 1;
36 | mBaseUrl = Url.DONGMANZHIJIA + keywords;
37 | }
38 |
39 | @Override
40 | public void get() {
41 | new Thread(new Runnable() {
42 | @Override
43 | public void run() {
44 | try {
45 | list.clear();
46 | String select = Jsoup.connect(mBaseUrl)
47 | .timeout(10000)
48 | .ignoreContentType(true)
49 | .ignoreHttpErrors(true)
50 | .userAgent(Url.MOBBILE_AGENT)
51 | .get().toString();
52 | if (select.contains("[")) {
53 | select = select.substring(select.indexOf("["), select.length());
54 | JSONArray jsonArray = new JSONArray(select);
55 | latch = new CountDownLatch(jsonArray.length());
56 | for (int i = 0; i < jsonArray.length(); i++) {
57 | runInSameTime(jsonArray.getJSONObject(i));
58 | }
59 | latch.await();
60 | Message msg = mHandler.obtainMessage();
61 | msg.what = MsgType.SUCCESS;
62 | msg.obj = list;
63 | mHandler.sendMessage(msg);
64 | }
65 | else
66 | {
67 | Message msg = mHandler.obtainMessage();
68 | msg.what = MsgType.ERROR;
69 | mHandler.sendMessage(msg);
70 | }
71 | } catch (IOException e) {
72 | e.printStackTrace();
73 | Message msg = mHandler.obtainMessage();
74 | msg.what = MsgType.ERROR;
75 | mHandler.sendMessage(msg);
76 | } catch (JSONException e) {
77 | e.printStackTrace();
78 | } catch (InterruptedException e) {
79 | e.printStackTrace();
80 | }
81 | }
82 | }).start();
83 | }
84 |
85 | private void runInSameTime(final JSONObject jsonObject) throws IOException {
86 | mExecutorService.submit(new Runnable() {
87 | @Override
88 | public void run() {
89 | try {
90 | String name = jsonObject.getString("full_name");
91 | String time = "";
92 | String info = jsonObject.getString("description");
93 | String category = "类型:" + jsonObject.getString("types");
94 | String status = "状态:" + jsonObject.getString("status");
95 | String author = "作者:" + jsonObject.getString("author");
96 | String words = "最新章节:" + jsonObject.getString("last_chapter_name");
97 | String pic = jsonObject.getString("image_url");
98 | String url = MAINURL + jsonObject.getString("lnovel_url").replace("..", "");
99 | NovelBean no = new NovelBean(name, time, info, category, status, author, words, pic, url);
100 | list.add(no);
101 | } catch (JSONException e) {
102 | e.printStackTrace();
103 | }
104 | latch.countDown();
105 | }
106 | });
107 | }
108 |
109 |
110 | @Override
111 | public ArrayList getDownloadurls(final String url) throws InterruptedException {
112 | latch = new CountDownLatch(1);
113 | final ArrayList urls = new ArrayList<>();
114 | mExecutorService.submit(new Runnable() {
115 | @Override
116 | public void run() {
117 | try {
118 | Elements elements = Jsoup.connect(url)
119 | .timeout(10000)
120 | .ignoreContentType(true)
121 | .ignoreHttpErrors(true)
122 | .userAgent(Url.MOBBILE_AGENT)
123 | .get()
124 | .getElementsByTag("script");
125 | Matcher m = Pattern.compile("[^a-z]+
.+[^a-z]+").matcher(elements.toString());
126 | while (m.find()) {
127 | String name="";
128 | String path="";
129 | Matcher matcher = Pattern.compile("([^a-z]+)
").matcher(m.group());
130 | if (matcher.find()) {
131 | name = matcher.group(1);
132 | }
133 | matcher = Pattern.compile("[^a-z]+").matcher(m.group());
134 | if (matcher.find()) {
135 | path = matcher.group(1);
136 |
137 | }
138 | urls.add(new DownloadBean(name, path));
139 | }
140 |
141 | } catch (IOException e) {
142 | e.printStackTrace();
143 | }
144 | latch.countDown();
145 | }
146 | });
147 | latch.await();
148 | return urls;
149 | }
150 |
151 | }
152 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/service/EpubeeService.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.service;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 |
6 | import com.delsart.bookdownload.MsgType;
7 | import com.delsart.bookdownload.Url;
8 | import com.delsart.bookdownload.bean.DownloadBean;
9 | import com.delsart.bookdownload.bean.NovelBean;
10 |
11 | import org.jsoup.Jsoup;
12 | import org.jsoup.nodes.Document;
13 | import org.jsoup.nodes.Element;
14 | import org.jsoup.select.Elements;
15 |
16 | import java.io.IOException;
17 | import java.util.ArrayList;
18 | import java.util.concurrent.CountDownLatch;
19 |
20 | public class EpubeeService extends BaseService {
21 | private final Handler mHandler;
22 | private int mPage;
23 | private String mBaseUrl;
24 | private CountDownLatch latch;
25 | private ArrayList list = new ArrayList<>();
26 |
27 | public EpubeeService(Handler handler, String keywords) {
28 | super(handler, keywords);
29 | this.mHandler = handler;
30 | mPage = 1;
31 | mBaseUrl = Url.AIXIA + keywords + "&page=";
32 | }
33 |
34 | @Override
35 | public void get() {
36 | new Thread(new Runnable() {
37 | @Override
38 | public void run() {
39 | try {
40 | list.clear();
41 | Elements select = Jsoup.connect(mBaseUrl + mPage)
42 | .timeout(10000)
43 | .ignoreContentType(true)
44 | .ignoreHttpErrors(true)
45 | .userAgent(Url.MOBBILE_AGENT)
46 | .get()
47 | .select("body > div.list > li > a");
48 | latch = new CountDownLatch(select.size());
49 | for (Element element : select) {
50 | runInSameTime(element);
51 | }
52 | latch.await();
53 | mPage++;
54 | Message msg = mHandler.obtainMessage();
55 | msg.what = MsgType.SUCCESS;
56 | msg.obj = list;
57 | mHandler.sendMessage(msg);
58 | } catch (IOException e) {
59 | e.printStackTrace();
60 | Message msg = mHandler.obtainMessage();
61 | msg.what = MsgType.ERROR;
62 | mHandler.sendMessage(msg);
63 | } catch (InterruptedException e) {
64 | e.printStackTrace();
65 | }
66 | }
67 | }).start();
68 | }
69 |
70 | private void runInSameTime(final Element element) throws IOException {
71 | mExecutorService.submit(new Runnable() {
72 | @Override
73 | public void run() {
74 | String url = element.attr("abs:href");
75 | try {
76 | Document document = Jsoup.connect(url)
77 | .ignoreContentType(true)
78 | .ignoreHttpErrors(true)
79 | .userAgent(Url.MOBBILE_AGENT)
80 | .get();
81 | String name = document.select("body > div:nth-child(2) > h1").text();
82 | String time = document.select("body > div:nth-child(3) > li:nth-child(6)").text();
83 | String info = document.select("body > div.intro > li").text();
84 | String category = document.select("body > div:nth-child(3) > li:nth-child(2)").text();
85 | String status = document.select("body > div:nth-child(3) > li:nth-child(5)").text();
86 | String author = document.select("body > div:nth-child(3) > li:nth-child(1)").text();
87 | String words = document.select("body > div:nth-child(3) > li:nth-child(3)").text();
88 | String pic = "";
89 | NovelBean no = new NovelBean(name, time, info, category, status, author, words, pic, url);
90 | list.add(no);
91 | } catch (IOException e) {
92 | e.printStackTrace();
93 | }
94 | latch.countDown();
95 | }
96 | });
97 | }
98 |
99 |
100 | @Override
101 | public ArrayList getDownloadurls(final String url) throws InterruptedException {
102 | latch = new CountDownLatch(1);
103 | final ArrayList urls = new ArrayList<>();
104 | mExecutorService.submit(new Runnable() {
105 | @Override
106 | public void run() {
107 | try {
108 | Elements elements = Jsoup.connect(url)
109 | .timeout(10000)
110 | .ignoreContentType(true)
111 | .ignoreHttpErrors(true)
112 | .userAgent(Url.MOBBILE_AGENT)
113 | .get()
114 | .select("body > div:nth-child(5)");
115 | String u1 = elements.select("li:nth-child(2) > a").attr("abs:href");
116 | String u1n = elements.select("li:nth-child(2) > a").text();
117 | String u2 = elements.select("li:nth-child(3) > a").attr("abs:href");
118 | String u2n = elements.select("li:nth-child(3) > a").text();
119 | urls.add(new DownloadBean(u1n, u1));
120 | urls.add(new DownloadBean(u2n, u2));
121 | } catch (IOException e) {
122 | e.printStackTrace();
123 | }
124 | latch.countDown();
125 | }
126 | });
127 | latch.await();
128 | return urls;
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/service/M360DService.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.service;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 |
6 | import com.delsart.bookdownload.MsgType;
7 | import com.delsart.bookdownload.Url;
8 | import com.delsart.bookdownload.bean.DownloadBean;
9 | import com.delsart.bookdownload.bean.NovelBean;
10 |
11 | import org.jsoup.Jsoup;
12 | import org.jsoup.nodes.Document;
13 | import org.jsoup.nodes.Element;
14 | import org.jsoup.select.Elements;
15 |
16 | import java.io.IOException;
17 | import java.util.ArrayList;
18 | import java.util.concurrent.CountDownLatch;
19 |
20 | public class M360DService extends BaseService {
21 | private static String TAG = "test";
22 | private final Handler mHandler;
23 | private int mPage;
24 | private String mBaseUrl;
25 | private CountDownLatch latch;
26 | private ArrayList urls = new ArrayList<>();
27 | private ArrayList list = new ArrayList<>();
28 |
29 | public M360DService(Handler handler, String keywords) {
30 | super(handler, keywords);
31 | this.mHandler = handler;
32 | mPage = 1;
33 | mBaseUrl = Url.M360D + keywords + "&page=";
34 | }
35 |
36 | @Override
37 | public void get() {
38 | new Thread(new Runnable() {
39 | @Override
40 | public void run() {
41 | try {
42 | list.clear();
43 | Elements select = Jsoup.connect(mBaseUrl + mPage)
44 | .timeout(10000)
45 | .ignoreContentType(true)
46 | .ignoreHttpErrors(true)
47 | .userAgent(Url.MOBBILE_AGENT)
48 | .get()
49 | .select("div[itemtype=http://schema.org/Novel].am-thumbnail");
50 | latch = new CountDownLatch(select.size());
51 | for (int i = 0; i < select.size(); i++) {
52 | runInSameTime(select.get(i));
53 | }
54 | latch.await();
55 | mPage++;
56 | Message msg = mHandler.obtainMessage();
57 | msg.what = MsgType.SUCCESS;
58 | msg.obj = list;
59 | mHandler.sendMessage(msg);
60 | } catch (IOException e) {
61 | e.printStackTrace();
62 | Message msg = mHandler.obtainMessage();
63 | msg.what = MsgType.ERROR;
64 | mHandler.sendMessage(msg);
65 | } catch (InterruptedException e) {
66 | e.printStackTrace();
67 | }
68 | }
69 | }).start();
70 | }
71 |
72 | private void runInSameTime(final Element element) throws IOException {
73 | mExecutorService.submit(new Runnable() {
74 | @Override
75 | public void run() {
76 | String name = element.select("a[itemprop=name]").text();
77 | String durl = element.select("a[itemprop=name]").attr("abs:href");
78 | String time = "最后更新:" + element.select("span[itemprop=dateModified]").text();
79 | String info = element.select("div[itemprop=description]").text();
80 | String category = "分类:" + element.select("a[itemprop=genre]").text();
81 | String status = "状态:" + element.select("span[itemprop=updataStatus]").text();
82 | String author = "作者:" + element.select("a[itemprop=author]").text();
83 | String words = "";
84 | String pic = "http://www.360dxs.com/static/books/logo/" + durl.substring(durl.indexOf("_") + 1, durl.indexOf(".html")) + "s.jpg";
85 | NovelBean no = new NovelBean(name, time, info, category, status, author, words, pic, durl);
86 | list.add(no);
87 | latch.countDown();
88 | }
89 | });
90 |
91 | }
92 |
93 | @Override
94 | public ArrayList getDownloadurls(final String url) throws InterruptedException {
95 | latch = new CountDownLatch(1);
96 | final ArrayList urls = new ArrayList<>();
97 | mExecutorService.submit(new Runnable() {
98 | @Override
99 | public void run() {
100 | try {
101 | Document document = Jsoup.connect(url)
102 | .timeout(10000)
103 | .ignoreContentType(true)
104 | .ignoreHttpErrors(true)
105 | .userAgent(Url.MOBBILE_AGENT)
106 | .get();
107 | Document document2 = Jsoup.connect(document.select("a:contains(全文下载)").attr("abs:href")).get();
108 | Elements elements = document2.select("div.am-u-sm-12").get(1).select("a");
109 | for (Element element : elements) {
110 | urls.add(new DownloadBean("全文下载: " + element.text(), element.attr("abs:href")));
111 | }
112 | document = Jsoup.connect(document.select("a:contains(分卷下载)").attr("abs:href")).get();
113 | Elements elements1 = document.select("div.am-u-sm-12").get(1).select("h3.am-text-center");
114 | Elements elements2 = document.select("div.am-u-sm-12").get(1).select("ul");
115 | for (int i = 0; i < elements2.size(); i++) {
116 | Elements elements3 = elements2.get(i).select("a");
117 | for (Element element : elements3) {
118 | urls.add(new DownloadBean(elements1.get(i).text() + ":" + element.text(), element.attr("abs:href")));
119 | }
120 | }
121 | } catch (IOException e) {
122 | e.printStackTrace();
123 | }
124 | latch.countDown();
125 | }
126 | });
127 | latch.await();
128 | return urls;
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/service/QiShuService.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.service;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 | import android.util.Log;
6 |
7 | import com.delsart.bookdownload.MsgType;
8 | import com.delsart.bookdownload.Url;
9 | import com.delsart.bookdownload.bean.DownloadBean;
10 | import com.delsart.bookdownload.bean.NovelBean;
11 |
12 | import org.jsoup.Jsoup;
13 | import org.jsoup.nodes.Document;
14 | import org.jsoup.nodes.Element;
15 | import org.jsoup.select.Elements;
16 |
17 | import java.io.IOException;
18 | import java.util.ArrayList;
19 | import java.util.concurrent.CountDownLatch;
20 |
21 | public class QiShuService extends BaseService {
22 | private static String TAG = "test";
23 | private final Handler mHandler;
24 | private int mPage;
25 | private String mBaseUrl;
26 | private CountDownLatch latch;
27 | private ArrayList list = new ArrayList<>();
28 |
29 | public QiShuService(Handler handler, String keywords) {
30 | super(handler, keywords);
31 | this.mHandler = handler;
32 | mPage = 0;
33 | mBaseUrl = Url.QISHU + toUtf8(keywords) + "&p=";
34 | }
35 | String lasts="";
36 | @Override
37 | public void get() {
38 | new Thread(new Runnable() {
39 | @Override
40 | public void run() {
41 | try {
42 | list.clear();
43 | Elements select = Jsoup.connect(mBaseUrl + mPage)
44 | .timeout(10000)
45 | //.ignoreContentType(true)
46 | .ignoreHttpErrors(true)
47 | .userAgent(Url.PC_AGENT)
48 | .get()
49 | .select("div#results").select("h3.c-title").select("a");
50 | latch = new CountDownLatch(select.size());
51 | for (int i = 0; i < select.size(); i++) {
52 | runInSameTime(select.get(i));
53 | }
54 | latch.await();
55 | if (select.toString().equals(lasts))
56 | list.clear();
57 | lasts=select.toString();
58 | mPage++;
59 | Message msg = mHandler.obtainMessage();
60 | msg.what = MsgType.SUCCESS;
61 | msg.obj = list;
62 | mHandler.sendMessage(msg);
63 | } catch (Exception e) {
64 | e.printStackTrace();
65 | Message msg = mHandler.obtainMessage();
66 | msg.what = MsgType.ERROR;
67 | mHandler.sendMessage(msg);
68 | }
69 | }
70 | }).start();
71 | }
72 |
73 | private void runInSameTime(final Element element) throws IOException {
74 | mExecutorService.submit(new Runnable() {
75 | @Override
76 | public void run() {
77 | String url = element.attr("abs:href");
78 | if (!url.contains(".html")) {
79 | latch.countDown();
80 | return;
81 | } try {
82 | Document document = Jsoup.connect(url)
83 | .ignoreContentType(true)
84 | .ignoreHttpErrors(true)
85 | .get();
86 | Elements a = document.select("div.detail");
87 | if (a.select("li").size() < 7) {
88 | Log.d(TAG, "run:qishu错误 " + url);
89 | latch.countDown();
90 | return;
91 | }
92 | String name = a.select("h1").text();
93 | String time = a.select("li.small").get(4).text();
94 | String info = document.select("body > div:nth-child(4) > div.show > div:nth-child(2) > div.showInfo").text();
95 | String category = a.select("li.small").get(3).text();
96 | String status = a.select("li.small").get(5).text();
97 | String author = a.select("li.small").get(6).text();
98 | String words = a.select("li.small").get(2).text();
99 | String pic = a.select("img").attr("abs:src");
100 | NovelBean no = new NovelBean(name, time, info, category, status, author, words, pic, url);
101 | list.add(no);
102 | } catch (IOException e) {
103 | e.printStackTrace();
104 | }
105 | latch.countDown();
106 | }
107 | });
108 | }
109 |
110 |
111 | @Override
112 | public ArrayList getDownloadurls(final String url) throws InterruptedException {
113 | latch = new CountDownLatch(1);
114 | final ArrayList urls = new ArrayList<>();
115 | mExecutorService.submit(new Runnable() {
116 | @Override
117 | public void run() {
118 | try {
119 | Document document = Jsoup.connect(url)
120 | .timeout(10000)
121 | .ignoreContentType(true)
122 | .ignoreHttpErrors(true)
123 | .userAgent(Url.MOBBILE_AGENT)
124 | .get();
125 |
126 | String u1 = document.select("body > div:nth-child(4) > div.show > div:nth-child(4) > div.showDown > ul > li:nth-child(1) > a").attr("abs:href");
127 | String u1n = document.select("body > div:nth-child(4) > div.show > div:nth-child(4) > div.showDown > ul > li:nth-child(1) > a").text();
128 | String u2 = document.select("body > div:nth-child(4) > div.show > div:nth-child(4) > div.showDown > ul > li:nth-child(2) > a").attr("abs:href");
129 | String u2n = document.select("body > div:nth-child(4) > div.show > div:nth-child(4) > div.showDown > ul > li:nth-child(2) > a").text();
130 | String u3 = document.select("body > div:nth-child(4) > div.show > div:nth-child(4) > div.showDown > ul > li:nth-child(3) > a").attr("abs:href");
131 | String u3n = document.select("body > div:nth-child(4) > div.show > div:nth-child(4) > div.showDown > ul > li:nth-child(3) > a").text();
132 | urls.add(new DownloadBean(u1n, u1));
133 | urls.add(new DownloadBean(u2n, u2));
134 | urls.add(new DownloadBean(u3n, u3));
135 | } catch (IOException e) {
136 | e.printStackTrace();
137 | }
138 | latch.countDown();
139 | }
140 | });
141 | latch.await();
142 | return urls;
143 | }
144 |
145 | }
146 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/service/ShuYuZheService.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.service;
2 |
3 | import android.icu.text.LocaleDisplayNames;
4 | import android.os.Handler;
5 | import android.os.Message;
6 | import android.util.Log;
7 |
8 | import com.delsart.bookdownload.MsgType;
9 | import com.delsart.bookdownload.Url;
10 | import com.delsart.bookdownload.bean.DownloadBean;
11 | import com.delsart.bookdownload.bean.NovelBean;
12 |
13 | import org.jsoup.Jsoup;
14 | import org.jsoup.nodes.Document;
15 | import org.jsoup.nodes.Element;
16 | import org.jsoup.select.Elements;
17 |
18 | import java.io.IOException;
19 | import java.util.ArrayList;
20 | import java.util.concurrent.CountDownLatch;
21 | import java.util.jar.Attributes;
22 | import java.util.regex.Matcher;
23 | import java.util.regex.Pattern;
24 |
25 | public class ShuYuZheService extends BaseService {
26 | private static String TAG = "test";
27 | private final Handler mHandler;
28 | private int mPage;
29 | private String mBaseUrl;
30 | private CountDownLatch latch;
31 | private ArrayList list = new ArrayList<>();
32 |
33 | public ShuYuZheService(Handler handler, String keywords) {
34 | super(handler, keywords);
35 | this.mHandler = handler;
36 | mPage = 1;
37 | mBaseUrl = Url.SHUYUZHE + keywords;
38 | }
39 |
40 | @Override
41 | public void get() {
42 | new Thread(new Runnable() {
43 | @Override
44 | public void run() {
45 | try {
46 | list.clear();
47 | Log.d(TAG, "run: "+mBaseUrl + "/"+mPage);
48 | Elements select = Jsoup.connect(mBaseUrl + "/"+mPage)
49 | .timeout(10000)
50 | .ignoreContentType(true)
51 | .ignoreHttpErrors(true)
52 | .userAgent(Url.PC_AGENT)
53 | .get()
54 | .select("body > div.container > div > div > div.panel.panel-success > div.panel-body > table > tbody > tr");
55 | latch = new CountDownLatch(select.size() - 1);
56 | for (int i = 1; i < select.size(); i++) {
57 | runInSameTime(select.get(i));
58 | }
59 |
60 | Log.d(TAG, "run: "+select.size());
61 | latch.await();
62 | mPage++;
63 |
64 |
65 |
66 |
67 | Message msg = mHandler.obtainMessage();
68 | msg.what = MsgType.SUCCESS;
69 | msg.obj = list;
70 | mHandler.sendMessage(msg);
71 |
72 | } catch (IOException e) {
73 | e.printStackTrace();
74 | Message msg = mHandler.obtainMessage();
75 | msg.what = MsgType.ERROR;
76 | mHandler.sendMessage(msg);
77 | } catch (InterruptedException e) {
78 | e.printStackTrace();
79 | }
80 | }
81 | }).start();
82 | }
83 |
84 | private void runInSameTime(final Element element) throws IOException {
85 | mExecutorService.execute(new Runnable() {
86 | @Override
87 | public void run() {
88 | try {
89 | Document document = Jsoup.connect(element.select("td:nth-child(1) > a").attr("abs:href"))
90 | .ignoreContentType(true)
91 | .userAgent(Url.PC_AGENT)
92 | .get();
93 | Elements elements = document.select("ul.list-group");
94 | String name = elements.select("li").get(2).text().replace("文件名称:Book.ShuYuZhe.com书语者_","");
95 | String status = elements.select("li").get(4).text();
96 |
97 | String time = elements.select("li").get(6).text();
98 |
99 | String info = "";
100 |
101 | String category = elements.select("li").get(5).text();
102 |
103 |
104 |
105 | String author = "";
106 |
107 | String words = elements.select("li").get(3).text();
108 |
109 |
110 | String url = document.select("a:contains(下载此书)").attr("href");
111 | String pic = "";
112 | list.add(new NovelBean(name, time, info, category, status, author, words, pic, url));
113 | } catch (IOException e) {
114 | e.printStackTrace();
115 | }
116 | latch.countDown();
117 | }
118 | });
119 | }
120 |
121 |
122 | @Override
123 | public ArrayList getDownloadurls(final String url) throws InterruptedException {
124 | latch = new CountDownLatch(1);
125 | final ArrayList urls = new ArrayList<>();
126 | mExecutorService.submit(new Runnable() {
127 | @Override
128 | public void run() {
129 | urls.add(new DownloadBean("全文下载", url));
130 | latch.countDown();
131 | }
132 | });
133 | latch.await();
134 | return urls;
135 | }
136 |
137 | }
138 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/service/XiaoShuWuService.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.service;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 |
6 | import com.delsart.bookdownload.MsgType;
7 | import com.delsart.bookdownload.Url;
8 | import com.delsart.bookdownload.bean.DownloadBean;
9 | import com.delsart.bookdownload.bean.NovelBean;
10 |
11 | import org.jsoup.Jsoup;
12 | import org.jsoup.nodes.Document;
13 | import org.jsoup.nodes.Element;
14 | import org.jsoup.select.Elements;
15 |
16 | import java.io.IOException;
17 | import java.util.ArrayList;
18 | import java.util.concurrent.CountDownLatch;
19 | import java.util.regex.Matcher;
20 | import java.util.regex.Pattern;
21 |
22 | public class XiaoShuWuService extends BaseService {
23 | private static String TAG = "test";
24 | private final Handler mHandler;
25 | private int mPage;
26 | private String mBaseUrl;
27 | private CountDownLatch latch;
28 | private ArrayList list = new ArrayList<>();
29 |
30 | public XiaoShuWuService(Handler handler, String keywords) {
31 | super(handler, keywords);
32 | this.mHandler = handler;
33 | mPage = 1;
34 | mBaseUrl = Url.XIAOSHUWU + keywords;
35 | }
36 |
37 | @Override
38 | public void get() {
39 | new Thread(new Runnable() {
40 | @Override
41 | public void run() {
42 | try {
43 | list.clear();
44 | Elements select = Jsoup.connect(mBaseUrl.replace("0", mPage + ""))
45 | .timeout(10000)
46 | .ignoreContentType(true)
47 | .ignoreHttpErrors(true)
48 | .userAgent(Url.MOBBILE_AGENT)
49 | .get()
50 | .select("div#posts-list").select("a");
51 | latch = new CountDownLatch(select.size());
52 | for (int i = 0; i < select.size(); i++) {
53 | runInSameTime(select.get(i));
54 | }
55 | latch.await();
56 | mPage++;
57 | Message msg = mHandler.obtainMessage();
58 | msg.what = MsgType.SUCCESS;
59 | msg.obj = list;
60 | mHandler.sendMessage(msg);
61 | } catch (IOException e) {
62 | e.printStackTrace();
63 | Message msg = mHandler.obtainMessage();
64 | msg.what = MsgType.ERROR;
65 | mHandler.sendMessage(msg);
66 | } catch (InterruptedException e) {
67 | e.printStackTrace();
68 | }
69 | }
70 | }).start();
71 | }
72 |
73 | private void runInSameTime(final Element element) throws IOException {
74 | mExecutorService.submit(new Runnable() {
75 | @Override
76 | public void run() {
77 | String url = element.attr("abs:href");
78 | Document document = null;
79 | try {
80 | document = Jsoup.connect(url)
81 | .ignoreContentType(true)
82 | .ignoreHttpErrors(true)
83 | .userAgent(Url.MOBBILE_AGENT)
84 | .get();
85 |
86 | String t = document.select("#post-title").text();
87 | String name = document.select("#post-title").text();
88 | Matcher m = Pattern.compile("《.+》").matcher(t);
89 | if (m.find()) {
90 | name = m.group(0);
91 | }
92 |
93 | String time = document.select("#container > div > div.post_content > div > p:nth-child(5)").text().replace("作者信息", "\n作者信息");
94 | String info = "";
95 | Elements elements = document.select("#container > div > div.post_content > p");
96 | for (int i = 0; i < elements.size(); i++) {
97 | if (!elements.get(i).text().equals(""))
98 | info = info + elements.get(i).text() + "\n\n";
99 |
100 |
101 | }
102 | String category = document.select("#container > div > div.post_detail > ul:nth-child(1) > li:nth-child(1)").text() + "\n" + document.select("#container > div > div.post_detail > ul:nth-child(1) > li:nth-child(2)").text();
103 |
104 | String status = "";
105 | m = Pattern.compile("([^a-z]+).+").matcher(t);
106 | if (m.find()) {
107 | status = "文件格式:" + m.group(0).replaceAll("([^a-z]+)", "");
108 | }
109 |
110 | String author = "";
111 | m = Pattern.compile("》.+([^a-z]+)").matcher(t);
112 | if (m.find()) {
113 | author = "书籍作者:" + m.group(0).replaceAll("([^a-z]+)", "").replace("》", "");
114 | }
115 |
116 | String words = "";
117 | String pic = document.select("#container > div > div.post_content > p:nth-child(1) > img").attr("abs:src");
118 | String durl = document.select("#container > div > div.post_content > div > p.downlink > strong > a").attr("abs:href");
119 | NovelBean no = new NovelBean(name, time, info, category, status, author, words, pic, durl);
120 | list.add(no);
121 | } catch (IOException e) {
122 | e.printStackTrace();
123 | }
124 | latch.countDown();
125 | }
126 | });
127 | }
128 |
129 |
130 | @Override
131 | public ArrayList getDownloadurls(final String url) throws InterruptedException {
132 | latch = new CountDownLatch(1);
133 | final ArrayList urls = new ArrayList<>();
134 | mExecutorService.submit(new Runnable() {
135 | @Override
136 | public void run() {
137 | Document document = null;
138 | try {
139 | document = Jsoup.connect(url)
140 | .timeout(10000)
141 | .ignoreContentType(true)
142 | .ignoreHttpErrors(true)
143 | .userAgent(Url.MOBBILE_AGENT)
144 | .get();
145 |
146 | String u1 = "";
147 | String u1n = document.select("body > div:nth-child(4) > p:nth-child(7)").text();
148 | Elements elements = document.select("body > div.list").select("a");
149 | urls.add(new DownloadBean(u1n, u1));
150 | for (Element element : elements) {
151 | urls.add(new DownloadBean(element.text(), element.attr("abs:href")));
152 | }
153 | } catch (IOException e) {
154 | e.printStackTrace();
155 | }
156 | latch.countDown();
157 | }
158 | });
159 | latch.await();
160 | return urls;
161 | }
162 |
163 | }
164 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/service/ZhiXuanService.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.service;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 |
6 | import com.delsart.bookdownload.MsgType;
7 | import com.delsart.bookdownload.Url;
8 | import com.delsart.bookdownload.bean.DownloadBean;
9 | import com.delsart.bookdownload.bean.NovelBean;
10 |
11 | import org.jsoup.Jsoup;
12 | import org.jsoup.nodes.Document;
13 | import org.jsoup.nodes.Element;
14 | import org.jsoup.select.Elements;
15 |
16 | import java.io.IOException;
17 | import java.util.ArrayList;
18 | import java.util.concurrent.CountDownLatch;
19 | import java.util.regex.Matcher;
20 | import java.util.regex.Pattern;
21 |
22 | public class ZhiXuanService extends BaseService {
23 | private static String TAG = "test";
24 | private final Handler mHandler;
25 | private int mPage;
26 | private String mBaseUrl;
27 | private CountDownLatch latch;
28 | private ArrayList list = new ArrayList<>();
29 |
30 | public ZhiXuanService(Handler handler, String keywords) {
31 | super(handler, keywords);
32 | this.mHandler = handler;
33 | mPage = 1;
34 | mBaseUrl = Url.ZHIXUAN + keywords + "&page=";
35 | }
36 | String lasts="";
37 | @Override
38 | public void get() {
39 | new Thread(new Runnable() {
40 | @Override
41 | public void run() {
42 | try {
43 | list.clear();
44 | Elements select = Jsoup.connect(mBaseUrl + mPage)
45 | .timeout(10000)
46 | .ignoreContentType(true)
47 | .ignoreHttpErrors(true)
48 | .userAgent(Url.MOBBILE_AGENT)
49 | .get()
50 | .select("div.info");
51 | latch = new CountDownLatch(select.size());
52 | for (int i = 0; i < select.size(); i++) {
53 | runInSameTime(select.get(i));
54 | }
55 | latch.await();
56 | if (select.toString().equals(lasts))
57 | list.clear();
58 | lasts=select.toString();
59 | mPage++;
60 | Message msg = mHandler.obtainMessage();
61 | msg.what = MsgType.SUCCESS;
62 | msg.obj = list;
63 | mHandler.sendMessage(msg);
64 | } catch (IOException e) {
65 | e.printStackTrace();
66 | Message msg = mHandler.obtainMessage();
67 | msg.what = MsgType.ERROR;
68 | mHandler.sendMessage(msg);
69 | } catch (InterruptedException e) {
70 | e.printStackTrace();
71 | }
72 | }
73 | }).start();
74 | }
75 |
76 | private void runInSameTime(final Element element) throws IOException {
77 | mExecutorService.submit(new Runnable() {
78 | @Override
79 | public void run() {
80 | String url = element.select("a").attr("abs:href");
81 | Document document = null;
82 | try {
83 | document = Jsoup.connect(url)
84 | .ignoreContentType(true)
85 | .ignoreHttpErrors(true)
86 | .userAgent(Url.MOBBILE_AGENT)
87 | .get();
88 |
89 | String t = document.select("#m > div.postcont > p:nth-child(4)").text();
90 | String name = document.select("#m > div.posttitle").text().replace("(校对版全本)", "").replace("《", "").replace("》", "");
91 | String time = "收录日期:" + element.select("span").text();
92 | String info = "";
93 | Matcher m = Pattern.compile("【内容简介】.+").matcher(t);
94 | if (m.find())
95 | info = m.group(0).replace(" ", "\n").replace(" ", "\n").replace("【内容简介】: \n", "");
96 | String category = document.select("#m > div.postcont > div.pagefujian > div.filecont > p.fileinfo > span:nth-child(1)").text();
97 | String status = "";
98 | String author = "";
99 | if (name.contains("作者")) {
100 | author = name.substring(name.indexOf("作者"), name.length());
101 | name = name.replace(author, "");
102 | }
103 | String words = "";
104 | if (t.contains("【内容简介"))
105 | words = t.substring(0, t.indexOf("【内容简介")).replace("【", "").replace("】", "");
106 | String pic = document.select("img[title=点击查看原图]").attr("abs:src");
107 | String durl=document.select("#m > div.postcont > div.pagefujian > div.filecont > p.filetit > a").attr("abs:href");
108 | NovelBean no = new NovelBean(name, time, info, category, status, author, words, pic, durl);
109 | list.add(no);
110 | } catch (IOException e) {
111 | e.printStackTrace();
112 | }
113 | latch.countDown();
114 | }
115 | });
116 | }
117 |
118 |
119 | @Override
120 | public ArrayList getDownloadurls(final String url) throws InterruptedException {
121 | latch = new CountDownLatch(1);
122 | final ArrayList urls = new ArrayList<>();
123 | mExecutorService.execute(new Runnable() {
124 | @Override
125 | public void run() {
126 | Document document = null;
127 | try {
128 | document = Jsoup.connect(url)
129 | .timeout(10000)
130 | .ignoreContentType(true)
131 | .ignoreHttpErrors(true)
132 | .userAgent(Url.MOBBILE_AGENT)
133 | .get();
134 | Elements elements=document.select("body > div.wrap > div.content > div:nth-child(4) > div.panel-body a");
135 | for (Element element : elements) {
136 | urls.add(new DownloadBean(element.text(), element.attr("abs:href")));
137 | }
138 | } catch (IOException e) {
139 | e.printStackTrace();
140 | }
141 | latch.countDown();
142 | }
143 | });
144 | latch.await();
145 | return urls;
146 | }
147 |
148 | }
149 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/service/ZhouDuService.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.service;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 |
6 | import com.delsart.bookdownload.MsgType;
7 | import com.delsart.bookdownload.Url;
8 | import com.delsart.bookdownload.bean.DownloadBean;
9 | import com.delsart.bookdownload.bean.NovelBean;
10 |
11 | import org.jsoup.Jsoup;
12 | import org.jsoup.nodes.Document;
13 | import org.jsoup.nodes.Element;
14 | import org.jsoup.select.Elements;
15 |
16 | import java.io.IOException;
17 | import java.util.ArrayList;
18 | import java.util.concurrent.CountDownLatch;
19 |
20 | public class ZhouDuService extends BaseService {
21 | private static String TAG = "test";
22 | private final Handler mHandler;
23 | private int mPage;
24 | private String mBaseUrl;
25 | private CountDownLatch latch;
26 | private ArrayList list = new ArrayList<>();
27 |
28 | public ZhouDuService(Handler handler, String keywords) {
29 | super(handler, keywords);
30 | this.mHandler = handler;
31 | mPage = 1;
32 | mBaseUrl = Url.ZHOUDU + keywords + "&page=";
33 | }
34 |
35 | @Override
36 | public void get() {
37 | new Thread(new Runnable() {
38 | @Override
39 | public void run() {
40 | try {
41 | list.clear();
42 | Elements select = Jsoup.connect(mBaseUrl + mPage)
43 | .timeout(10000)
44 | .ignoreContentType(true)
45 | .ignoreHttpErrors(true)
46 | .get()
47 | .select("body > div > div > ul > a");
48 | latch = new CountDownLatch(select.size());
49 | for (int i = 0; i < select.size(); i++) {
50 | runInSameTime(select.get(i));
51 | }
52 | latch.await();
53 | mPage++;
54 | Message msg = mHandler.obtainMessage();
55 | msg.what = MsgType.SUCCESS;
56 | msg.obj = list;
57 | mHandler.sendMessage(msg);
58 | } catch (IOException e) {
59 | e.printStackTrace();
60 | Message msg = mHandler.obtainMessage();
61 | msg.what = MsgType.ERROR;
62 | mHandler.sendMessage(msg);
63 | } catch (InterruptedException e) {
64 | e.printStackTrace();
65 | }
66 | }
67 | }).start();
68 | }
69 |
70 | private void runInSameTime(final Element element) throws IOException {
71 | mExecutorService.submit(new Runnable() {
72 | @Override
73 | public void run() {
74 | try {
75 | Document document = Jsoup.connect(element.attr("abs:href"))
76 | .ignoreContentType(true)
77 | .ignoreHttpErrors(true)
78 | .get();
79 |
80 | String t = document.select("body > div > div > div.hanghang-za > div.hanghang-shu-content > div.hanghang-shu-content-font").text();
81 | if (t.length() < 5) {
82 | latch.countDown();
83 | return;
84 | }
85 | String name = document.select("body > div > div > div.hanghang-za > div:nth-child(1)").text();
86 | String status = "";
87 | String time = "";
88 | String info = t.substring(t.indexOf("简介"), t.length());
89 | String category = document.select("body > div > div > div.hanghang-za > div.hanghang-shu-content > div.hanghang-shu-content-font > p:nth-child(2)").text();
90 | String author = document.select("body > div > div > div.hanghang-za > div.hanghang-shu-content > div.hanghang-shu-content-font > p:nth-child(1)").text();
91 | String words = "";
92 | String url = document.select("body > div > div > div.hanghang-za > div.hanghang-box > div.hanghang-shu-content-btn > a").attr("href");
93 | String pic = document.select("body > div > div > div.hanghang-za > div.hanghang-shu-content > div.hanghang-shu-content-img > img").attr("abs:src");
94 | NovelBean no = new NovelBean(name, time, info, category, status, author, words, pic, url);
95 | list.add(no);
96 | } catch (IOException e) {
97 | e.printStackTrace();
98 | }
99 |
100 |
101 | latch.countDown();
102 |
103 | }
104 | });
105 | }
106 |
107 |
108 | @Override
109 | public ArrayList getDownloadurls(final String url) throws InterruptedException {
110 | latch = new CountDownLatch(1);
111 | final ArrayList urls = new ArrayList<>();
112 | mExecutorService.submit(new Runnable() {
113 | @Override
114 | public void run() {
115 | urls.add(new DownloadBean("百度云", url));
116 | latch.countDown();
117 | }
118 | });
119 | latch.await();
120 | return urls;
121 | }
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/activity/AboutActivity.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.activity;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.content.pm.PackageManager;
7 | import android.net.Uri;
8 | import android.os.Bundle;
9 | import android.os.PersistableBundle;
10 | import android.preference.PreferenceManager;
11 | import android.support.annotation.NonNull;
12 | import android.support.annotation.Nullable;
13 | import android.support.v4.content.ContextCompat;
14 | import android.util.AttributeSet;
15 | import android.view.View;
16 | import android.widget.Toast;
17 |
18 | import com.danielstone.materialaboutlibrary.ConvenienceBuilder;
19 | import com.danielstone.materialaboutlibrary.MaterialAboutActivity;
20 | import com.danielstone.materialaboutlibrary.items.MaterialAboutActionItem;
21 | import com.danielstone.materialaboutlibrary.items.MaterialAboutItemOnClickAction;
22 | import com.danielstone.materialaboutlibrary.items.MaterialAboutTitleItem;
23 | import com.danielstone.materialaboutlibrary.model.MaterialAboutCard;
24 | import com.danielstone.materialaboutlibrary.model.MaterialAboutList;
25 | import com.danielstone.materialaboutlibrary.util.ViewTypeManager;
26 | import com.delsart.bookdownload.MyApplication;
27 | import com.delsart.bookdownload.R;
28 | import com.delsart.bookdownload.Url;
29 | import com.delsart.bookdownload.custom.MyViewTypeManager;
30 | import com.mikepenz.community_material_typeface_library.CommunityMaterial;
31 | import com.mikepenz.iconics.IconicsDrawable;
32 |
33 | import java.net.URL;
34 |
35 | import moe.feng.alipay.zerosdk.AlipayZeroSdk;
36 |
37 | /**
38 | * Created by Delsart on 2017/7/24.
39 | */
40 |
41 | public class AboutActivity extends MaterialAboutActivity {
42 | public static final String THEME_EXTRA = "";
43 | public static final int THEME_LIGHT_LIGHTBAR = 0;
44 | public static final int THEME_LIGHT_DARKBAR = 1;
45 | public static final int THEME_DARK_LIGHTBAR = 2;
46 | public static final int THEME_DARK_DARKBAR = 3;
47 | public static final int THEME_CUSTOM_CARDVIEW = 4;
48 |
49 | protected int colorIcon = R.color.DayColor;
50 |
51 | @Override
52 | protected void onCreate(@Nullable Bundle savedInstanceState) {
53 | if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", false)) {
54 | setTheme(R.style.DarkTheme_aboutTheme);
55 | colorIcon = R.color.DarkColor;
56 | }
57 | else
58 | setTheme(R.style.aboutTheme);
59 | super.onCreate(savedInstanceState);
60 | }
61 |
62 |
63 | @NonNull
64 | @Override
65 | protected MaterialAboutList getMaterialAboutList(@NonNull final Context c) {
66 | final Activity activity = this;
67 | MaterialAboutCard.Builder appCardBuilder = new MaterialAboutCard.Builder();
68 | // Add items to card
69 | appCardBuilder.addItem(new MaterialAboutTitleItem.Builder()
70 | .text(R.string.app_name)
71 | .desc("© 2017 Delsart")
72 | .icon(R.mipmap.ic_launcher)
73 | .build());
74 |
75 | try {
76 |
77 | appCardBuilder.addItem(ConvenienceBuilder.createVersionActionItem(c,
78 | new IconicsDrawable(c)
79 | .icon(CommunityMaterial.Icon.cmd_information_outline)
80 | .color(ContextCompat.getColor(c, colorIcon))
81 | .sizeDp(18),
82 | "版本",
83 | false));
84 |
85 | } catch (PackageManager.NameNotFoundException e) {
86 | e.printStackTrace();
87 | }
88 |
89 | appCardBuilder.addItem(new MaterialAboutActionItem.Builder()
90 | .text("更新日志")
91 | .icon(new IconicsDrawable(c)
92 | .icon(CommunityMaterial.Icon.cmd_history)
93 | .color(ContextCompat.getColor(c, colorIcon))
94 | .sizeDp(18))
95 | .setOnClickAction(ConvenienceBuilder.createWebViewDialogOnClickAction(c, "", "https://github.com/Delsart/Bookster/blob/master/%E6%9B%B4%E6%96%B0%E6%97%A5%E5%BF%97.txt", true, false))
96 | .build());
97 |
98 |
99 | MaterialAboutCard.Builder authorCardBuilder = new MaterialAboutCard.Builder();
100 | authorCardBuilder.title("作者相关");
101 | // authorCardBuilder.titleColor(ContextCompat.getColor(c, R.color.colorAccent));
102 |
103 | authorCardBuilder.addItem(new MaterialAboutActionItem.Builder()
104 | .text("Delsart")
105 | .subText("作者 , 中国")
106 | .icon(new IconicsDrawable(c)
107 | .icon(CommunityMaterial.Icon.cmd_account)
108 | .color(ContextCompat.getColor(c, colorIcon))
109 | .sizeDp(18))
110 | .setOnClickAction(
111 | ConvenienceBuilder.createWebsiteOnClickAction(c, Uri.parse("https://www.coolapk.com/u/473036")))
112 | .build());
113 |
114 |
115 | authorCardBuilder.addItem(new MaterialAboutActionItem.Builder()
116 | .text("Archie")
117 | .subText("图标设计者 , 中国")
118 | .icon(new IconicsDrawable(c)
119 | .icon(CommunityMaterial.Icon.cmd_account)
120 | .color(ContextCompat.getColor(c, colorIcon))
121 | .sizeDp(18))
122 | .setOnClickAction(ConvenienceBuilder.createWebsiteOnClickAction(c, Uri.parse("https://www.coolapk.com/u/801526")))
123 | .build());
124 |
125 | authorCardBuilder.addItem(new MaterialAboutActionItem.Builder()
126 | .text("Fairyex")
127 | .subText("空视图设计者 , 中国")
128 | .icon(new IconicsDrawable(c)
129 | .icon(CommunityMaterial.Icon.cmd_account)
130 | .color(ContextCompat.getColor(c, colorIcon))
131 | .sizeDp(18))
132 | .setOnClickAction(ConvenienceBuilder.createWebsiteOnClickAction(c, Uri.parse("http://www.coolapk.com/u/466253")))
133 | .build());
134 |
135 | authorCardBuilder.addItem(new MaterialAboutActionItem.Builder()
136 | .text("Used-open-sources")
137 | .icon(new IconicsDrawable(c)
138 | .icon(CommunityMaterial.Icon.cmd_android_debug_bridge)
139 | .color(ContextCompat.getColor(c, colorIcon))
140 | .sizeDp(18))
141 | .setOnClickAction(new MaterialAboutItemOnClickAction() {
142 | @Override
143 | public void onClick() {
144 | Intent intent = new Intent(c, UsedOpenSource.class);
145 | intent.putExtra(AboutActivity.THEME_EXTRA, getIntent().getIntExtra(THEME_EXTRA, THEME_LIGHT_DARKBAR));
146 | c.startActivity(intent);
147 | }
148 | })
149 | .build());
150 |
151 | authorCardBuilder.addItem(new MaterialAboutActionItem.Builder()
152 | .text("Fork on GitHub")
153 | .icon(new IconicsDrawable(c)
154 | .icon(CommunityMaterial.Icon.cmd_github_circle)
155 | .color(ContextCompat.getColor(c, colorIcon))
156 | .sizeDp(18))
157 | .setOnClickAction(ConvenienceBuilder.createWebsiteOnClickAction(c, Uri.parse("https://github.com/Delsart/Bookster")))
158 | .build());
159 |
160 |
161 | MaterialAboutCard.Builder convenienceCardBuilder = new MaterialAboutCard.Builder();
162 | convenienceCardBuilder.title("更多");
163 | convenienceCardBuilder.addItem(ConvenienceBuilder.createWebsiteActionItem(c,
164 | new IconicsDrawable(c)
165 | .icon(CommunityMaterial.Icon.cmd_earth)
166 | .color(ContextCompat.getColor(c, colorIcon))
167 | .sizeDp(18),
168 | "访问我们的主页",
169 | true,
170 | Uri.parse("https://hereacg.org")));
171 |
172 | convenienceCardBuilder.addItem(ConvenienceBuilder.createRateActionItem(c,
173 | new IconicsDrawable(c)
174 | .icon(CommunityMaterial.Icon.cmd_star)
175 | .color(ContextCompat.getColor(c, colorIcon))
176 | .sizeDp(18),
177 | "为这个应用评分",
178 | null
179 | ));
180 |
181 | convenienceCardBuilder.addItem(ConvenienceBuilder.createEmailItem(c,
182 | new IconicsDrawable(c)
183 | .icon(CommunityMaterial.Icon.cmd_email)
184 | .color(ContextCompat.getColor(c, colorIcon))
185 | .sizeDp(18),
186 | "发送邮件",
187 | true,
188 | "2289582155@qq.com",
189 | "Question concerning MaterialAboutLibrary"));
190 |
191 | convenienceCardBuilder.addItem(new MaterialAboutActionItem.Builder()
192 | .text("捐赠,请作者女装(误)喝杯果汁(支付宝)")
193 | .icon(new IconicsDrawable(c)
194 | .icon(CommunityMaterial.Icon.cmd_coffee)
195 | .color(ContextCompat.getColor(c, colorIcon))
196 | .sizeDp(18))
197 | .setOnClickAction(new MaterialAboutItemOnClickAction() {
198 | @Override
199 | public void onClick() {
200 | if (AlipayZeroSdk.hasInstalledAlipayClient(MyApplication.getContext()))
201 | AlipayZeroSdk.startAlipayClient(activity, "a6x02835mi3wh18ivz0mbdb");
202 | else
203 | Toast.makeText(getApplicationContext(), "没有安装支付宝", Toast.LENGTH_SHORT).show();
204 | }
205 | })
206 | .build());
207 |
208 | convenienceCardBuilder.addItem(new MaterialAboutActionItem.Builder()
209 | .text("捐赠,请作者女装(误)喝杯果汁(微信)")
210 | .icon(new IconicsDrawable(c)
211 | .icon(CommunityMaterial.Icon.cmd_coffee)
212 | .color(ContextCompat.getColor(c, colorIcon))
213 | .sizeDp(18))
214 | .setOnClickAction(new MaterialAboutItemOnClickAction() {
215 | @Override
216 | public void onClick() {
217 | Uri uri = Uri.parse("http://a3.qpic.cn/psb?/V10dNxbX00vsuB/eKAX6FA4sv5Y3Tnb.lrqpj6OjMWE6QuHyv2Z*h2MBtk!/b/dGoBAAAAAAAA&bo=.AJSA*gCUgMDCSw!&rf=viewer_4");
218 | startActivity(new Intent(Intent.ACTION_VIEW, uri));
219 | }
220 | })
221 | .build());
222 |
223 | MaterialAboutCard.Builder otherCardBuilder = new MaterialAboutCard.Builder();
224 | otherCardBuilder.title("来源");
225 | otherCardBuilder.addItem(ConvenienceBuilder.createWebsiteActionItem(c,
226 | new IconicsDrawable(c)
227 | .icon(CommunityMaterial.Icon.cmd_earth)
228 | .color(ContextCompat.getColor(c, colorIcon))
229 | .sizeDp(18),
230 | "爱下小说",
231 | true,
232 | Uri.parse("http://m.ixdzs.com")));
233 |
234 | otherCardBuilder.addItem(ConvenienceBuilder.createWebsiteActionItem(c,
235 | new IconicsDrawable(c)
236 | .icon(CommunityMaterial.Icon.cmd_earth)
237 | .color(ContextCompat.getColor(c, colorIcon))
238 | .sizeDp(18),
239 | "知轩藏书",
240 | true,
241 | Uri.parse("http://www.zxcs8.com")));
242 |
243 | otherCardBuilder.addItem(ConvenienceBuilder.createWebsiteActionItem(c,
244 | new IconicsDrawable(c)
245 | .icon(CommunityMaterial.Icon.cmd_earth)
246 | .color(ContextCompat.getColor(c, colorIcon))
247 | .sizeDp(18),
248 | "周读",
249 | true,
250 | Uri.parse("http://www.ireadweek.com")));
251 |
252 | otherCardBuilder.addItem(ConvenienceBuilder.createWebsiteActionItem(c,
253 | new IconicsDrawable(c)
254 | .icon(CommunityMaterial.Icon.cmd_earth)
255 | .color(ContextCompat.getColor(c, colorIcon))
256 | .sizeDp(18),
257 | "书语者",
258 | true,
259 | Uri.parse("https://book.shuyuzhe.com")));
260 |
261 | otherCardBuilder.addItem(ConvenienceBuilder.createWebsiteActionItem(c,
262 | new IconicsDrawable(c)
263 | .icon(CommunityMaterial.Icon.cmd_earth)
264 | .color(ContextCompat.getColor(c, colorIcon))
265 | .sizeDp(18),
266 | "动漫之家",
267 | true,
268 | Uri.parse("https://www.dmzj.com/")));
269 |
270 | otherCardBuilder.addItem(ConvenienceBuilder.createWebsiteActionItem(c,
271 | new IconicsDrawable(c)
272 | .icon(CommunityMaterial.Icon.cmd_earth)
273 | .color(ContextCompat.getColor(c, colorIcon))
274 | .sizeDp(18),
275 | "360℃",
276 | true,
277 | Uri.parse("http://www.360dxs.com")));
278 | otherCardBuilder.addItem(ConvenienceBuilder.createWebsiteActionItem(c,
279 | new IconicsDrawable(c)
280 | .icon(CommunityMaterial.Icon.cmd_earth)
281 | .color(ContextCompat.getColor(c, colorIcon))
282 | .sizeDp(18),
283 | "我的小书屋",
284 | true,
285 | Uri.parse("http://mebook.cc")));
286 | otherCardBuilder.addItem(ConvenienceBuilder.createWebsiteActionItem(c,
287 | new IconicsDrawable(c)
288 | .icon(CommunityMaterial.Icon.cmd_earth)
289 | .color(ContextCompat.getColor(c, colorIcon))
290 | .sizeDp(18),
291 | "奇书网",
292 | true,
293 | Uri.parse("http://www.qisuu.com")));
294 | otherCardBuilder.addItem(ConvenienceBuilder.createWebsiteActionItem(c,
295 | new IconicsDrawable(c)
296 | .icon(CommunityMaterial.Icon.cmd_earth)
297 | .color(ContextCompat.getColor(c, colorIcon))
298 | .sizeDp(18),
299 | "Blah",
300 | true,
301 | Uri.parse("http://blah.me")));
302 | return new MaterialAboutList(appCardBuilder.build(), authorCardBuilder.build(), convenienceCardBuilder.build(), otherCardBuilder.build());
303 | }
304 |
305 |
306 | @Override
307 | protected CharSequence getActivityTitle() {
308 | return "关于";
309 | }
310 |
311 | @NonNull
312 | @Override
313 | protected ViewTypeManager getViewTypeManager() {
314 | return new MyViewTypeManager();
315 | }
316 | }
317 |
318 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.activity;
2 |
3 |
4 | import android.content.DialogInterface;
5 | import android.content.Intent;
6 | import android.content.SharedPreferences;
7 | import android.content.pm.PackageInfo;
8 | import android.content.pm.PackageManager;
9 | import android.net.Uri;
10 | import android.os.Bundle;
11 | import android.preference.PreferenceManager;
12 | import android.support.design.widget.FloatingActionButton;
13 | import android.support.design.widget.TabLayout;
14 | import android.support.v4.view.MenuItemCompat;
15 | import android.support.v4.view.ViewPager;
16 | import android.support.v7.app.AlertDialog;
17 | import android.support.v7.app.AppCompatActivity;
18 | import android.support.v7.widget.SearchView;
19 | import android.support.v7.widget.Toolbar;
20 | import android.util.Log;
21 | import android.view.KeyEvent;
22 | import android.view.Menu;
23 | import android.view.MenuItem;
24 | import android.view.View;
25 | import android.widget.Toast;
26 |
27 | import com.delsart.bookdownload.MyApplication;
28 | import com.delsart.bookdownload.R;
29 | import com.delsart.bookdownload.adapter.PagerAdapter;
30 | import com.delsart.bookdownload.ui.fragment.AiXiaFragment;
31 | import com.delsart.bookdownload.ui.fragment.BaseFragment;
32 | import com.delsart.bookdownload.ui.fragment.BlahFragment;
33 | import com.delsart.bookdownload.ui.fragment.DongManZhiJiaFragment;
34 | import com.delsart.bookdownload.ui.fragment.M360DFragment;
35 | import com.delsart.bookdownload.ui.fragment.QiShuFragment;
36 | import com.delsart.bookdownload.ui.fragment.ShuYuZheFragment;
37 | import com.delsart.bookdownload.ui.fragment.XiaoShuWuFragment;
38 | import com.delsart.bookdownload.ui.fragment.ZhiXuanFragment;
39 | import com.delsart.bookdownload.ui.fragment.ZhouDuFragment;
40 | import com.delsart.bookdownload.utils.StatusBarUtils;
41 |
42 | import org.json.JSONObject;
43 |
44 | import java.io.BufferedReader;
45 | import java.io.InputStream;
46 | import java.io.InputStreamReader;
47 | import java.net.HttpURLConnection;
48 | import java.net.URL;
49 | import java.util.ArrayList;
50 | import java.util.List;
51 |
52 | import moe.feng.alipay.zerosdk.AlipayZeroSdk;
53 |
54 | public class MainActivity extends AppCompatActivity {
55 | private SharedPreferences firstime;
56 | private SharedPreferences.Editor editor;
57 | private PagerAdapter mPagerAdapter;
58 | private SearchView searchView;
59 | private SharedPreferences autoupdate;
60 | String lastKeyWords = "";
61 |
62 |
63 | @Override
64 | protected void onCreate(Bundle savedInstanceState) {
65 | if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", false))
66 | setTheme(R.style.DarkTheme);
67 | else
68 | setTheme(R.style.DayTheme);
69 |
70 | super.onCreate(savedInstanceState);
71 | setContentView(R.layout.activity_main);
72 | autoupdate = getSharedPreferences("com.delsart.bookdownload_preferences", MODE_PRIVATE);
73 | StatusBarUtils.MIUISetStatusBarLightMode(this, true);
74 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
75 | setSupportActionBar(toolbar);
76 | initView();
77 | showInfoDialog();
78 |
79 |
80 | if (autoupdate.getBoolean("autoUpdate", true)) {
81 |
82 | // try {
83 | // getUpdate();
84 | // } catch (Exception e) {
85 | // e.printStackTrace();
86 | // }
87 | }
88 | }
89 |
90 | private void showInfoDialog() {
91 | firstime = getSharedPreferences("data", MODE_PRIVATE);
92 | editor = firstime.edit();
93 | if (firstime.getInt("first", 0) == 0) {
94 | AlertDialog.Builder builder = new AlertDialog.Builder(this);
95 | builder.setTitle("使用须知");
96 | builder.setCancelable(false);
97 | builder.setMessage(R.string.firstlaunchshowtext);
98 | builder.setNegativeButton("拒绝", new DialogInterface.OnClickListener() {
99 | @Override
100 | public void onClick(DialogInterface dialog, int which) {
101 | finish();
102 | }
103 | });
104 | builder.setPositiveButton("知道了", new DialogInterface.OnClickListener() {
105 | @Override
106 | public void onClick(DialogInterface dialog, int which) {
107 | editor.putInt("first", 1);
108 | editor.apply();
109 | }
110 | });
111 | builder.show();
112 | }
113 | if (firstime.getInt("showrate", 1) > 3 && firstime.getBoolean("ifshowrate", true)) {
114 | editor.putInt("showrate", 1);
115 | editor.apply();
116 | AlertDialog.Builder builder = new AlertDialog.Builder(this);
117 | builder.setTitle("嗨,还好吗?");
118 | builder.setMessage(R.string.showrate);
119 | builder.setNegativeButton("评分", new DialogInterface.OnClickListener() {
120 | @Override
121 | public void onClick(DialogInterface dialog, int which) {
122 | Uri uri = Uri.parse("market://details?id=" + getPackageName());
123 | Intent intent = new Intent(Intent.ACTION_VIEW, uri);
124 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
125 | startActivity(intent);
126 | }
127 | });
128 | builder.setPositiveButton("捐赠", new DialogInterface.OnClickListener() {
129 | @Override
130 | public void onClick(DialogInterface dialog, int which) {
131 | if (AlipayZeroSdk.hasInstalledAlipayClient(MyApplication.getContext()))
132 | AlipayZeroSdk.startAlipayClient(MainActivity.this, "a6x02835mi3wh18ivz0mbdb");
133 | else
134 | Toast.makeText(getApplicationContext(), "没有安装支付宝", Toast.LENGTH_SHORT).show();
135 |
136 | }
137 | });
138 | builder.setNeutralButton("拒绝,并不再提醒", new DialogInterface.OnClickListener() {
139 | @Override
140 | public void onClick(DialogInterface dialog, int which) {
141 | editor.putBoolean("ifshowrate", false);
142 | editor.apply();
143 | }
144 | });
145 | builder.show();
146 | } else {
147 | editor.putInt("showrate", firstime.getInt("showrate", 1) + 1);
148 | editor.apply();
149 | }
150 | }
151 |
152 | private void getUpdate() throws Exception {
153 | new Thread(new Runnable() {
154 | @Override
155 | public void run() {
156 | try {
157 | URL url = new URL("https://hereacg.org/bookster/update.json");
158 | HttpURLConnection connection = (HttpURLConnection) url.openConnection();
159 | connection.setRequestMethod("GET");
160 | connection.setConnectTimeout(3000);
161 | InputStream in = connection.getInputStream();
162 | // 下面对获取到的输入流进行读取
163 | BufferedReader reader = new BufferedReader(new InputStreamReader(in));
164 | StringBuilder response = new StringBuilder();
165 | String line;
166 | while ((line = reader.readLine()) != null) {
167 | response.append(line);
168 | }
169 | parseJSONWithJSONObject(response.toString());
170 | } catch (Exception e) {
171 | e.printStackTrace();
172 | }
173 | }
174 | }).start();
175 | }
176 |
177 | private void parseJSONWithJSONObject(String jsonDatas) {
178 | final String jsonData = jsonDatas;
179 | new Thread(new Runnable() {
180 | @Override
181 | public void run() {
182 | try {
183 | JSONObject jsonObject = new JSONObject(jsonData);
184 | String version = jsonObject.getString("version");
185 | String info = jsonObject.getString("info");
186 | String time = jsonObject.getString("time");
187 | String size = jsonObject.getString("size");
188 | final String url = jsonObject.getString("url");
189 | PackageManager manager = getPackageManager();
190 | PackageInfo infos = manager.getPackageInfo(getPackageName(), 0);
191 | Log.d("sss", "run: " + version + gettrueversion(version) + "ssssss" + gettrueversion(infos.versionName));
192 | if (gettrueversion(version) > gettrueversion(infos.versionName)) {
193 | showupdate(version, time, size, info, url);
194 | }
195 | } catch (Exception e) {
196 | e.printStackTrace();
197 | }
198 | }
199 | }).start();
200 | }
201 |
202 | public float gettrueversion(String s) {
203 | String s2 = "";
204 | for (char a : s.toCharArray()) {
205 |
206 | if ("0123456789.".indexOf(a) >= 0) {
207 | s2 = s2 + a;
208 |
209 | }
210 | }
211 |
212 | return Float.parseFloat(s2);
213 | }
214 |
215 | public void showupdate(final String version, final String time, final String size, final String info, final String url) {
216 | runOnUiThread(new Runnable() {
217 | @Override
218 | public void run() {
219 | AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
220 | builder.setTitle("有新版本");
221 | builder.setMessage("版本号:" + version + "\n更新时间:" + time + "\nApk大小:" + size + "MB\n更新日志:" + info);
222 | builder.setNegativeButton("取消", null);
223 | builder.setPositiveButton("下载", new DialogInterface.OnClickListener() {
224 | @Override
225 | public void onClick(DialogInterface dialog, int which) {
226 | Uri uri = Uri.parse(url);
227 | startActivity(new Intent(Intent.ACTION_VIEW, uri));
228 | }
229 | });
230 | builder.setNeutralButton("关闭自动检查", new DialogInterface.OnClickListener() {
231 | @Override
232 | public void onClick(DialogInterface dialog, int which) {
233 | SharedPreferences.Editor editor = autoupdate.edit();
234 | editor.putBoolean("autoUpdate", false);
235 | editor.apply();
236 | }
237 | });
238 | builder.show();
239 | }
240 | });
241 | }
242 |
243 | List fragments = new ArrayList<>();
244 | List titles = new ArrayList<>();
245 |
246 | private void initView() {
247 | getWindow().setBackgroundDrawable(null);
248 | addpage(new AiXiaFragment(), "爱下");
249 | addpage(new ZhiXuanFragment(), "知轩藏书");
250 | addpage(new ZhouDuFragment(), "周读");
251 | addpage(new ShuYuZheFragment(), "书语者");
252 | addpage(new DongManZhiJiaFragment(), "动漫之家");
253 | addpage(new M360DFragment(), "360℃");
254 | addpage(new XiaoShuWuFragment(), "我的小书屋");
255 | addpage(new QiShuFragment(), "奇书");
256 | addpage(new BlahFragment(), "blah");
257 |
258 | ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
259 | final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
260 | tabLayout.setupWithViewPager(viewPager);
261 | mPagerAdapter = new PagerAdapter(getSupportFragmentManager(), fragments, titles);
262 | viewPager.setAdapter(mPagerAdapter);
263 | viewPager.setOffscreenPageLimit(fragments.size());
264 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
265 | fab.setOnClickListener(new View.OnClickListener() {
266 | @Override
267 | public void onClick(View view) {
268 | searchView.findFocus();
269 | mPagerAdapter.setTop(tabLayout.getSelectedTabPosition());
270 | }
271 | });
272 |
273 | if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", false)) {
274 | tabLayout.setSelectedTabIndicatorColor(getResources().getColor(R.color.DarkColor));
275 | tabLayout.setTabTextColors(tabLayout.getTabTextColors().getDefaultColor(), getResources().getColor(R.color.DarkColor));
276 | }
277 | }
278 |
279 | private void addpage(BaseFragment fragment, String s) {
280 |
281 | if (autoupdate.getBoolean(s, true)) {
282 | fragments.add(fragment);
283 | titles.add(s);
284 | }
285 | }
286 |
287 | @Override
288 | public boolean onOptionsItemSelected(MenuItem item) {
289 | switch (item.getItemId()) {
290 | case R.id.about:
291 | startActivity(new Intent(this, AboutActivity.class));
292 | break;
293 | case R.id.setting:
294 | startActivity(new Intent(this, SettingsActivity.class));
295 | break;
296 | case R.id.Theme:
297 | SharedPreferences.Editor meditor = PreferenceManager.getDefaultSharedPreferences(this).edit();
298 | if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", false))
299 | meditor.putBoolean("dark_theme", false);
300 | else
301 | meditor.putBoolean("dark_theme", true);
302 | meditor.apply();
303 | Intent intent = getIntent();
304 |
305 | startActivity(intent);
306 | this.overridePendingTransition(R.anim.enter_anim,0);
307 | finish();
308 |
309 | break;
310 | }
311 | return true;
312 | }
313 |
314 | @Override
315 | public boolean onCreateOptionsMenu(Menu menu) {
316 | getMenuInflater().inflate(R.menu.menu, menu);
317 |
318 | if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", false))
319 | menu.findItem(R.id.Theme).setTitle("今夜白");
320 | final MenuItem searchItem = menu.findItem(R.id.toolbar_search);
321 | searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
322 | MenuItemCompat.getActionView(searchItem);
323 | searchView.setQueryHint("搜索书籍或者作者");
324 | searchView.setOnSearchClickListener(new View.OnClickListener() {
325 | @Override
326 | public void onClick(View v) {
327 | searchView.setQuery(lastKeyWords, false);
328 | }
329 | });
330 |
331 |
332 | searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
333 | @Override
334 | public boolean onQueryTextSubmit(String query) {
335 | //处理搜索结果
336 | try {
337 | lastKeyWords = query;
338 | Runtime runtime = Runtime.getRuntime();
339 | runtime.exec("input keyevent " + KeyEvent.KEYCODE_BACK);
340 | runtime.exec("input keyevent " + KeyEvent.KEYCODE_BACK);
341 | setTitle("搜索:" + query);
342 | for (BaseFragment fragment : mPagerAdapter.getFragments()) {
343 | fragment.startSearch(query);
344 | }
345 | } catch (Exception e) {
346 | e.printStackTrace();
347 | }
348 | return false;
349 | }
350 |
351 | @Override
352 | public boolean onQueryTextChange(String s) {
353 | return false;
354 | }
355 | });
356 | return super.onCreateOptionsMenu(menu);
357 | }
358 | }
359 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/activity/SettingsActivity.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.activity;
2 |
3 |
4 | import android.content.Context;
5 | import android.os.Bundle;
6 | import android.preference.PreferenceActivity;
7 | import android.preference.PreferenceManager;
8 | import android.support.annotation.Nullable;
9 | import android.util.AttributeSet;
10 | import android.view.MenuItem;
11 | import android.view.View;
12 |
13 | import com.delsart.bookdownload.R;
14 |
15 | public class SettingsActivity extends PreferenceActivity {
16 |
17 | @Override
18 | public void onCreate(@Nullable Bundle savedInstanceState) {
19 | if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", false))
20 | setTheme(R.style.DarkThemeSettingTheme);
21 | else
22 | setTheme(R.style.settingTheme);
23 | super.onCreate(savedInstanceState);
24 |
25 | getActionBar().setDisplayHomeAsUpEnabled(true);
26 | addPreferencesFromResource(R.xml.settinglayout);
27 | }
28 |
29 |
30 |
31 | @Override
32 | public boolean onMenuItemSelected(int featureId, MenuItem item) {
33 | finish();
34 | return super.onMenuItemSelected(featureId, item);
35 |
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/activity/UsedOpenSource.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.activity;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.preference.PreferenceManager;
6 | import android.support.annotation.NonNull;
7 | import android.support.annotation.Nullable;
8 | import android.support.v4.content.ContextCompat;
9 | import android.view.MenuItem;
10 |
11 | import com.danielstone.materialaboutlibrary.ConvenienceBuilder;
12 | import com.danielstone.materialaboutlibrary.model.MaterialAboutCard;
13 | import com.danielstone.materialaboutlibrary.model.MaterialAboutList;
14 | import com.danielstone.materialaboutlibrary.util.OpenSourceLicense;
15 | import com.delsart.bookdownload.R;
16 | import com.mikepenz.community_material_typeface_library.CommunityMaterial;
17 | import com.mikepenz.iconics.IconicsDrawable;
18 |
19 | /**
20 | * Created by Delsart on 2017/7/24.
21 | */
22 |
23 | public class UsedOpenSource extends AboutActivity {
24 | @Override
25 | protected void onCreate(@Nullable Bundle savedInstanceState) {
26 | if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", false)) {
27 | setTheme(R.style.DarkTheme_aboutTheme);
28 | colorIcon = R.color.DarkColor;
29 | }
30 | else
31 | setTheme(R.style.aboutTheme);
32 | super.onCreate(savedInstanceState);
33 | }
34 | @NonNull
35 | @Override
36 | protected MaterialAboutList getMaterialAboutList(@NonNull final Context c) {
37 | MaterialAboutCard materialAboutLIbraryLicenseCard = ConvenienceBuilder.createLicenseCard(c,
38 | new IconicsDrawable(c)
39 | .icon(CommunityMaterial.Icon.cmd_book)
40 | .color(ContextCompat.getColor(c, colorIcon))
41 | .sizeDp(18),
42 | "material-about-library", "2016", "Daniel Stone",
43 | OpenSourceLicense.APACHE_2);
44 |
45 | MaterialAboutCard androidIconicsLicenseCard = ConvenienceBuilder.createLicenseCard(c,
46 | new IconicsDrawable(c)
47 | .icon(CommunityMaterial.Icon.cmd_book)
48 | .color(ContextCompat.getColor(c, colorIcon))
49 | .sizeDp(18),
50 | "Android Iconics", "2016", "Mike Penz",
51 | OpenSourceLicense.APACHE_2);
52 |
53 | MaterialAboutCard leakCanaryLicenseCard = ConvenienceBuilder.createLicenseCard(c,
54 | new IconicsDrawable(c)
55 | .icon(CommunityMaterial.Icon.cmd_book)
56 | .color(ContextCompat.getColor(c, colorIcon))
57 | .sizeDp(18),
58 | "BRVAH", "2016", "陈宇明",
59 | OpenSourceLicense.APACHE_2);
60 |
61 | MaterialAboutCard mitLicenseCard = ConvenienceBuilder.createLicenseCard(c,
62 | new IconicsDrawable(c)
63 | .icon(CommunityMaterial.Icon.cmd_book)
64 | .color(ContextCompat.getColor(c, colorIcon))
65 | .sizeDp(18),
66 | "Jsoup", "2017", "Jonathan Hedley",
67 | OpenSourceLicense.MIT);
68 |
69 |
70 |
71 | return new MaterialAboutList(materialAboutLIbraryLicenseCard,
72 | androidIconicsLicenseCard,
73 | leakCanaryLicenseCard,
74 | mitLicenseCard);
75 | }
76 |
77 | @Override
78 | protected CharSequence getActivityTitle() {
79 | return "Used-open-sources";
80 | }
81 |
82 | @Override
83 | public boolean onOptionsItemSelected(MenuItem item) {
84 | switch (item.getItemId()) {
85 | case android.R.id.home:
86 | finish();
87 | return true;
88 | default:
89 | return false;
90 | }
91 | }
92 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/fragment/AiXiaFragment.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.fragment;
2 |
3 |
4 | import android.os.Handler;
5 |
6 | import com.delsart.bookdownload.service.AiXiaService;
7 | import com.delsart.bookdownload.service.BaseService;
8 |
9 | public class AiXiaFragment extends BaseFragment {
10 |
11 | @Override
12 | protected BaseService getService(Handler handler, String keywords) {
13 | return new AiXiaService(handler, keywords);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/fragment/BaseFragment.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.fragment;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.DialogInterface;
5 | import android.content.Intent;
6 | import android.net.Uri;
7 | import android.os.Bundle;
8 | import android.os.Handler;
9 | import android.os.Looper;
10 | import android.os.Message;
11 | import android.preference.PreferenceManager;
12 | import android.support.annotation.Nullable;
13 | import android.support.design.widget.Snackbar;
14 | import android.support.v4.app.Fragment;
15 | import android.support.v4.app.NotificationCompatSideChannelService;
16 | import android.support.v4.content.ContextCompat;
17 | import android.support.v7.app.AlertDialog;
18 | import android.support.v7.widget.LinearLayoutManager;
19 | import android.support.v7.widget.RecyclerView;
20 | import android.view.LayoutInflater;
21 | import android.view.View;
22 | import android.view.ViewGroup;
23 | import android.widget.ImageView;
24 | import android.widget.LinearLayout;
25 | import android.widget.TextView;
26 | import android.widget.Toast;
27 |
28 | import com.bumptech.glide.Glide;
29 | import com.chad.library.adapter.base.BaseQuickAdapter;
30 | import com.delsart.bookdownload.MsgType;
31 | import com.delsart.bookdownload.R;
32 | import com.delsart.bookdownload.adapter.MyItemAdapter;
33 | import com.delsart.bookdownload.bean.DownloadBean;
34 | import com.delsart.bookdownload.bean.NovelBean;
35 | import com.delsart.bookdownload.handler.MyHandler;
36 | import com.delsart.bookdownload.handler.OnHandleMessageCallback;
37 | import com.delsart.bookdownload.service.BaseService;
38 |
39 | import java.util.ArrayList;
40 |
41 | public abstract class BaseFragment extends Fragment {
42 | public final MyHandler mHandler = new MyHandler<>(this);
43 | private RecyclerView mRecyclerView;
44 | public MyItemAdapter mAdapter;
45 | public BaseService mService;
46 | public ArrayList mList = new ArrayList<>();
47 | private ProgressDialog waitingDialog;
48 | public View mNoFoundView;
49 | private View mSearchingView;
50 |
51 |
52 | protected abstract BaseService getService(Handler handler, String keywords);
53 |
54 | @Nullable
55 | @Override
56 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
57 | View mNoSearchView = inflater.inflate(R.layout.view_no_search, null, false);
58 | mNoFoundView = inflater.inflate(R.layout.view_no_found, null, false);
59 | mSearchingView = inflater.inflate(R.layout.view_searching, null, false);
60 | View view = LayoutInflater.from(getContext()).inflate(R.layout.recycler_view, container, false);
61 | mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
62 |
63 | mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
64 | if (PreferenceManager.getDefaultSharedPreferences(getContext())
65 | .getBoolean("dark_theme",false))
66 | {
67 | mRecyclerView.setBackgroundColor(ContextCompat.getColor(getContext(),R.color.DarkRecyclerViewBackground));
68 | mAdapter = new MyItemAdapter(ContextCompat.getColor(getContext(),R.color.DarkMainColor));
69 | }else
70 | mAdapter = new MyItemAdapter(ContextCompat.getColor(getContext(),R.color.DayColor));
71 | mAdapter.openLoadAnimation(BaseQuickAdapter.SLIDEIN_BOTTOM);
72 | mAdapter.setEmptyView(mNoSearchView);
73 | mRecyclerView.setAdapter(mAdapter);
74 |
75 |
76 | initLoadMore();
77 | setOnClickEvent();
78 | initReLoad();
79 | return view;
80 | }
81 |
82 |
83 | private void initReLoad() {
84 | mNoFoundView.setOnClickListener(new View.OnClickListener() {
85 | @Override
86 | public void onClick(View v) {
87 | mAdapter.setEmptyView(mSearchingView);
88 | mService.reLoad();
89 | }
90 | });
91 | }
92 |
93 | public void initLoadMore() {
94 | mAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
95 | @Override
96 | public void onLoadMoreRequested() {
97 | mService.get();
98 | }
99 | }, mRecyclerView);
100 | }
101 |
102 | private void setOnClickEvent() {
103 | mAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
104 | @Override
105 | public void onItemClick(BaseQuickAdapter adapter, View view, final int position) {
106 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
107 | builder.setTitle("查看");
108 | View mDialogView = LayoutInflater.from(getContext()).inflate(R.layout.view_dialog, null);
109 | LinearLayout linearLayout = (LinearLayout) mDialogView.findViewById(R.id.droot);
110 | TextView mDialogName = (TextView) linearLayout.getChildAt(0);
111 | ImageView mDialogPic = (ImageView) linearLayout.getChildAt(1);
112 | TextView mDialogInfo = (TextView) linearLayout.getChildAt(2);
113 | mDialogName.setText(mList.get(position).getName());
114 | mDialogInfo.setText(mList.get(position).getShowText());
115 | Glide.with(getContext()).load(mList.get(position).getPic()).into(mDialogPic);
116 | mDialogPic.setOnLongClickListener(new View.OnLongClickListener() {
117 | @Override
118 | public boolean onLongClick(View v) {
119 | Toast.makeText(getContext(),"在网页中打开图片",Toast.LENGTH_SHORT).show();
120 | Uri uri = Uri.parse(mList.get(position).getPic());
121 | startActivity(new Intent(Intent.ACTION_VIEW, uri));
122 | return false;
123 | }
124 | });
125 | builder.setView(mDialogView);
126 | builder.setPositiveButton("下载", new DialogInterface.OnClickListener() {
127 | @Override
128 | public void onClick(DialogInterface dialog, int which) {
129 | waitingDialog = new ProgressDialog(getContext());
130 | waitingDialog.setTitle("下载");
131 | waitingDialog.setMessage("获取中...");
132 | waitingDialog.setIndeterminate(true);
133 | waitingDialog.setCancelable(false);
134 | waitingDialog.show();
135 | try {
136 | new Thread(new Runnable() {
137 | @Override
138 | public void run() {
139 | try {
140 | doOnClickDownload(mService.getDownloadurls(mList.get(position).getDownloadFromUrl()));
141 | } catch (InterruptedException e) {
142 | e.printStackTrace();
143 | }
144 | }
145 | }).start();
146 | } catch (Exception e) {
147 | e.printStackTrace();
148 | }
149 | }
150 | });
151 | builder.setNegativeButton("取消", null);
152 | builder.show();
153 | }
154 | });
155 | }
156 |
157 | public void doOnClickDownload(final ArrayList urls) {
158 | String[] sList = new String[urls.size()];
159 | for (int i = 0; i < urls.size(); i++) {
160 | sList[i] = urls.get(i).getType();
161 | }
162 | AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
163 | Looper.prepare();
164 | builder.setTitle("选择下载对象");
165 | builder.setItems(sList, new DialogInterface.OnClickListener() {
166 | @Override
167 | public void onClick(DialogInterface dialog, int which) {
168 | String url = urls.get(which).getUrl();
169 | if (!url.equals("")) {
170 | Uri uri = Uri.parse(url);
171 | startActivity(new Intent(Intent.ACTION_VIEW, uri));
172 | }
173 | }
174 | });
175 | builder.setPositiveButton("取消", null);
176 | builder.create().show();
177 | waitingDialog.dismiss();
178 | Looper.loop();
179 | }
180 |
181 |
182 | public void startSearch(String keywords) {
183 | mList.clear();
184 | mAdapter.setNewData(null);
185 | mService = getService(mHandler, keywords);
186 | mAdapter.setEmptyView(mSearchingView);
187 | runService();
188 | }
189 |
190 |
191 | public void runService() {
192 | mService.get();
193 | mHandler.setOnHandleMessageCallback(new OnHandleMessageCallback() {
194 | @Override
195 | public void handleMessage(BaseFragment fragment, Message msg) {
196 | switch (msg.what) {
197 | case MsgType.ERROR:
198 | mAdapter.loadMoreFail();
199 | mAdapter.setEmptyView(mNoFoundView);
200 | break;
201 | case MsgType.SUCCESS:
202 | ArrayList data = (ArrayList) msg.obj;
203 | if (data != null) {
204 | mList.addAll(data);
205 | if (data.size() > 0) {
206 | mAdapter.addData(data);
207 | mAdapter.loadMoreComplete();
208 | } else {
209 | mAdapter.setEmptyView(mNoFoundView);
210 | mAdapter.loadMoreEnd();
211 | }
212 | } else {
213 | Snackbar.make(getActivity().findViewById(android.R.id.content), "未知错误", Snackbar.LENGTH_SHORT).show();
214 | }
215 | break;
216 | }
217 | }
218 | });
219 | }
220 |
221 | public void toTop() {
222 | mRecyclerView.smoothScrollToPosition(0);
223 | }
224 | }
225 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/fragment/BlahFragment.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.fragment;
2 |
3 |
4 | import android.os.Handler;
5 |
6 | import com.delsart.bookdownload.service.BaseService;
7 | import com.delsart.bookdownload.service.BlahService;
8 |
9 | public class BlahFragment extends BaseFragment {
10 |
11 | @Override
12 | protected BaseService getService(Handler handler, String keywords) {
13 | return new BlahService(handler, keywords);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/fragment/DongManZhiJiaFragment.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.fragment;
2 |
3 |
4 | import android.os.Handler;
5 | import android.os.Message;
6 | import android.support.design.widget.Snackbar;
7 |
8 | import com.chad.library.adapter.base.BaseQuickAdapter;
9 | import com.delsart.bookdownload.MsgType;
10 | import com.delsart.bookdownload.bean.NovelBean;
11 | import com.delsart.bookdownload.handler.OnHandleMessageCallback;
12 | import com.delsart.bookdownload.service.BaseService;
13 | import com.delsart.bookdownload.service.DongManZhiJiaService;
14 | import com.delsart.bookdownload.service.ZhouDuService;
15 |
16 | import java.util.ArrayList;
17 |
18 | public class DongManZhiJiaFragment extends BaseFragment {
19 |
20 | @Override
21 | protected BaseService getService(Handler handler, String keywords) {
22 | return new DongManZhiJiaService(handler, keywords);
23 | }
24 |
25 | @Override
26 | public void runService() {
27 | mService.get();
28 | mHandler.setOnHandleMessageCallback(new OnHandleMessageCallback() {
29 | @Override
30 | public void handleMessage(BaseFragment fragment, Message msg) {
31 | switch (msg.what) {
32 | case MsgType.ERROR:
33 | mAdapter.loadMoreFail();
34 | mAdapter.setEmptyView(mNoFoundView);
35 | break;
36 | case MsgType.SUCCESS:
37 | ArrayList data = (ArrayList) msg.obj;
38 | if (data != null) {
39 | mList.addAll(data);
40 | if (data.size() > 0) {
41 | mAdapter.addData(data);
42 | mAdapter.loadMoreEnd();
43 | } else {
44 | mAdapter.setEmptyView(mNoFoundView);
45 | mAdapter.loadMoreEnd();
46 | }
47 | } else {
48 | Snackbar.make(getActivity().findViewById(android.R.id.content), "未知错误", Snackbar.LENGTH_SHORT).show();
49 | }
50 | break;
51 | }
52 | }
53 | });
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/fragment/M360DFragment.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.fragment;
2 |
3 |
4 | import android.os.Handler;
5 |
6 | import com.delsart.bookdownload.service.BaseService;
7 | import com.delsart.bookdownload.service.M360DService;
8 |
9 | public class M360DFragment extends BaseFragment {
10 |
11 | @Override
12 | protected BaseService getService(Handler handler, String keywords) {
13 | return new M360DService(handler, keywords);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/fragment/QiShuFragment.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.fragment;
2 |
3 |
4 | import android.os.Handler;
5 |
6 | import com.delsart.bookdownload.service.BaseService;
7 | import com.delsart.bookdownload.service.QiShuService;
8 |
9 | public class QiShuFragment extends BaseFragment {
10 |
11 | @Override
12 | protected BaseService getService(Handler handler, String keywords) {
13 | return new QiShuService(handler, keywords);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/fragment/ShuYuZheFragment.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.fragment;
2 |
3 |
4 | import android.os.Handler;
5 |
6 | import com.delsart.bookdownload.service.BaseService;
7 | import com.delsart.bookdownload.service.ShuYuZheService;
8 |
9 | public class ShuYuZheFragment extends BaseFragment {
10 |
11 | @Override
12 | protected BaseService getService(Handler handler, String keywords) {
13 | return new ShuYuZheService(handler, keywords);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/fragment/XiaoShuWuFragment.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.fragment;
2 |
3 |
4 | import android.os.Handler;
5 |
6 | import com.delsart.bookdownload.service.BaseService;
7 | import com.delsart.bookdownload.service.XiaoShuWuService;
8 |
9 | public class XiaoShuWuFragment extends BaseFragment {
10 |
11 | @Override
12 | protected BaseService getService(Handler handler, String keywords) {
13 | return new XiaoShuWuService(handler, keywords);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/fragment/ZhiXuanFragment.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.fragment;
2 |
3 |
4 | import android.os.Handler;
5 |
6 | import com.delsart.bookdownload.service.BaseService;
7 | import com.delsart.bookdownload.service.ZhiXuanService;
8 |
9 | public class ZhiXuanFragment extends BaseFragment {
10 |
11 | @Override
12 | protected BaseService getService(Handler handler, String keywords) {
13 | return new ZhiXuanService(handler, keywords);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/ui/fragment/ZhouDuFragment.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.ui.fragment;
2 |
3 |
4 | import android.os.Handler;
5 |
6 | import com.delsart.bookdownload.service.BaseService;
7 | import com.delsart.bookdownload.service.ZhouDuService;
8 |
9 | public class ZhouDuFragment extends BaseFragment {
10 |
11 | @Override
12 | protected BaseService getService(Handler handler, String keywords) {
13 | return new ZhouDuService(handler, keywords);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/delsart/bookdownload/utils/StatusBarUtils.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload.utils;
2 |
3 | import android.app.Activity;
4 | import android.os.Build;
5 | import android.view.View;
6 | import android.view.Window;
7 |
8 | import java.lang.reflect.Field;
9 | import java.lang.reflect.Method;
10 |
11 |
12 | public class StatusBarUtils {
13 | public static boolean MIUISetStatusBarLightMode(Activity activity, boolean dark) {
14 | boolean result = false;
15 | Window window = activity.getWindow();
16 | if (window != null) {
17 | Class clazz = window.getClass();
18 | try {
19 | int darkModeFlag = 0;
20 | Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
21 | Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
22 | darkModeFlag = field.getInt(layoutParams);
23 | Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
24 | if (dark) {
25 | extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体
26 | } else {
27 | extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
28 | }
29 | result = true;
30 |
31 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
32 | //开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
33 | if (dark) {
34 | activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
35 | } else {
36 | activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
37 | }
38 | }
39 | } catch (Exception ignored) {
40 | }
41 | }
42 | return result;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/enter_anim.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
20 |
21 |
30 |
31 |
32 |
37 |
38 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_custom.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
21 |
22 |
29 |
30 |
37 |
38 |
39 |
40 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
20 |
21 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/recycler_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
15 |
16 |
21 |
22 |
28 |
29 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_no_found.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_no_search.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_searching.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Delsart/Bookster/dead2122e3456e910a13dc7c906282cc83f0c594/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Delsart/Bookster/dead2122e3456e910a13dc7c906282cc83f0c594/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_to_top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Delsart/Bookster/dead2122e3456e910a13dc7c906282cc83f0c594/app/src/main/res/mipmap-xhdpi/ic_to_top.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Delsart/Bookster/dead2122e3456e910a13dc7c906282cc83f0c594/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Delsart/Bookster/dead2122e3456e910a13dc7c906282cc83f0c594/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Delsart/Bookster/dead2122e3456e910a13dc7c906282cc83f0c594/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Delsart/Bookster/dead2122e3456e910a13dc7c906282cc83f0c594/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_no_found.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Delsart/Bookster/dead2122e3456e910a13dc7c906282cc83f0c594/app/src/main/res/mipmap-xxxhdpi/ic_no_found.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_no_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Delsart/Bookster/dead2122e3456e910a13dc7c906282cc83f0c594/app/src/main/res/mipmap-xxxhdpi/ic_no_search.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v23/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
23 |
24 |
25 |
26 |
34 |
35 |
42 |
43 |
44 |
45 |
53 |
61 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | @color/accent_material_light
6 | #ffffff
7 | #608cb1
8 | #2c2c2c
9 | #202020
10 | #4C708E
11 | #00000000
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 | 16dp
3 | 16dp
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Bookster
3 | 请进行搜索
4 | 本软件只提供搜索服务,不储存任何网络资源。所得任何结果不代表本应用立场。\n\n本软件完全免费,所有数据均来源网络,请勿用作非法用途,如果侵害了你的权益,请联系我尽快删除。\n\n如果可以,请点击来源网页中的广告来支持来源网站做下去
5 | 设置
6 | 到目前为止,用的还算称心吗?\n\n在这里恳请您为这个应用评个5星。\n\n此外开发者在这个应用上花费了大量的心血和时间,希望您能够小小的支持一下。
7 | 没有找到搜索条目\n点击重试,或尝试其他来源
8 | 正在搜索…
9 | Search
10 | 设置
11 | 关于
12 | 深空黑
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
18 |
19 |
20 |
21 |
22 |
28 |
29 |
35 |
36 |
37 |
38 |
39 |
40 |
46 |
51 |
52 |
53 |
54 |
60 |
61 |
65 |
69 |
70 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/settinglayout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
16 |
20 |
24 |
28 |
32 |
36 |
40 |
44 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/test/java/com/delsart/bookdownload/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.delsart.bookdownload;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
6 | jcenter()
7 | mavenCentral()
8 | maven { url "https://jitpack.io" }
9 | maven { url = 'https://dl.bintray.com/yuancloud/maven/' }
10 | }
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:2.3.3'
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
22 | jcenter()
23 | mavenCentral()
24 | maven { url "https://jitpack.io" }
25 | maven { url = 'https://dl.bintray.com/yuancloud/maven/' }
26 | }
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Delsart/Bookster/dead2122e3456e910a13dc7c906282cc83f0c594/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jul 21 23:53:24 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/更新日志.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Delsart/Bookster/dead2122e3456e910a13dc7c906282cc83f0c594/更新日志.txt
--------------------------------------------------------------------------------