├── .gitignore ├── .idea ├── gradle.xml ├── kotlinc.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── release │ └── output.json └── src │ ├── androidTest │ └── java │ │ └── cc │ │ └── zsakvo │ │ └── a99demo │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── cc │ │ │ └── zsakvo │ │ │ └── ninecswd │ │ │ ├── ArticleActivity.java │ │ │ ├── BookDetailActivity.java │ │ │ ├── CategoryActivity.java │ │ │ ├── ChangeCoverActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── SearchActivity.java │ │ │ ├── adapter │ │ │ ├── ArticleAdapter.java │ │ │ ├── CategoryAdapter.java │ │ │ ├── CoverListAdapter.java │ │ │ ├── ListAdapter.java │ │ │ └── MyViewpagerAdapter.java │ │ │ ├── application │ │ │ └── MyApplication.java │ │ │ ├── classes │ │ │ ├── ArticleList.java │ │ │ ├── BookDetails.java │ │ │ ├── BookList.java │ │ │ └── DownloadDetails.java │ │ │ ├── fragment │ │ │ ├── ArticleFragment.java │ │ │ ├── BaseFragment.java │ │ │ ├── BookStoreFragment.java │ │ │ └── CategoryFragment.java │ │ │ ├── listener │ │ │ ├── Interface.java │ │ │ ├── ItemClickListener.java │ │ │ └── OnDataFinishedListener.java │ │ │ ├── phrase │ │ │ ├── Book.java │ │ │ └── PhraseBookDetail.java │ │ │ ├── task │ │ │ ├── DownloadTask.java │ │ │ ├── GetArticleContentTask.java │ │ │ ├── GetArticleListTask.java │ │ │ ├── GetBookDetailTask.java │ │ │ ├── GetBookListTask.java │ │ │ ├── GetCategoryListTask.java │ │ │ ├── GetCoversTask.java │ │ │ ├── GetDownloadInfoTask.java │ │ │ ├── GetSearchListTask.java │ │ │ ├── OutPutTxtTask.java │ │ │ └── SetCoverTask.java │ │ │ └── utils │ │ │ ├── DecodeUtils.java │ │ │ ├── DialogUtils.java │ │ │ ├── EpubUtils.java │ │ │ ├── ReplaceUtils.java │ │ │ ├── SplitUtil.java │ │ │ └── TxtUtils.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── ic_baidu.xml │ │ ├── ic_bing.xml │ │ ├── ic_launcher_background.xml │ │ └── ic_search.xml │ │ ├── layout │ │ ├── activity_article.xml │ │ ├── activity_category.xml │ │ ├── activity_change_cover.xml │ │ ├── activity_main.xml │ │ ├── activity_search.xml │ │ ├── articlelist.xml │ │ ├── booklist.xml │ │ ├── categorylist.xml │ │ ├── coverlist.xml │ │ ├── dialog.xml │ │ ├── fragment_99lib.xml │ │ ├── fragment_article.xml │ │ ├── fragment_category.xml │ │ └── n_activity_book_detail.xml │ │ ├── menu │ │ ├── main_menu.xml │ │ ├── search_menu.xml │ │ └── select_engine_menu.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── cc │ └── zsakvo │ └── a99demo │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2018.9.7 网站升级,目前已失效,研究更新 2 | 3 | # 99LibraryDownloader 4 | 从99lib抓取书籍并生成epub 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | defaultConfig { 6 | applicationId "cc.zsakvo.ninecswd" 7 | minSdkVersion 21 8 | targetSdkVersion 27 9 | versionCode 3 10 | versionName "1.1-beta" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(dir: 'libs', include: ['*.jar']) 23 | implementation 'com.android.support:appcompat-v7:27.0.2' 24 | implementation 'com.android.support:cardview-v7:27.0.2' 25 | implementation 'com.zzhoujay.richtext:richtext:3.0.5' 26 | implementation 'com.android.support:design:27.0.2' 27 | implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.4-7' 28 | implementation 'com.scwang.smartrefresh:SmartRefreshHeader:1.0.4-7' 29 | implementation 'org.zeroturnaround:zt-zip:1.12' 30 | // implementation 'org.jsoup:jsoup:1.11.2' 31 | implementation 'com.github.limuyang2:CardSearchView:1.0.6.9' 32 | implementation 'com.github.nukc.stateview:library:1.3.4' 33 | implementation 'io.simi:nob:0.0.8' 34 | // implementation 'com.mapzen:on-the-road:0.8.1' 35 | implementation 'com.github.bumptech.glide:glide:4.4.0' 36 | // implementation 'com.alibaba:fastjson:1.1.68.android' 37 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.31" 38 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 39 | testImplementation 'junit:junit:4.12' 40 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 41 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 42 | } 43 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/release/output.json: -------------------------------------------------------------------------------- 1 | [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":3},"path":"app-release.apk","properties":{"packageId":"cc.zsakvo.ninecswd","split":"","minSdkVersion":"21"}}] -------------------------------------------------------------------------------- /app/src/androidTest/java/cc/zsakvo/a99demo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.a99demo; 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 | * Instrumented 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("cc.zsakvo.a99demo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/ArticleActivity.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd; 2 | 3 | import android.support.design.widget.Snackbar; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | import android.support.v7.widget.Toolbar; 7 | import android.view.MenuItem; 8 | import android.view.View; 9 | import android.widget.ScrollView; 10 | import android.widget.TextView; 11 | 12 | import com.github.nukc.stateview.StateView; 13 | import com.scwang.smartrefresh.header.MaterialHeader; 14 | import com.scwang.smartrefresh.layout.api.RefreshLayout; 15 | import com.scwang.smartrefresh.layout.listener.OnRefreshListener; 16 | 17 | import cc.zsakvo.ninecswd.listener.Interface; 18 | import cc.zsakvo.ninecswd.task.GetArticleContentTask; 19 | 20 | public class ArticleActivity extends AppCompatActivity implements Interface.GetArticle,OnRefreshListener{ 21 | 22 | Toolbar toolbar; 23 | private StateView mStateView; 24 | RefreshLayout refreshLayout; 25 | TextView tv_article; 26 | String url; 27 | ScrollView sv; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate (savedInstanceState); 32 | setContentView (R.layout.activity_article); 33 | toolbar = (Toolbar)findViewById (R.id.atToolBar); 34 | toolbar.setTitle ("文库"); 35 | setSupportActionBar(toolbar); 36 | if (getSupportActionBar() != null) { 37 | getSupportActionBar ().setDisplayHomeAsUpEnabled (true); 38 | } 39 | url = getIntent ().getStringExtra ("url"); 40 | String title = getIntent ().getStringExtra ("title"); 41 | tv_article = (TextView)findViewById (R.id.article); 42 | sv = (ScrollView)findViewById (R.id.at_scroll); 43 | refreshLayout = (RefreshLayout)findViewById (R.id.atRefreshLayout); 44 | refreshLayout.setOnRefreshListener (this); 45 | refreshLayout.setEnableAutoLoadmore (true); 46 | MaterialHeader mMaterialHeader = (MaterialHeader) refreshLayout.getRefreshHeader (); 47 | refreshLayout.autoRefresh (); 48 | // GetArticleContentTask gct = new GetArticleContentTask (tv_article,toolbar,mStateView,this); 49 | // gct.execute (url); 50 | } 51 | 52 | @Override 53 | public boolean onOptionsItemSelected(MenuItem item) { 54 | if(item.getItemId()==android.R.id.home){ 55 | finish (); 56 | return true; 57 | } 58 | return super.onOptionsItemSelected(item); 59 | } 60 | 61 | @Override 62 | public void GetResult(Boolean result) { 63 | if (result){ 64 | sv.setVisibility (View.VISIBLE); 65 | refreshLayout.finishRefresh (300); 66 | }else { 67 | refreshLayout.finishRefresh (false); 68 | Snackbar.make (toolbar,"数据获取失败,请检查网络连接后重试!",Snackbar.LENGTH_LONG).show (); 69 | } 70 | } 71 | 72 | @Override 73 | public void onRefresh(RefreshLayout refreshlayout) { 74 | GetArticleContentTask gct = new GetArticleContentTask (tv_article,toolbar,mStateView,ArticleActivity.this); 75 | gct.execute (url); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/BookDetailActivity.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd; 2 | 3 | import android.app.Activity; 4 | import android.app.Dialog; 5 | import android.content.Intent; 6 | import android.content.pm.PackageManager; 7 | import android.graphics.Bitmap; 8 | import android.graphics.drawable.BitmapDrawable; 9 | import android.net.Uri; 10 | import android.os.AsyncTask; 11 | import android.os.Build; 12 | import android.os.Environment; 13 | import android.support.design.widget.FloatingActionButton; 14 | import android.support.design.widget.Snackbar; 15 | import android.support.v4.app.ActivityCompat; 16 | import android.support.v7.app.AppCompatActivity; 17 | import android.os.Bundle; 18 | import android.support.v7.widget.CardView; 19 | import android.support.v7.widget.Toolbar; 20 | import android.util.Log; 21 | import android.view.MenuItem; 22 | import android.view.View; 23 | import android.widget.ImageView; 24 | import android.widget.TextView; 25 | 26 | import com.bumptech.glide.Glide; 27 | import com.scwang.smartrefresh.header.MaterialHeader; 28 | import com.scwang.smartrefresh.layout.api.RefreshLayout; 29 | import com.scwang.smartrefresh.layout.listener.OnRefreshListener; 30 | 31 | import org.w3c.dom.Text; 32 | 33 | import java.io.File; 34 | import java.util.ArrayList; 35 | import java.util.List; 36 | import java.util.concurrent.ConcurrentHashMap; 37 | 38 | import cc.zsakvo.ninecswd.classes.DownloadDetails; 39 | import cc.zsakvo.ninecswd.listener.Interface; 40 | import cc.zsakvo.ninecswd.listener.OnDataFinishedListener; 41 | import cc.zsakvo.ninecswd.task.DownloadTask; 42 | import cc.zsakvo.ninecswd.task.GetDownloadInfoTask; 43 | import cc.zsakvo.ninecswd.task.GetBookDetailTask; 44 | import cc.zsakvo.ninecswd.task.OutPutTxtTask; 45 | import cc.zsakvo.ninecswd.task.SetCoverTask; 46 | import cc.zsakvo.ninecswd.utils.DialogUtils; 47 | import cc.zsakvo.ninecswd.utils.EpubUtils; 48 | import cc.zsakvo.ninecswd.utils.SplitUtil; 49 | import io.simi.nob.NOBKit; 50 | 51 | import static android.os.AsyncTask.THREAD_POOL_EXECUTOR; 52 | 53 | public class BookDetailActivity extends AppCompatActivity implements View.OnClickListener,OnDataFinishedListener,EpubUtils.getResult,Interface.GetBookDetailFinish,OnRefreshListener,Interface.OutPutTxtFinish{ 54 | 55 | Toolbar toolbar; 56 | TextView tv_title,tv_intro,tv_detail,tv_dlTXT,tv_dlEpub,tv_dlNob; 57 | ImageView iv_cover; 58 | RefreshLayout refreshLayout; 59 | String url; 60 | CardView cv; 61 | FloatingActionButton fab; 62 | Dialog loadingDialog; 63 | ConcurrentHashMap ch = new ConcurrentHashMap<> (); 64 | private int nowNum; 65 | private int allNum; 66 | private List chapterIDs; 67 | private int whatGenerate = 0; 68 | private Boolean loadOK = false; 69 | DialogUtils du; 70 | Boolean hasPermissions = false; 71 | DownloadDetails downloadDetails = null; 72 | private static final int REQUEST_EXTERNAL_STORAGE = 1; 73 | private static String[] PERMISSIONS_STORAGE = { 74 | "android.permission.READ_EXTERNAL_STORAGE", 75 | "android.permission.WRITE_EXTERNAL_STORAGE" }; 76 | private Bitmap cover_bit; 77 | private String searchStr; 78 | 79 | @Override 80 | protected void onCreate(Bundle savedInstanceState) { 81 | super.onCreate(savedInstanceState); 82 | setContentView(R.layout.n_activity_book_detail); 83 | toolbar = (Toolbar)findViewById(R.id.bdToolBar); 84 | toolbar.setTitle("书籍详情"); 85 | setSupportActionBar(toolbar); 86 | if (getSupportActionBar() != null) { 87 | getSupportActionBar ().setDisplayHomeAsUpEnabled (true); 88 | } 89 | url = getIntent().getStringExtra("url"); 90 | tv_title = (TextView)findViewById(R.id.bdTitle); 91 | tv_intro = (TextView)findViewById(R.id.bdIntro); 92 | tv_detail = (TextView)findViewById(R.id.bdDetail); 93 | iv_cover = (ImageView)findViewById(R.id.bdCover); 94 | iv_cover.setOnClickListener (this); 95 | du = new DialogUtils (this,loadingDialog); 96 | 97 | cv = (CardView)findViewById (R.id.dl_card); 98 | tv_dlTXT = (TextView)findViewById (R.id.dl_txt); 99 | tv_dlTXT.setOnClickListener (this); 100 | tv_dlEpub = (TextView)findViewById (R.id.dl_epub); 101 | tv_dlEpub.setOnClickListener (this); 102 | tv_dlNob = (TextView) findViewById (R.id.dl_nob); 103 | tv_dlNob.setOnClickListener (this); 104 | 105 | refreshLayout = (RefreshLayout) findViewById (R.id.bdRefreshLayout); 106 | refreshLayout.setOnRefreshListener(this); 107 | refreshLayout.setEnableAutoLoadmore (true); 108 | MaterialHeader mMaterialHeader = (MaterialHeader) refreshLayout.getRefreshHeader (); 109 | refreshLayout.autoRefresh (); 110 | verifyStoragePermissions(BookDetailActivity.this); 111 | } 112 | 113 | private void beginDownload(){ 114 | remindStoragePermissions(BookDetailActivity.this); 115 | if (hasPermissions) { 116 | nowNum = 0; 117 | GetDownloadInfoTask gdi = new GetDownloadInfoTask (du); 118 | gdi.setOnDataFinishedListener (this); 119 | gdi.execute (url); 120 | }else { 121 | Snackbar.make (toolbar,"未授予存储权限,无法下载书籍!",Snackbar.LENGTH_LONG).show (); 122 | verifyStoragePermissions (BookDetailActivity.this); 123 | } 124 | } 125 | 126 | @Override 127 | public void onClick(View view) { 128 | switch (view.getId()){ 129 | case R.id.dl_txt: 130 | whatGenerate = 0; 131 | beginDownload(); 132 | break; 133 | case R.id.dl_epub: 134 | whatGenerate = 1; 135 | beginDownload(); 136 | break; 137 | case R.id.dl_nob: 138 | whatGenerate = 2; 139 | beginDownload(); 140 | break; 141 | case R.id.bdCover: 142 | Intent intent = new Intent (BookDetailActivity.this,ChangeCoverActivity.class); 143 | intent.putExtra ("str",searchStr); 144 | startActivityForResult(intent, 0); 145 | } 146 | } 147 | 148 | public void verifyStoragePermissions(Activity activity) { 149 | 150 | try { 151 | //检测是否有写的权限 152 | int permission = ActivityCompat.checkSelfPermission(activity, 153 | "android.permission.WRITE_EXTERNAL_STORAGE"); 154 | if (permission != PackageManager.PERMISSION_GRANTED) { 155 | // 没有写的权限,去申请写的权限,会弹出对话框 156 | ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE); 157 | } 158 | 159 | } catch (Exception e) { 160 | e.printStackTrace(); 161 | } 162 | } 163 | 164 | public void remindStoragePermissions(Activity activity) { 165 | 166 | try { 167 | //检测是否有写的权限 168 | int permission = ActivityCompat.checkSelfPermission(activity, 169 | "android.permission.WRITE_EXTERNAL_STORAGE"); 170 | if (permission != PackageManager.PERMISSION_GRANTED) { 171 | // 没有写的权限,去申请写的权限,会弹出对话框 172 | Snackbar.make (toolbar,"未授予存储权限,将无法下载书籍!",Snackbar.LENGTH_LONG).show (); 173 | }else { 174 | hasPermissions = true; 175 | } 176 | } catch (Exception e) { 177 | e.printStackTrace(); 178 | } 179 | } 180 | 181 | @Override 182 | public void onDataSuccessfully(Object data) { 183 | 184 | } 185 | 186 | @Override 187 | public void onDataSuccessfully(DownloadDetails downloadDetails) { 188 | this.downloadDetails = downloadDetails; 189 | chapterIDs = downloadDetails.getChapterIDs (); 190 | allNum = chapterIDs.size (); 191 | du.setAllNum (allNum); 192 | for (int[] integers: SplitUtil.splitChaIDsByNum (downloadDetails.getChapterIDs (),3)){ 193 | new DownloadTask (downloadDetails.getBookID (), 194 | ch, 195 | du, 196 | allNum, 197 | nowNum, 198 | whatGenerate, 199 | this) 200 | .executeOnExecutor (THREAD_POOL_EXECUTOR,integers); 201 | } 202 | } 203 | 204 | @Override 205 | public void onDataFailed() { 206 | 207 | } 208 | 209 | @Override 210 | public void onDownloadFinishedNum(int num){ 211 | nowNum+=num; 212 | List chapters = new ArrayList<> (); 213 | if (nowNum>=allNum){ 214 | du.setDialogTitle ("正在写出数据……"); 215 | for (int id:chapterIDs){ 216 | chapters.add (ch.get (id)); 217 | } 218 | switch (whatGenerate){ 219 | case 0: 220 | StringBuilder sb = new StringBuilder (); 221 | for (String s:chapters){ 222 | sb.append (s); 223 | } 224 | new OutPutTxtTask (downloadDetails.getBookName (),this).execute (sb.toString ()); 225 | break; 226 | case 1: 227 | new EpubUtils (downloadDetails.getBookID (), 228 | downloadDetails.getBookName (), 229 | downloadDetails.getBookAuthor (), 230 | downloadDetails.getBookCoverURL (), 231 | chapters, 232 | downloadDetails.getTitles (), 233 | this).generateEpub (); 234 | break; 235 | case 2: 236 | NOBKit.Builder builder = new NOBKit 237 | .Builder (Environment.getExternalStorageDirectory().getPath()+"/99lib/Nob") 238 | .cover (cover_bit) 239 | .metadata (downloadDetails.getBookName (), downloadDetails.getBookAuthor ().replace ("作者: ","")) 240 | .putChapters (downloadDetails.getTitles (),chapters); 241 | isGenerOk (1); 242 | builder.build (downloadDetails.getBookName ()); 243 | break; 244 | } 245 | } 246 | } 247 | 248 | @Override 249 | public boolean onOptionsItemSelected(MenuItem item) { 250 | if(item.getItemId()==android.R.id.home){ 251 | finish (); 252 | return true; 253 | } 254 | return super.onOptionsItemSelected(item); 255 | } 256 | 257 | public void scanFile() { 258 | final Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); 259 | final Uri contentUri = Uri.fromFile(new File (Environment.getExternalStorageDirectory().getPath()+"/99lib/Nob/"+downloadDetails.getBookName ()+".nob")); 260 | scanIntent.setData(contentUri); 261 | sendBroadcast(scanIntent); 262 | } 263 | 264 | @Override 265 | public void isGenerOk(int i) { 266 | if (i==1){ 267 | du.concelDialog (); 268 | scanFile (); 269 | Snackbar.make (toolbar,"书籍下载完毕!",Snackbar.LENGTH_LONG).show (); 270 | } 271 | } 272 | 273 | @Override 274 | public void GetFailed() { 275 | refreshLayout.finishRefresh (false); 276 | Snackbar.make (toolbar,"数据获取失败,请检查网络连接或重试",Snackbar.LENGTH_LONG).show (); 277 | } 278 | 279 | @Override 280 | public void GetSuccessful(String...strings) { 281 | tv_title.setText (strings[0]); 282 | tv_intro.setText (strings[1]); 283 | tv_detail.setText (strings[2]); 284 | searchStr = strings[4]; 285 | Glide.with(BookDetailActivity.this).load(strings[3]).into(iv_cover); 286 | new SetCoverTask (new Interface.GetCover () { 287 | @Override 288 | public void GetCoverOK(Bitmap bitmap) { 289 | cover_bit = bitmap; 290 | iv_cover.setImageBitmap (bitmap); 291 | } 292 | }).execute (strings[3]); 293 | cv.setVisibility (View.VISIBLE); 294 | cv.bringToFront (); 295 | refreshLayout.finishRefresh (500); 296 | } 297 | 298 | GetBookDetailTask gbd; 299 | 300 | @Override 301 | public void onRefresh(RefreshLayout refreshlayout) { 302 | gbd = new GetBookDetailTask (this); 303 | gbd.execute (url); 304 | } 305 | 306 | @Override 307 | public void outPutFailed() { 308 | 309 | } 310 | 311 | @Override 312 | public void outPutSuccess(int i) { 313 | switch (i){ 314 | case 1: 315 | du.concelDialog (); 316 | Snackbar.make (toolbar,"书籍下载完毕!",Snackbar.LENGTH_LONG).show (); 317 | break; 318 | } 319 | } 320 | 321 | @Override 322 | protected void onDestroy(){ 323 | if (gbd != null && gbd.getStatus() != AsyncTask.Status.FINISHED) 324 | gbd.cancel(true); 325 | super.onDestroy(); 326 | } 327 | 328 | @Override 329 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 330 | super.onActivityResult(requestCode, resultCode, data); 331 | tv_dlNob.setOnClickListener (null); 332 | tv_dlNob.setText ("请稍后"); 333 | if (data!=null) { 334 | Glide.with (BookDetailActivity.this).load (data.getStringExtra ("url")).into (iv_cover); 335 | new SetCoverTask (new Interface.GetCover () { 336 | @Override 337 | public void GetCoverOK(Bitmap bitmap) { 338 | cover_bit = bitmap; 339 | tv_dlNob.setText ("Nob下载"); 340 | tv_dlNob.setOnClickListener (BookDetailActivity.this); 341 | } 342 | }).execute (data.getStringExtra ("url")); 343 | }else { 344 | tv_dlNob.setText ("Nob下载"); 345 | tv_dlNob.setOnClickListener (BookDetailActivity.this); 346 | } 347 | } 348 | } 349 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/CategoryActivity.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.design.widget.FloatingActionButton; 6 | import android.support.design.widget.Snackbar; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.LinearLayoutManager; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.support.v7.widget.Toolbar; 11 | import android.view.MenuItem; 12 | import android.view.View; 13 | 14 | import com.scwang.smartrefresh.header.MaterialHeader; 15 | import com.scwang.smartrefresh.layout.api.RefreshLayout; 16 | import com.scwang.smartrefresh.layout.listener.OnLoadmoreListener; 17 | import com.scwang.smartrefresh.layout.listener.OnRefreshListener; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | import cc.zsakvo.ninecswd.classes.BookList; 23 | import cc.zsakvo.ninecswd.listener.Interface; 24 | import cc.zsakvo.ninecswd.listener.ItemClickListener; 25 | import cc.zsakvo.ninecswd.task.GetCategoryListTask; 26 | import cc.zsakvo.ninecswd.adapter.ListAdapter; 27 | 28 | 29 | public class CategoryActivity extends AppCompatActivity implements ItemClickListener,View.OnClickListener,OnRefreshListener,OnLoadmoreListener,Interface.GetCategoryList{ 30 | 31 | private RecyclerView recyclerView; 32 | Toolbar toolbar; 33 | FloatingActionButton fab; 34 | private List listDetails = new ArrayList<>(); 35 | ListAdapter adapter; 36 | int page =1; 37 | String searchStr; 38 | Boolean isInit; 39 | int totalPage = 1; 40 | String str; 41 | String baseUrl = "http://www.99lib.net/book/index.php?type="; 42 | String Url; 43 | RefreshLayout refreshLayout; 44 | 45 | @Override 46 | protected void onCreate(Bundle savedInstanceState) { 47 | super.onCreate(savedInstanceState); 48 | setContentView(R.layout.activity_category); 49 | this.str = getIntent().getStringExtra("url"); 50 | toolbar = (Toolbar)findViewById(R.id.c_toolBar); 51 | // fab = (FloatingActionButton)findViewById(R.id.c_fab); 52 | toolbar.setTitle(str); 53 | // fab.setOnClickListener(this); 54 | setSupportActionBar(toolbar); 55 | toolbar.setTitle("分类目录"); 56 | if (getSupportActionBar() != null) { 57 | getSupportActionBar ().setDisplayHomeAsUpEnabled (true); 58 | } 59 | recyclerView = (RecyclerView)findViewById(R.id.c_novel_list); 60 | LinearLayoutManager layoutManager = new LinearLayoutManager(this); 61 | recyclerView.setLayoutManager(layoutManager); 62 | adapter = new ListAdapter (listDetails); 63 | adapter.setOnItemClickListener(CategoryActivity.this); 64 | recyclerView.setAdapter(adapter); 65 | refreshLayout = (RefreshLayout)findViewById(R.id.c_refreshLayout); 66 | refreshLayout.setOnRefreshListener (this); 67 | refreshLayout.setOnLoadmoreListener (this); 68 | MaterialHeader mMaterialHeader = (MaterialHeader) refreshLayout.getRefreshHeader (); 69 | refreshLayout.autoRefresh (); 70 | } 71 | 72 | private void initView(){ 73 | 74 | } 75 | 76 | @Override 77 | public void onResume(){ 78 | super.onResume(); 79 | } 80 | 81 | private void searchBook(){ 82 | toolbar.setTitle(str); 83 | Url = baseUrl+str+"&page="+page; 84 | GetCategoryListTask gct = new GetCategoryListTask (totalPage, listDetails, adapter,this); 85 | gct.execute (Url,page); 86 | } 87 | 88 | @Override 89 | public void onItemClick(View view,final int position){ 90 | String url = String.valueOf(listDetails.get(position).getBook_url()); 91 | Intent intent = new Intent(CategoryActivity.this, BookDetailActivity.class); 92 | intent.putExtra("url", url); 93 | startActivity(intent); 94 | } 95 | 96 | @Override 97 | public void onClick(View view) { 98 | switch (view.getId()){ 99 | // case R.id.c_fab: 100 | // adapter = new ListAdapter(listDetails); 101 | // adapter.setOnItemClickListener(CategoryActivity.this); 102 | // recyclerView.setAdapter(adapter); 103 | // break; 104 | default: 105 | break; 106 | } 107 | } 108 | 109 | @Override 110 | public boolean onOptionsItemSelected(MenuItem item) { 111 | if(item.getItemId()==android.R.id.home){ 112 | finish (); 113 | return true; 114 | } 115 | return super.onOptionsItemSelected(item); 116 | } 117 | 118 | @Override 119 | public void onLoadmore(RefreshLayout refreshlayout) { 120 | page++; 121 | searchBook(); 122 | } 123 | 124 | @Override 125 | public void onRefresh(RefreshLayout refreshlayout) { 126 | listDetails.clear (); 127 | recyclerView.setAdapter (adapter); 128 | page = 1; 129 | searchBook(); 130 | } 131 | 132 | @Override 133 | public void GetOK(List listDetails) { 134 | this.listDetails.addAll (listDetails); 135 | adapter.notifyDataSetChanged(); 136 | if (refreshLayout.isRefreshing ()){ 137 | refreshLayout.finishRefresh (500); 138 | }else { 139 | refreshLayout.finishLoadmore (500); 140 | } 141 | } 142 | 143 | @Override 144 | public void GetFailed() { 145 | refreshLayout.finishLoadmoreWithNoMoreData (); 146 | if (refreshLayout.isRefreshing ()){ 147 | refreshLayout.finishRefresh (false); 148 | }else { 149 | refreshLayout.finishLoadmore (false); 150 | } 151 | Snackbar.make (recyclerView,"数据获取失败,请检查网络连接或重试",Snackbar.LENGTH_LONG).show (); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/ChangeCoverActivity.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd; 2 | 3 | import android.content.DialogInterface; 4 | import android.content.Intent; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v7.app.AlertDialog; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.os.Bundle; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.support.v7.widget.StaggeredGridLayoutManager; 11 | import android.support.v7.widget.Toolbar; 12 | import android.util.Log; 13 | import android.view.Menu; 14 | import android.view.MenuItem; 15 | import android.view.View; 16 | import android.widget.Toast; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import cc.zsakvo.ninecswd.adapter.CoverListAdapter; 22 | import cc.zsakvo.ninecswd.listener.Interface; 23 | import cc.zsakvo.ninecswd.listener.ItemClickListener; 24 | import cc.zsakvo.ninecswd.task.GetCoversTask; 25 | 26 | public class ChangeCoverActivity extends AppCompatActivity implements Interface.GetCoverUrls,ItemClickListener{ 27 | 28 | // public enum Engine { 29 | // Bing, 30 | // Baidu, 31 | // Sogou 32 | // } 33 | 34 | Toolbar toolbar; 35 | String[] engine = new String[]{"Bing","Baidu"}; 36 | private String searchStr; 37 | private String searchEngine = "Baidu"; 38 | private RecyclerView recyclerView; 39 | private CoverListAdapter adapter; 40 | private List list = new ArrayList<> (); 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | super.onCreate (savedInstanceState); 45 | setContentView (R.layout.activity_change_cover); 46 | toolbar = (Toolbar)findViewById (R.id.ccToolBar); 47 | toolbar.setTitle ("选择封面"); 48 | recyclerView = (RecyclerView)findViewById (R.id.cover_recycler); 49 | setSupportActionBar (toolbar); 50 | if (getSupportActionBar ()!=null){ 51 | getSupportActionBar ().setDisplayHomeAsUpEnabled (true); 52 | } 53 | searchStr = getIntent ().getStringExtra ("str"); 54 | StaggeredGridLayoutManager layoutManager = new 55 | StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL); 56 | recyclerView.setLayoutManager(layoutManager); 57 | adapter = new CoverListAdapter (list); 58 | adapter.setOnItemClickListener (this); 59 | recyclerView.setAdapter(adapter); 60 | new GetCoversTask (this).execute (searchStr,searchEngine); 61 | } 62 | 63 | @Override 64 | public boolean onCreateOptionsMenu(Menu menu){ 65 | getMenuInflater().inflate(R.menu.select_engine_menu,menu); 66 | return true; 67 | } 68 | 69 | @Override 70 | public boolean onOptionsItemSelected(final MenuItem item) { 71 | if(item.getItemId()==android.R.id.home){ 72 | finish (); 73 | return true; 74 | } 75 | switch (item.getItemId ()){ 76 | case android.R.id.home: 77 | finish (); 78 | break; 79 | case R.id.select_engine: 80 | AlertDialog dialog = new AlertDialog.Builder(this).setTitle("选择搜索引擎") 81 | .setItems(engine, new DialogInterface.OnClickListener () { 82 | @Override 83 | public void onClick(DialogInterface dialog, int which) { 84 | list.clear (); 85 | switch (engine[which]){ 86 | case "Bing": 87 | item.setIcon (R.drawable.ic_bing); 88 | searchEngine = "Bing"; 89 | new GetCoversTask (ChangeCoverActivity.this).execute (searchStr,searchEngine); 90 | break; 91 | case "Baidu": 92 | item.setIcon (R.drawable.ic_baidu); 93 | searchEngine = "Baidu"; 94 | new GetCoversTask (ChangeCoverActivity.this).execute (searchStr,searchEngine); 95 | break; 96 | // case "Sogou": 97 | // item.setIcon (R.drawable.ic_bing); 98 | // searchEngine = "Sogou"; 99 | // new GetCoversTask (ChangeCoverActivity.this).execute (searchStr,searchEngine); 100 | // break; 101 | default: 102 | break; 103 | } 104 | } 105 | }).create(); 106 | dialog.show(); 107 | break; 108 | } 109 | return super.onOptionsItemSelected(item); 110 | } 111 | 112 | @Override 113 | public void GetCoverUrls(List list) { 114 | if (list.size ()==0){ 115 | Snackbar.make (recyclerView,"没有找到合适的图片!",Snackbar.LENGTH_LONG).show (); 116 | }else { 117 | this.list.addAll (list); 118 | adapter.notifyDataSetChanged (); 119 | } 120 | } 121 | 122 | @Override 123 | public void GetCoverUrlsFailed() { 124 | 125 | } 126 | 127 | @Override 128 | public void onItemClick(View view, int postion) { 129 | Intent intent = new Intent (); 130 | intent.putExtra ("url",list.get (postion)); 131 | setResult(1, intent); 132 | finish(); 133 | } 134 | 135 | @Override 136 | public void onBackPressed(){ 137 | super.onBackPressed (); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/MainActivity.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.design.widget.TabLayout; 7 | import android.support.v4.view.ViewPager; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.support.v7.widget.Toolbar; 10 | import android.view.KeyEvent; 11 | import android.view.Menu; 12 | import android.view.MenuItem; 13 | 14 | import com.github.nukc.stateview.StateView; 15 | 16 | import cc.zsakvo.ninecswd.adapter.MyViewpagerAdapter; 17 | import cc.zsakvo.ninecswd.fragment.ArticleFragment; 18 | import cc.zsakvo.ninecswd.fragment.BaseFragment; 19 | import cc.zsakvo.ninecswd.fragment.BookStoreFragment; 20 | import cc.zsakvo.ninecswd.fragment.CategoryFragment; 21 | import km.lmy.searchview.SearchView; 22 | 23 | 24 | public class MainActivity extends AppCompatActivity{ 25 | TabLayout tabLayout; 26 | ViewPager viewPager; 27 | String[] mTitle; 28 | BaseFragment[] mBaseFragment; 29 | Toolbar toolbar; 30 | SearchView searchView; 31 | MyViewpagerAdapter mMyViewpagerAdapter; 32 | private long firstClick; 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.activity_main); 38 | toolbar = (Toolbar)findViewById(R.id.toolBar); 39 | searchView=(SearchView)findViewById(R.id.searchView); 40 | setSupportActionBar(toolbar); 41 | initView(); 42 | initDatas(); 43 | initListener(); 44 | } 45 | 46 | 47 | public boolean onCreateOptionsMenu(Menu menu){ 48 | getMenuInflater().inflate(R.menu.main_menu,menu); 49 | return true; 50 | } 51 | 52 | @Override 53 | public boolean onOptionsItemSelected(MenuItem item){ 54 | switch (item.getItemId()){ 55 | case R.id.m_search: 56 | startActivity(new Intent(MainActivity.this,SearchActivity.class)); 57 | break; 58 | // case R.id.m_setting: 59 | // Snackbar.make(toolbar,"设置",Snackbar.LENGTH_LONG).show(); 60 | // break; 61 | // case R.id.m_about: 62 | // Snackbar.make(toolbar,"关于程序",Snackbar.LENGTH_LONG).show(); 63 | // StateView mStateView = StateView.inject(this); 64 | // mStateView.setRetryResource (R.layout.layout_retry); 65 | // break; 66 | } 67 | return true; 68 | } 69 | 70 | private void initView() { 71 | tabLayout = (TabLayout) findViewById(R.id.tabLayout); 72 | viewPager = (ViewPager) findViewById(R.id.vp_content); 73 | } 74 | 75 | private void initDatas() { 76 | 77 | //为标题赋值 78 | mTitle = new String[]{ 79 | "书库", 80 | "分类", 81 | "文库" 82 | }; 83 | mBaseFragment = new BaseFragment[]{ 84 | new BookStoreFragment(), 85 | new CategoryFragment (), 86 | new ArticleFragment() 87 | }; 88 | 89 | setTabAndViewPager(); 90 | } 91 | 92 | private void setTabAndViewPager() { 93 | mMyViewpagerAdapter = new MyViewpagerAdapter(getSupportFragmentManager(),mTitle); 94 | viewPager.setAdapter(mMyViewpagerAdapter); 95 | viewPager.setOffscreenPageLimit(0); 96 | tabLayout.setupWithViewPager(viewPager,true); 97 | } 98 | 99 | private void initListener() { 100 | 101 | } 102 | 103 | @Override 104 | public boolean onKeyDown(int keyCode, KeyEvent event) { 105 | // TODO Auto-generated method stub 106 | if(keyCode== KeyEvent.KEYCODE_BACK){ 107 | if(System.currentTimeMillis()-firstClick>2000){ 108 | firstClick=System.currentTimeMillis(); 109 | Snackbar.make(toolbar,"再按一次退出",Snackbar.LENGTH_LONG).show(); 110 | }else{ 111 | System.exit(0); 112 | } 113 | return true; 114 | } 115 | return false; 116 | } 117 | } -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/SearchActivity.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd; 2 | 3 | import android.content.Intent; 4 | import android.support.design.widget.FloatingActionButton; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.os.Bundle; 8 | import android.support.v7.widget.LinearLayoutManager; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.support.v7.widget.Toolbar; 11 | import android.util.Log; 12 | import android.view.Menu; 13 | import android.view.MenuItem; 14 | import android.view.View; 15 | 16 | import com.github.nukc.stateview.StateView; 17 | import com.scwang.smartrefresh.header.MaterialHeader; 18 | import com.scwang.smartrefresh.layout.api.RefreshLayout; 19 | import com.scwang.smartrefresh.layout.listener.OnLoadmoreListener; 20 | import com.scwang.smartrefresh.layout.listener.OnRefreshListener; 21 | 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | import cc.zsakvo.ninecswd.classes.BookList; 26 | import cc.zsakvo.ninecswd.listener.Interface; 27 | import cc.zsakvo.ninecswd.listener.ItemClickListener; 28 | import cc.zsakvo.ninecswd.task.GetSearchListTask; 29 | import cc.zsakvo.ninecswd.adapter.ListAdapter; 30 | import km.lmy.searchview.SearchView; 31 | 32 | 33 | public class SearchActivity extends AppCompatActivity implements ItemClickListener,View.OnClickListener,Interface.GetSearch,OnRefreshListener,OnLoadmoreListener{ 34 | 35 | private RecyclerView recyclerView; 36 | private StateView mStateView; 37 | SearchView searchView; 38 | Toolbar toolbar; 39 | FloatingActionButton fab; 40 | private List listDetails = new ArrayList<>(); 41 | ListAdapter adapter; 42 | int page; 43 | String searchStr; 44 | Boolean isInit; 45 | int totalPage = 1; 46 | RefreshLayout refreshLayout; 47 | 48 | @Override 49 | protected void onCreate(Bundle savedInstanceState) { 50 | super.onCreate(savedInstanceState); 51 | setContentView(R.layout.activity_search); 52 | toolbar = (Toolbar)findViewById(R.id.s_toolBar); 53 | searchView = (SearchView)findViewById(R.id.s_searchView); 54 | // fab = (FloatingActionButton)findViewById(R.id.s_fab); 55 | // fab.setOnClickListener(this); 56 | setSupportActionBar(toolbar); 57 | toolbar.setTitle("搜索书籍"); 58 | setSupportActionBar(toolbar); 59 | if (getSupportActionBar() != null) { 60 | getSupportActionBar ().setDisplayHomeAsUpEnabled (true); 61 | } 62 | // mStateView = StateView.inject(findViewById (R.id.coord)); 63 | recyclerView = (RecyclerView)findViewById(R.id.s_novel_list); 64 | LinearLayoutManager layoutManager = new LinearLayoutManager(this); 65 | recyclerView.setLayoutManager(layoutManager); 66 | recyclerView.removeAllViewsInLayout(); 67 | adapter = new ListAdapter (listDetails); 68 | adapter.setOnItemClickListener(SearchActivity.this); 69 | recyclerView.setAdapter(adapter); 70 | refreshLayout = (RefreshLayout)findViewById(R.id.s_refreshLayout); 71 | refreshLayout.setOnRefreshListener(this); 72 | refreshLayout.setOnLoadmoreListener(this); 73 | MaterialHeader mMaterialHeader = (MaterialHeader) refreshLayout.getRefreshHeader (); 74 | searchView.defaultState (SearchView.OPEN); 75 | } 76 | 77 | private void initView(){ 78 | 79 | } 80 | 81 | @Override 82 | public void onResume(){ 83 | super.onResume(); 84 | initSearchView(); 85 | } 86 | 87 | @Override 88 | public boolean onCreateOptionsMenu(Menu menu){ 89 | getMenuInflater().inflate(R.menu.search_menu,menu); 90 | return true; 91 | } 92 | 93 | @Override 94 | public boolean onPrepareOptionsMenu(Menu menu){ 95 | // searchView.open (); 96 | return true; 97 | } 98 | 99 | 100 | @Override 101 | public boolean onOptionsItemSelected(MenuItem item){ 102 | switch (item.getItemId()){ 103 | case R.id.s_search: 104 | searchView.autoOpenOrClose(); 105 | break; 106 | case android.R.id.home: 107 | finish (); 108 | break; 109 | } 110 | return true; 111 | } 112 | 113 | private void initSearchView(){ 114 | searchView.setHintText ("请输入关键字,如 人间椅子"); 115 | // searchView.setSearchEditText ("我的"); 116 | searchView.setHistoryItemClickListener(new SearchView.OnHistoryItemClickListener() { 117 | @Override 118 | public void onClick(String historyStr, int position) { 119 | searchView.close(); 120 | searchStr = historyStr; 121 | page = 1; 122 | isInit = true; 123 | onRefresh (refreshLayout); 124 | } 125 | }); 126 | 127 | //设置软键盘搜索按钮点击事件 128 | searchView.setOnSearchActionListener(new SearchView.OnSearchActionListener() { 129 | @Override 130 | public void onSearchAction(String searchText) { 131 | searchView.close(); 132 | searchView.addOneHistory(searchText); 133 | page = 1; 134 | isInit = true; 135 | searchStr = searchText; 136 | onRefresh (refreshLayout); 137 | } 138 | }); 139 | } 140 | 141 | private Boolean canSearch(String value) { 142 | Boolean hasEng=false; 143 | Boolean hasChi=false; 144 | Boolean result=false; 145 | int valueLength = 0; 146 | String chinese = "[\u0391-\uFFE5]"; 147 | /* 获取字段值的长度,如果含中文字符,则每个中文字符长度为2,否则为1 */ 148 | for (int i = 0; i < value.length(); i++) { 149 | /* 获取一个字符 */ 150 | String temp = value.substring(i, i + 1); 151 | /* 判断是否为中文字符 */ 152 | if (temp.matches(chinese)) { 153 | /* 中文字符长度为2 */ 154 | valueLength += 2; 155 | hasChi = true; 156 | } else { 157 | /* 其他字符长度为1 */ 158 | valueLength += 1; 159 | hasEng = true; 160 | } 161 | } 162 | if (hasChi&&hasEng){ 163 | result = true; 164 | }else if (valueLength>=4){ 165 | result = true; 166 | } 167 | return result; 168 | } 169 | 170 | private void searchBook(){ 171 | if (!canSearch(searchStr)){ 172 | Snackbar.make(toolbar,"搜索关键字不得少于2个中文或4个英文!",Snackbar.LENGTH_LONG).show(); 173 | return; 174 | } 175 | toolbar.setTitle("搜索:"+searchStr); 176 | String url = "http://www.99lib.net/book/search.php?keyword="+searchStr+"&page="+page; 177 | GetSearchListTask gst = new GetSearchListTask (this); 178 | gst.execute (url,page); 179 | } 180 | 181 | @Override 182 | public void onBackPressed(){ 183 | if (searchView.isOpen()){ 184 | searchView.close(); 185 | if (listDetails.size ()==0){ 186 | super.onBackPressed (); 187 | } 188 | }else { 189 | super.onBackPressed(); 190 | } 191 | } 192 | 193 | @Override 194 | public void onItemClick(View view,final int position){ 195 | String url = String.valueOf(listDetails.get(position).getBook_url()); 196 | Intent intent = new Intent(SearchActivity.this, BookDetailActivity.class); 197 | intent.putExtra("url", url); 198 | startActivity(intent); 199 | } 200 | 201 | @Override 202 | public void onClick(View view) { 203 | switch (view.getId()){ 204 | // case R.id.s_fab: 205 | // adapter = new ListAdapter(listDetails); 206 | // adapter.setOnItemClickListener(SearchActivity.this); 207 | // recyclerView.setAdapter(adapter); 208 | // break; 209 | default: 210 | break; 211 | } 212 | } 213 | 214 | @Override 215 | public void GetOK(List listDetails,int totalPages) { 216 | this.listDetails.addAll (listDetails); 217 | if (totalPages!=0) { 218 | this.totalPage = totalPages; 219 | } 220 | adapter.notifyDataSetChanged(); 221 | if (refreshLayout.isRefreshing ()){ 222 | refreshLayout.finishRefresh (500); 223 | }else { 224 | refreshLayout.finishLoadmore (500); 225 | } 226 | } 227 | 228 | @Override 229 | public void GetFailed() { 230 | refreshLayout.finishLoadmoreWithNoMoreData (); 231 | if (refreshLayout.isRefreshing ()){ 232 | refreshLayout.finishRefresh (false); 233 | }else { 234 | refreshLayout.finishLoadmore (false); 235 | } 236 | Snackbar.make (recyclerView,"数据获取失败,请检查网络连接或换个关键词~",Snackbar.LENGTH_LONG).show (); 237 | } 238 | 239 | @Override 240 | public void onLoadmore(RefreshLayout refreshlayout) { 241 | Log.e ("onLoadmore: ",page+"ppp"+totalPage ); 242 | if (page>=totalPage){ 243 | refreshLayout.finishLoadmoreWithNoMoreData (); 244 | Snackbar.make (recyclerView,"已经是最后一页了!",Snackbar.LENGTH_LONG).show (); 245 | }else { 246 | page++; 247 | searchBook(); 248 | } 249 | } 250 | 251 | @Override 252 | public void onRefresh(RefreshLayout refreshlayout) { 253 | page = 1; 254 | listDetails.clear (); 255 | recyclerView.setAdapter (adapter); 256 | refreshlayout.resetNoMoreData (); 257 | searchBook(); 258 | } 259 | 260 | 261 | } 262 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/adapter/ArticleAdapter.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.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 | 10 | import java.util.List; 11 | 12 | import cc.zsakvo.ninecswd.R; 13 | import cc.zsakvo.ninecswd.classes.ArticleList; 14 | import cc.zsakvo.ninecswd.listener.ItemClickListener; 15 | 16 | /** 17 | * Created by akvo on 2018/2/19. 18 | */ 19 | 20 | public class ArticleAdapter extends RecyclerView.Adapter{ 21 | 22 | private List articleList; 23 | private ItemClickListener mItemClickListener; 24 | 25 | public ArticleAdapter(List articleList){ 26 | this.articleList = articleList; 27 | } 28 | 29 | public void setOnItemClickListener(ItemClickListener listener){ 30 | this.mItemClickListener = listener; 31 | } 32 | 33 | @Override 34 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 35 | View view = LayoutInflater.from(parent.getContext()) 36 | .inflate(R.layout.articlelist,parent,false); 37 | ViewHolder holder = new ViewHolder(view,mItemClickListener); 38 | return holder; 39 | } 40 | 41 | @Override 42 | public void onBindViewHolder(ViewHolder holder, int position) { 43 | ArticleList listDetail = this.articleList.get(position); 44 | holder.tv_article_name.setText(listDetail.getArticleName()); 45 | holder.tv_article_intro.setText(listDetail.getArticleAuthor()); 46 | } 47 | 48 | @Override 49 | public int getItemCount() { 50 | return articleList.size(); 51 | } 52 | 53 | static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ 54 | private ItemClickListener mClickListener; 55 | TextView tv_article_name; 56 | TextView tv_article_intro; 57 | 58 | public ViewHolder(View view,ItemClickListener clickListener){ 59 | super(view); 60 | this.mClickListener = clickListener; 61 | view.findViewById(R.id.alist).setOnClickListener(this); 62 | tv_article_name = view.findViewById(R.id.alist_name); 63 | tv_article_intro = view.findViewById(R.id.alist_intro); 64 | } 65 | 66 | @Override 67 | public void onClick(View v) { 68 | switch (v.getId()){ 69 | case R.id.alist: 70 | if(mClickListener != null){ 71 | mClickListener.onItemClick(v,getAdapterPosition()); 72 | } 73 | break; 74 | default: 75 | break; 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/adapter/CategoryAdapter.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.adapter; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.util.DisplayMetrics; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | 11 | import cc.zsakvo.ninecswd.R; 12 | import cc.zsakvo.ninecswd.listener.ItemClickListener; 13 | 14 | /** 15 | * Created by akvo on 2018/2/18. 16 | */ 17 | 18 | public class CategoryAdapter extends RecyclerView.Adapter{ 19 | 20 | private String[] categorys; 21 | private ItemClickListener mItemClickListener; 22 | 23 | @Override 24 | public CategoryAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 25 | View view = LayoutInflater.from(parent.getContext()) 26 | .inflate(R.layout.categorylist,parent,false); 27 | CategoryAdapter.ViewHolder holder = new CategoryAdapter.ViewHolder(view,mItemClickListener); 28 | return holder; 29 | } 30 | 31 | @Override 32 | public void onBindViewHolder(CategoryAdapter.ViewHolder holder, int position) { 33 | String category = this.categorys[position]; 34 | holder.tv.setText(category); 35 | } 36 | 37 | @Override 38 | public int getItemCount() { 39 | return this.categorys.length; 40 | } 41 | 42 | public void setOnItemClickListener(ItemClickListener listener){ 43 | this.mItemClickListener = listener; 44 | } 45 | 46 | public CategoryAdapter(String[] categorys){ 47 | this.categorys = categorys; 48 | } 49 | 50 | static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ 51 | private ItemClickListener mClickListener; 52 | DisplayMetrics dm; 53 | TextView tv; 54 | 55 | public ViewHolder(View view,ItemClickListener clickListener){ 56 | super(view); 57 | this.mClickListener = clickListener; 58 | view.findViewById(R.id.clist).setOnClickListener(this); 59 | dm = view.getContext().getResources().getDisplayMetrics(); 60 | int a = dm.widthPixels; 61 | int b = dm.heightPixels; 62 | tv = (TextView) view.findViewById(R.id.category_t); 63 | tv.setHeight(b/11); 64 | tv.setWidth(a/3); 65 | } 66 | 67 | @Override 68 | public void onClick(View v) { 69 | switch (v.getId()){ 70 | case R.id.clist: 71 | if(mClickListener != null){ 72 | mClickListener.onItemClick(v,getAdapterPosition()); 73 | } 74 | break; 75 | default: 76 | break; 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/adapter/CoverListAdapter.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.adapter; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.util.DisplayMetrics; 5 | import android.util.Log; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.ImageView; 10 | import android.widget.TextView; 11 | 12 | import com.bumptech.glide.Glide; 13 | 14 | import java.util.List; 15 | 16 | import cc.zsakvo.ninecswd.BookDetailActivity; 17 | import cc.zsakvo.ninecswd.R; 18 | import cc.zsakvo.ninecswd.application.MyApplication; 19 | import cc.zsakvo.ninecswd.listener.ItemClickListener; 20 | 21 | /** 22 | * Created by akvo on 2018/3/31. 23 | */ 24 | 25 | public class CoverListAdapter extends RecyclerView.Adapter { 26 | 27 | private ItemClickListener mItemClickListener; 28 | private List cover_url; 29 | 30 | @Override 31 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 32 | View view = LayoutInflater.from(parent.getContext()) 33 | .inflate(R.layout.coverlist,parent,false); 34 | ViewHolder holder = new ViewHolder(view,mItemClickListener); 35 | return holder; 36 | } 37 | 38 | @Override 39 | public void onBindViewHolder(ViewHolder holder, int position) { 40 | String category = this.cover_url.get (position); 41 | try { 42 | Glide.with (MyApplication.getContext ()).load (category).into (holder.iv); 43 | }catch (Exception e){ 44 | Glide.with (MyApplication.getContext ()).load (category).into (holder.iv); 45 | } 46 | } 47 | 48 | 49 | @Override 50 | public int getItemCount() { 51 | return this.cover_url.size (); 52 | } 53 | 54 | public void setOnItemClickListener(ItemClickListener listener){ 55 | this.mItemClickListener = listener; 56 | } 57 | 58 | public CoverListAdapter(List cover_url){ 59 | this.cover_url = cover_url; 60 | } 61 | 62 | static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ 63 | private ItemClickListener mClickListener; 64 | DisplayMetrics dm; 65 | ImageView iv; 66 | 67 | public ViewHolder(View view,ItemClickListener clickListener){ 68 | super(view); 69 | this.mClickListener = clickListener; 70 | view.findViewById(R.id.cover_list).setOnClickListener(this); 71 | dm = view.getContext().getResources().getDisplayMetrics(); 72 | int a = dm.widthPixels; 73 | int b = dm.heightPixels; 74 | iv = (ImageView) view.findViewById(R.id.cover_t); 75 | ViewGroup.LayoutParams para = iv.getLayoutParams(); 76 | float width = (a-96)/3; 77 | para.width = (int)width; 78 | para.height = (int)(width*1.435F); 79 | iv.setLayoutParams (para); 80 | } 81 | 82 | @Override 83 | public void onClick(View v) { 84 | switch (v.getId()){ 85 | case R.id.cover_list: 86 | if(mClickListener != null){ 87 | mClickListener.onItemClick(v,getAdapterPosition()); 88 | } 89 | break; 90 | default: 91 | break; 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/adapter/ListAdapter.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.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 java.util.List; 10 | 11 | import cc.zsakvo.ninecswd.R; 12 | import cc.zsakvo.ninecswd.classes.BookList; 13 | import cc.zsakvo.ninecswd.listener.ItemClickListener; 14 | 15 | 16 | /** 17 | * Created by akvo on 2018/2/9. 18 | */ 19 | 20 | public class ListAdapter extends RecyclerView.Adapter { 21 | 22 | private List novelList; 23 | private ItemClickListener mItemClickListener; 24 | 25 | public void setOnItemClickListener(ItemClickListener listener){ 26 | this.mItemClickListener = listener; 27 | } 28 | 29 | static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ 30 | private ItemClickListener mClickListener; 31 | TextView tv_book_name; 32 | TextView tv_book_intro; 33 | TextView tv_book_detail; 34 | public ViewHolder(View view,ItemClickListener clickListener){ 35 | super(view); 36 | this.mClickListener = clickListener; 37 | view.findViewById(R.id.blist).setOnClickListener(this); 38 | tv_book_name = (TextView)view.findViewById(R.id.blist_name); 39 | tv_book_intro = (TextView)view.findViewById(R.id.blist_intro); 40 | tv_book_detail = (TextView)view.findViewById(R.id.blist_detail); 41 | } 42 | 43 | @Override 44 | public void onClick(View v) { 45 | switch (v.getId()){ 46 | case R.id.blist: 47 | if(mClickListener != null){ 48 | mClickListener.onItemClick(v,getAdapterPosition()); 49 | } 50 | break; 51 | default: 52 | break; 53 | } 54 | } 55 | } 56 | 57 | public ListAdapter(List novelList){ 58 | this.novelList = novelList; 59 | } 60 | 61 | @Override 62 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){ 63 | View view = LayoutInflater.from(parent.getContext()) 64 | .inflate(R.layout.booklist,parent,false); 65 | ViewHolder holder = new ViewHolder(view,mItemClickListener); 66 | return holder; 67 | } 68 | 69 | @Override 70 | public void onBindViewHolder(ViewHolder holder,int position){ 71 | BookList listDetail = this.novelList.get(position); 72 | holder.tv_book_intro.setText(listDetail.getList_intro()); 73 | holder.tv_book_name.setText(listDetail.getList_name()); 74 | holder.tv_book_detail.setText(listDetail.getList_detail()); 75 | } 76 | 77 | @Override 78 | public int getItemCount(){ 79 | return this.novelList.size(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/adapter/MyViewpagerAdapter.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.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 cc.zsakvo.ninecswd.fragment.ArticleFragment; 8 | import cc.zsakvo.ninecswd.fragment.BookStoreFragment; 9 | import cc.zsakvo.ninecswd.fragment.CategoryFragment; 10 | 11 | 12 | public class MyViewpagerAdapter extends FragmentStatePagerAdapter { 13 | 14 | String[] mTabTitles; 15 | 16 | 17 | public MyViewpagerAdapter(FragmentManager fm, String[] titles) { 18 | super(fm); 19 | mTabTitles = titles; 20 | 21 | } 22 | 23 | @Override 24 | public Fragment getItem(int position) { 25 | Fragment fragment = null; 26 | switch(position) { 27 | case 0: 28 | fragment = BookStoreFragment.newInstance(position); 29 | break; 30 | case 1: 31 | fragment = CategoryFragment.newInstance(position); 32 | break; 33 | case 2: 34 | fragment = ArticleFragment.newInstance(position); 35 | break; 36 | case 3: 37 | break; 38 | } 39 | return fragment; 40 | } 41 | 42 | @Override 43 | public int getCount() { 44 | return mTabTitles.length; 45 | } 46 | 47 | @Override 48 | public CharSequence getPageTitle(int position) { 49 | 50 | return mTabTitles[position]; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/application/MyApplication.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.application; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | /** 7 | * Created by akvo on 2018/2/22. 8 | */ 9 | 10 | public class MyApplication extends Application { 11 | private static Context context; 12 | 13 | @Override 14 | public void onCreate() { 15 | super.onCreate (); 16 | context = getApplicationContext (); 17 | } 18 | 19 | public static Context getContext(){ 20 | return context; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/classes/ArticleList.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.classes; 2 | 3 | /** 4 | * Created by akvo on 2018/2/19. 5 | */ 6 | 7 | public class ArticleList { 8 | public String getArticleName() { 9 | return articleName; 10 | } 11 | 12 | public String getArticleAuthor() { 13 | return articleAuthor; 14 | } 15 | 16 | private String articleName; 17 | private String articleAuthor; 18 | 19 | public String getArticleUrl() { 20 | return articleUrl; 21 | } 22 | 23 | private String articleUrl; 24 | public ArticleList(String articleName,String articleAuthor,String articleUrl){ 25 | this.articleName = articleName; 26 | this.articleAuthor = articleAuthor; 27 | this.articleUrl = articleUrl; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/classes/BookDetails.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.classes; 2 | 3 | /** 4 | * Created by akvo on 2018/3/19. 5 | */ 6 | 7 | public class BookDetails { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/classes/BookList.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.classes; 2 | 3 | /** 4 | * Created by akvo on 2018/2/9. 5 | */ 6 | 7 | public class BookList { 8 | private String book_name; 9 | private String book_intro; 10 | private String book_detail; 11 | 12 | public String getBook_url() { 13 | return book_url; 14 | } 15 | 16 | private String book_url; 17 | 18 | public String getList_name() { 19 | return book_name; 20 | } 21 | 22 | public String getList_intro() { 23 | return book_intro; 24 | } 25 | 26 | public String getList_detail() { 27 | return book_detail; 28 | } 29 | 30 | public BookList(String book_name, String book_intro, String book_detail,String book_url){ 31 | this.book_name = book_name; 32 | this.book_intro = book_intro; 33 | this.book_detail = book_detail; 34 | this.book_url = book_url; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/classes/DownloadDetails.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.classes; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by akvo on 2018/3/17. 7 | */ 8 | 9 | public class DownloadDetails { 10 | 11 | public String getBookID() { 12 | return bookID; 13 | } 14 | 15 | public String getBookName() { 16 | return bookName; 17 | } 18 | 19 | public String getBookAuthor() { 20 | return bookAuthor; 21 | } 22 | 23 | public String getBookCoverURL() { 24 | return bookCoverURL; 25 | } 26 | 27 | public List getTitles() { 28 | return titles; 29 | } 30 | 31 | public List getChapters() { 32 | return chapters; 33 | } 34 | 35 | public List getChapterIDs() { 36 | return chapterIDs; 37 | } 38 | 39 | private String bookID; 40 | private String bookName; 41 | private String bookAuthor; 42 | private String bookCoverURL; 43 | private List titles; 44 | 45 | public void setChapters(List chapters) { 46 | this.chapters = chapters; 47 | } 48 | 49 | private List chapters; 50 | private List chapterIDs; 51 | 52 | public DownloadDetails(String bookID,String bookName,String bookAuthor,String bookCoverURL,List titles,List chapterIDs,List chapters){ 53 | this.bookID = bookID; 54 | this.bookName = bookName; 55 | this.bookAuthor = bookAuthor; 56 | this.bookCoverURL = bookCoverURL; 57 | this.titles = titles; 58 | this.chapterIDs = chapterIDs; 59 | this.chapters = chapters; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/fragment/ArticleFragment.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.fragment; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | 11 | import com.github.nukc.stateview.StateView; 12 | import com.scwang.smartrefresh.header.MaterialHeader; 13 | import com.scwang.smartrefresh.layout.api.RefreshLayout; 14 | import com.scwang.smartrefresh.layout.listener.OnLoadmoreListener; 15 | import com.scwang.smartrefresh.layout.listener.OnRefreshListener; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | import cc.zsakvo.ninecswd.ArticleActivity; 21 | import cc.zsakvo.ninecswd.R; 22 | import cc.zsakvo.ninecswd.adapter.ArticleAdapter; 23 | import cc.zsakvo.ninecswd.classes.ArticleList; 24 | import cc.zsakvo.ninecswd.listener.Interface; 25 | import cc.zsakvo.ninecswd.task.GetArticleListTask; 26 | 27 | /** 28 | * Created by akvo on 2018/2/19. 29 | */ 30 | 31 | public class ArticleFragment extends BaseFragment implements View.OnClickListener,OnRefreshListener,OnLoadmoreListener,Interface.GetArticleList{ 32 | 33 | private RecyclerView recyclerView; 34 | private StateView mStateView; 35 | private ArticleAdapter adapter; 36 | private RefreshLayout refreshLayout; 37 | private List listDetails = new ArrayList<>(); 38 | int page = 1; 39 | String baseUrl = "http://www.99lib.net/article/index.php?page="; 40 | int totalPage; 41 | 42 | public static ArticleFragment newInstance(int sectionNumber){ 43 | ArticleFragment fragment = new ArticleFragment(); 44 | Bundle args = new Bundle(); 45 | args.putInt("section_number",sectionNumber); 46 | return fragment; 47 | } 48 | 49 | @Override 50 | public void onClick(View view) { 51 | switch (view.getId()){ 52 | 53 | } 54 | } 55 | 56 | @Override 57 | public void onItemClick(View view, int postion) { 58 | String url = String.valueOf(listDetails.get(postion).getArticleUrl()); 59 | Intent intent = new Intent (getActivity (), ArticleActivity.class); 60 | intent.putExtra ("title",listDetails.get(postion).getArticleName ()); 61 | intent.putExtra ("url",url); 62 | startActivity (intent); 63 | } 64 | 65 | @Override 66 | public View bindLayout(LayoutInflater inflater) { 67 | mRootView = inflater.inflate(R.layout.fragment_article,null); 68 | mStateView = StateView.inject(mRootView, true); 69 | return mRootView; 70 | } 71 | 72 | @Override 73 | public void initView() { 74 | refreshLayout = (RefreshLayout)mRootView.findViewById(R.id.arefreshLayout); 75 | recyclerView = mRootView.findViewById(R.id.nn_article_list); 76 | LinearLayoutManager layoutManager = new LinearLayoutManager(this.getContext()); 77 | recyclerView.setLayoutManager(layoutManager); 78 | adapter = new ArticleAdapter(listDetails); 79 | adapter.setOnItemClickListener(ArticleFragment.this); 80 | recyclerView.setAdapter(adapter); 81 | } 82 | 83 | @Override 84 | protected void initData() { 85 | refreshLayout.setOnRefreshListener (this); 86 | refreshLayout.setOnLoadmoreListener (this); 87 | MaterialHeader mMaterialHeader = (MaterialHeader) refreshLayout.getRefreshHeader (); 88 | refreshLayout.autoRefresh (); 89 | } 90 | 91 | 92 | @Override 93 | public void onLoadmore(RefreshLayout refreshlayout) { 94 | page++; 95 | new GetArticleListTask (this).execute (baseUrl+page); 96 | } 97 | 98 | @Override 99 | public void onRefresh(RefreshLayout refreshlayout) { 100 | page = 1; 101 | listDetails.clear (); 102 | recyclerView.setAdapter (adapter); 103 | new GetArticleListTask (this).execute (baseUrl+page); 104 | } 105 | 106 | @Override 107 | public void GetOK(List listDetails, int totalPages) { 108 | this.listDetails.addAll (listDetails); 109 | this.totalPage = totalPages; 110 | adapter.notifyDataSetChanged(); 111 | if (refreshLayout.isRefreshing ()){ 112 | refreshLayout.finishRefresh (500); 113 | }else { 114 | refreshLayout.finishLoadmore (500); 115 | } 116 | } 117 | 118 | @Override 119 | public void GetFailed() { 120 | refreshLayout.finishLoadmoreWithNoMoreData (); 121 | if (refreshLayout.isRefreshing ()){ 122 | refreshLayout.finishRefresh (false); 123 | }else { 124 | refreshLayout.finishLoadmore (false); 125 | } 126 | Snackbar.make (recyclerView,"数据获取失败,请检查网络连接或重试",Snackbar.LENGTH_LONG).show (); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/fragment/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.fragment; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.NonNull; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import cc.zsakvo.ninecswd.listener.ItemClickListener; 13 | 14 | 15 | public abstract class BaseFragment extends Fragment implements ItemClickListener { 16 | 17 | public Context mContext; 18 | protected View mRootView; 19 | 20 | /** 21 | * 是否为可见状态 22 | */ 23 | protected boolean isVisible; 24 | /** 25 | * 是否初始视图完成 26 | */ 27 | private boolean isPrepared; 28 | 29 | @Override 30 | public void onCreate(@Nullable Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | mContext = getActivity(); 33 | } 34 | 35 | 36 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 37 | mRootView = bindLayout(inflater); 38 | initView(); 39 | return mRootView; 40 | } 41 | 42 | @Override 43 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 44 | 45 | super.onActivityCreated(savedInstanceState); 46 | //这里 初始化view的各控件 数据 47 | isPrepared = true; 48 | lazyLoad(); 49 | 50 | } 51 | 52 | /** 53 | * setUserVisibleHint是在onCreateView之前调用的 54 | * 55 | * @param isVisibleToUser 56 | */ 57 | @Override 58 | public void setUserVisibleHint(boolean isVisibleToUser) { 59 | 60 | super.setUserVisibleHint(isVisibleToUser); 61 | 62 | /** 63 | * 判断是否可见 64 | */ 65 | if(getUserVisibleHint()) { 66 | 67 | isVisible = true; 68 | //执行可见方法-初始化数据之类 69 | onVisible(); 70 | 71 | } else { 72 | 73 | isVisible = false; 74 | //不可见 75 | onInvisible(); 76 | } 77 | 78 | } 79 | 80 | 81 | /** 82 | * 可见做懒加载 83 | */ 84 | private void onVisible() { 85 | lazyLoad(); 86 | } 87 | 88 | /** 89 | * 懒加载 90 | */ 91 | private void lazyLoad() { 92 | /** 93 | * 判断是否可见,或者 初始化view的各控件 94 | */ 95 | if(!isVisible || !isPrepared) { 96 | return; 97 | } 98 | //可见 或者 控件初始化完成 就 加载数据 99 | initData(); 100 | 101 | } 102 | 103 | /** 104 | * 不可见-做一些销毁工作 105 | */ 106 | protected void onInvisible() { 107 | 108 | 109 | } 110 | 111 | /** 112 | * 绑定布局 113 | * 114 | * @param inflater 115 | * @return 116 | */ 117 | public abstract View bindLayout(LayoutInflater inflater); 118 | 119 | /** 120 | * 初始化布局 121 | */ 122 | public abstract void initView(); 123 | 124 | 125 | /** 126 | * 初始化数据 127 | */ 128 | protected abstract void initData(); 129 | } 130 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/fragment/BookStoreFragment.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.fragment; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.design.widget.Snackbar; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | 12 | import com.github.nukc.stateview.StateView; 13 | import com.scwang.smartrefresh.header.MaterialHeader; 14 | import com.scwang.smartrefresh.layout.api.RefreshLayout; 15 | import com.scwang.smartrefresh.layout.listener.OnLoadmoreListener; 16 | import com.scwang.smartrefresh.layout.listener.OnRefreshListener; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import cc.zsakvo.ninecswd.BookDetailActivity; 22 | import cc.zsakvo.ninecswd.R; 23 | import cc.zsakvo.ninecswd.classes.BookList; 24 | import cc.zsakvo.ninecswd.listener.Interface; 25 | import cc.zsakvo.ninecswd.task.GetBookListTask; 26 | 27 | 28 | /** 29 | * Created by akvo on 2018/1/7. 30 | */ 31 | 32 | public class BookStoreFragment extends BaseFragment implements View.OnClickListener,OnRefreshListener,OnLoadmoreListener,Interface.GetBookListFinish{ 33 | private RecyclerView recyclerView; 34 | private StateView mStateView; 35 | private List listDetails = new ArrayList<>(); 36 | cc.zsakvo.ninecswd.adapter.ListAdapter adapter; 37 | // FloatingActionButton fab; 38 | int page = 1; 39 | private RefreshLayout refreshLayout; 40 | private String baseURL = "http://www.99lib.net/book/index.php?page="; 41 | 42 | public BookStoreFragment(){ 43 | 44 | } 45 | 46 | public static BookStoreFragment newInstance(int sectionNumber){ 47 | BookStoreFragment fragment = new BookStoreFragment(); 48 | Bundle args = new Bundle(); 49 | args.putInt("section_number",sectionNumber); 50 | return fragment; 51 | } 52 | 53 | @SuppressLint("InflateParams") 54 | @Override 55 | public View bindLayout(LayoutInflater layoutInflater){ 56 | mRootView = layoutInflater.inflate(R.layout.fragment_99lib,null); 57 | mStateView = StateView.inject(mRootView, true); 58 | return mRootView; 59 | } 60 | 61 | @Override 62 | public void initView() { 63 | recyclerView = mRootView.findViewById(R.id.nn_novel_list); 64 | // fab = (FloatingActionButton)mRootView.findViewById(R.id.fab); 65 | // fab.setOnClickListener(this); 66 | LinearLayoutManager layoutManager = new LinearLayoutManager(this.getContext()); 67 | recyclerView.setLayoutManager(layoutManager); 68 | adapter = new cc.zsakvo.ninecswd.adapter.ListAdapter (listDetails); 69 | adapter.setOnItemClickListener(BookStoreFragment.this); 70 | recyclerView.setAdapter(adapter); 71 | } 72 | 73 | @Override 74 | protected void initData(){ 75 | refreshLayout = (RefreshLayout) mRootView.findViewById (R.id.refreshLayout); 76 | refreshLayout.setOnRefreshListener(this); 77 | refreshLayout.setOnLoadmoreListener (this); 78 | refreshLayout.setEnableAutoLoadmore (true); 79 | MaterialHeader mMaterialHeader = (MaterialHeader) refreshLayout.getRefreshHeader (); 80 | refreshLayout.autoRefresh (); 81 | } 82 | 83 | @Override 84 | public void onItemClick(View view,final int position){ 85 | String url = String.valueOf(listDetails.get(position).getBook_url()); 86 | Intent intent = new Intent(getActivity(), BookDetailActivity.class); 87 | intent.putExtra("url", url); 88 | startActivity(intent); 89 | } 90 | 91 | @Override 92 | public void onClick(View view) { 93 | switch (view.getId()){ 94 | // case R.id.fab: 95 | // recyclerView.setAdapter (adapter); 96 | // break; 97 | } 98 | } 99 | 100 | @Override 101 | public void onRefresh(RefreshLayout refreshlayout) { 102 | page = 1; 103 | listDetails.clear (); 104 | recyclerView.setAdapter (adapter); 105 | new GetBookListTask (BookStoreFragment.this).execute (baseURL+page); 106 | } 107 | 108 | @Override 109 | public void onLoadmore(RefreshLayout refreshlayout) { 110 | page++; 111 | new GetBookListTask (BookStoreFragment.this).execute (baseURL+page); 112 | } 113 | 114 | @Override 115 | public void bookList(List listDetails) { 116 | this.listDetails.addAll (listDetails); 117 | adapter.notifyDataSetChanged (); 118 | if (refreshLayout.isRefreshing ()){ 119 | refreshLayout.finishRefresh (500); 120 | }else { 121 | refreshLayout.finishLoadmore (500); 122 | } 123 | } 124 | 125 | @Override 126 | public void booksGetFailed(){ 127 | refreshLayout.finishLoadmoreWithNoMoreData (); 128 | if (refreshLayout.isRefreshing ()){ 129 | refreshLayout.finishRefresh (500); 130 | }else { 131 | refreshLayout.finishLoadmore (500); 132 | } 133 | Snackbar.make (recyclerView,"数据获取失败,请检查网络连接或重试",Snackbar.LENGTH_LONG).show (); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/fragment/CategoryFragment.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.fragment; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.support.v7.widget.StaggeredGridLayoutManager; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | 11 | import cc.zsakvo.ninecswd.CategoryActivity; 12 | import cc.zsakvo.ninecswd.R; 13 | import cc.zsakvo.ninecswd.adapter.CategoryAdapter; 14 | 15 | /** 16 | * Created by akvo on 2018/2/18. 17 | */ 18 | 19 | public class CategoryFragment extends BaseFragment { 20 | 21 | private RecyclerView recyclerView; 22 | private CategoryAdapter adapter; 23 | String[] categorys = new String[] {"传记回忆","英文读本","杂文随笔","现代小说","言情小说", 24 | "历史小说","侦探推理","惊悚悬疑","网络玄幻","寓言童话","青春都市","社会心理","外国小说" 25 | ,"科幻小说","当代小说","武侠小说","纪实报告","中国历史","世界历史","科普学习" 26 | ,"诗歌戏曲","宗教哲学","文学理论","日语读物","作品集","国学/古籍","战争军事" 27 | ,"政治经济","古典文学","官场小说","轻小说"}; 28 | 29 | public static CategoryFragment newInstance(int sectionNumber){ 30 | CategoryFragment fragment = new CategoryFragment(); 31 | Bundle args = new Bundle(); 32 | args.putInt("section_number",sectionNumber); 33 | return fragment; 34 | } 35 | 36 | @Override 37 | public void onItemClick(View view, int postion) { 38 | String str = categorys[postion]; 39 | Intent intent = new Intent(getActivity(), CategoryActivity.class); 40 | intent.putExtra("url",str); 41 | startActivity(intent); 42 | Snackbar.make(recyclerView,str,Snackbar.LENGTH_LONG).show(); 43 | } 44 | 45 | @Override 46 | public View bindLayout(LayoutInflater inflater) { 47 | mRootView = inflater.inflate(R.layout.fragment_category,null); 48 | return mRootView; 49 | } 50 | 51 | @Override 52 | public void initView() { 53 | // LinearLayoutManager layoutManager = new LinearLayoutManager(this.getContext()); 54 | // System.out.println("aaa"); 55 | } 56 | 57 | @Override 58 | protected void initData() { 59 | recyclerView = mRootView.findViewById(R.id.category_list); 60 | StaggeredGridLayoutManager layoutManager = new 61 | StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL); 62 | recyclerView.setLayoutManager(layoutManager); 63 | adapter = new CategoryAdapter (categorys); 64 | adapter.setOnItemClickListener(CategoryFragment.this); 65 | recyclerView.setAdapter(adapter); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/listener/Interface.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.listener; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | import java.util.List; 6 | 7 | import cc.zsakvo.ninecswd.classes.ArticleList; 8 | import cc.zsakvo.ninecswd.classes.BookList; 9 | 10 | /** 11 | * Created by akvo on 2018/3/19. 12 | */ 13 | 14 | public class Interface { 15 | public interface GetBookListFinish{ 16 | void bookList(List listDetails); 17 | void booksGetFailed(); 18 | } 19 | 20 | public interface GetBookDetailFinish{ 21 | void GetFailed(); 22 | void GetSuccessful(String...strings); 23 | } 24 | 25 | public interface OutPutTxtFinish{ 26 | void outPutFailed(); 27 | void outPutSuccess(int i); 28 | } 29 | 30 | public interface GetCover{ 31 | void GetCoverOK(Bitmap bitmap); 32 | } 33 | 34 | public interface GetCoverUrls{ 35 | void GetCoverUrls(List list); 36 | void GetCoverUrlsFailed(); 37 | } 38 | 39 | public interface GetArticleList{ 40 | void GetOK(List listDetails, int totalPages); 41 | void GetFailed(); 42 | } 43 | 44 | public interface GetArticle{ 45 | void GetResult(Boolean result); 46 | } 47 | 48 | public interface GetCategoryList{ 49 | void GetOK(List listDetails); 50 | void GetFailed(); 51 | } 52 | 53 | public interface GetSearch{ 54 | void GetOK(List listDetails,int totalPages); 55 | void GetFailed(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/listener/ItemClickListener.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.listener; 2 | 3 | import android.view.View; 4 | 5 | /** 6 | * Created by akvo on 2018/2/14. 7 | */ 8 | 9 | public interface ItemClickListener { 10 | void onItemClick(View view, int postion); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/listener/OnDataFinishedListener.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.listener; 2 | 3 | import cc.zsakvo.ninecswd.classes.DownloadDetails; 4 | 5 | /** 6 | * Created by akvo on 2018/2/22. 7 | */ 8 | 9 | public interface OnDataFinishedListener { 10 | public void onDataSuccessfully(Object data); 11 | public void onDataSuccessfully(DownloadDetails data); 12 | public void onDownloadFinishedNum(int num); 13 | public void onDataFailed(); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/phrase/Book.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.phrase; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by akvo on 2018/2/16. 7 | */ 8 | 9 | public class Book { 10 | private String bookID; 11 | 12 | public String getBookID() { 13 | return bookID; 14 | } 15 | 16 | public String getBookName() { 17 | return bookName; 18 | } 19 | 20 | public String getBookAuthor() { 21 | return bookAuthor; 22 | } 23 | 24 | public String getBookCoverURL() { 25 | return bookCoverURL; 26 | } 27 | 28 | public List getChapters() { 29 | return chapters; 30 | } 31 | 32 | public List getTitles() { 33 | return titles; 34 | } 35 | 36 | private String bookName; 37 | private String bookAuthor; 38 | private String bookCoverURL; 39 | private List chapters; 40 | private List titles; 41 | 42 | public Book(String bookID, String bookName, String bookAuthor, String bookCoverURL, List chapters, List titles){ 43 | this.bookID = bookID; 44 | this.bookName = bookName; 45 | this.bookAuthor = bookAuthor; 46 | this.bookCoverURL = bookCoverURL; 47 | this.chapters = chapters; 48 | this.titles = titles; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/phrase/PhraseBookDetail.java: -------------------------------------------------------------------------------- 1 | //package cc.zsakvo.a99demo.phrase; 2 | // 3 | //import android.annotation.SuppressLint; 4 | //import android.os.Handler; 5 | //import android.os.Message; 6 | // 7 | // 8 | //import org.jsoup.Jsoup; 9 | //import org.jsoup.nodes.Document; 10 | //import org.jsoup.nodes.Element; 11 | //import org.jsoup.select.Elements; 12 | // 13 | //import java.io.IOException; 14 | //import java.util.ArrayList; 15 | //import java.util.List; 16 | // 17 | //import SearchActivity; 18 | //import DecodeUtils; 19 | // 20 | ///** 21 | // * Created by akvo on 2018/2/16. 22 | // */ 23 | // 24 | //public class PhraseBookDetail { 25 | // 26 | // String url; 27 | // private String bookID; 28 | // private String bookName; 29 | // private String bookAuthor; 30 | // private String bookCoverURL; 31 | // private List chapters; 32 | // private List titles; 33 | // static Book book; 34 | // 35 | // public PhraseBookDetail(String url){ 36 | // this.url = url; 37 | // } 38 | // public static Book url(String url){ 39 | // new PhraseBookDetail(url).deal(); 40 | // return book; 41 | // } 42 | // 43 | // private void deal(){ 44 | // bookID = url.replace("http://www.99lib.net/book/","").replace("/index.htm",""); 45 | // Message msg = new Message(); 46 | // @SuppressLint("HandlerLeak") 47 | // android.os.Handler handler = new android.os.Handler() { 48 | // @Override 49 | // public void handleMessage(Message msg) { 50 | // switch (msg.what) { 51 | // case 1: 52 | // book = new Book(bookID,bookName,bookAuthor,bookCoverURL,chapters,titles); 53 | // default: 54 | // break; 55 | // } 56 | // } 57 | // }; 58 | // new getResult(handler,msg).start(); 59 | // } 60 | // 61 | // class getResult extends Thread{ 62 | // Handler handler; 63 | // Message msg; 64 | // public getResult(Handler handler, Message msg){ 65 | // this.handler = handler; 66 | // this.msg = msg; 67 | // } 68 | // 69 | // private String splitElement(Element element){ 70 | // Elements es = element.select("a"); 71 | // String str = ""; 72 | // for (Element e:es){ 73 | // String tmp = e.text()+" "; 74 | // str = str + tmp; 75 | // } 76 | // element.select("a").remove(); 77 | // String tmp = element.text()+" "; 78 | // str = tmp+str; 79 | // return str; 80 | // } 81 | // 82 | // @Override 83 | // public void run() { 84 | // super.run(); 85 | // try { 86 | // Document doc = Jsoup.connect(url).timeout(20000).get(); 87 | // bookName = doc.selectFirst("h2").text(); 88 | // bookAuthor = splitElement(doc.selectFirst("h4")); 89 | // bookCoverURL = "http://www.99lib.net"+doc.selectFirst("img").attr("src"); 90 | // Elements elements_drags = doc.getElementById("right").select("dd"); 91 | // titles = new ArrayList<>(); 92 | // chapters = new ArrayList<>(); 93 | // for (Element e:elements_drags){ 94 | // titles.add(e.selectFirst("a").text()); 95 | // chapters.add(DecodeUtils.url("http://www.99lib.net"+e.selectFirst("a").attr("href"))); 96 | // } 97 | // } catch (IOException e) { 98 | // e.printStackTrace(); 99 | // } 100 | // msg.what = 1; 101 | // handler.sendMessage(msg); 102 | // } 103 | // } 104 | // 105 | //} 106 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/task/DownloadTask.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.task; 2 | 3 | import android.os.AsyncTask; 4 | 5 | import java.util.concurrent.ConcurrentHashMap; 6 | 7 | import cc.zsakvo.ninecswd.listener.OnDataFinishedListener; 8 | import cc.zsakvo.ninecswd.utils.DecodeUtils; 9 | import cc.zsakvo.ninecswd.utils.DialogUtils; 10 | 11 | /** 12 | * Created by akvo on 2018/3/17. 13 | */ 14 | 15 | public class DownloadTask extends AsyncTask { 16 | 17 | private int downloadsNum; 18 | private ConcurrentHashMap ch; 19 | private String bookID; 20 | private DialogUtils du; 21 | private int allNum; 22 | private int nowNum; 23 | private int type; 24 | private OnDataFinishedListener onDataFinishedListener; 25 | 26 | public DownloadTask(String bookID, ConcurrentHashMap ch, DialogUtils du,int allNum,int nowNum,int type,OnDataFinishedListener onDataFinishedListener){ 27 | this.bookID = bookID; 28 | this.ch = ch; 29 | this.du = du; 30 | this.allNum = allNum; 31 | this.nowNum = nowNum; 32 | this.type = type; 33 | this.onDataFinishedListener = onDataFinishedListener; 34 | } 35 | 36 | @Override 37 | protected Integer doInBackground(int[]... ints) { 38 | String hostURL = "http://www.99lib.net/book/"; 39 | int[] integers = ints[0]; 40 | this.downloadsNum = integers.length; 41 | int p = 1; 42 | for (int i:integers){ 43 | String url = hostURL +bookID+"/"+i+".htm"; 44 | if (i==0){ 45 | continue; 46 | } 47 | ch.put (i, DecodeUtils.url (url,type)); 48 | publishProgress(); 49 | } 50 | nowNum+=integers.length; 51 | return null; 52 | } 53 | 54 | @Override 55 | protected void onProgressUpdate(Integer...integers){ 56 | super.onProgressUpdate (integers); 57 | du.addProgress (allNum); 58 | } 59 | 60 | @Override 61 | protected void onPostExecute(Integer integer){ 62 | super.onPostExecute (integer); 63 | onDataFinishedListener.onDownloadFinishedNum (this.downloadsNum); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/task/GetArticleContentTask.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.task; 2 | 3 | import android.os.AsyncTask; 4 | import android.support.v7.widget.Toolbar; 5 | import android.widget.TextView; 6 | 7 | import com.github.nukc.stateview.StateView; 8 | import com.zzhoujay.richtext.RichText; 9 | 10 | import cc.zsakvo.ninecswd.listener.Interface; 11 | import cc.zsakvo.ninecswd.utils.DecodeUtils; 12 | 13 | /** 14 | * Created by akvo on 2018/2/21. 15 | */ 16 | 17 | public class GetArticleContentTask extends AsyncTask { 18 | 19 | private TextView textView; 20 | private Toolbar toolbar; 21 | private StateView mStateView; 22 | private Interface.GetArticle ga; 23 | 24 | public GetArticleContentTask(TextView textView, Toolbar toolbar, StateView mStateView, Interface.GetArticle ga){ 25 | this.textView = textView; 26 | this.toolbar = toolbar; 27 | this.mStateView = mStateView; 28 | this.ga = ga; 29 | } 30 | 31 | 32 | @Override 33 | protected String doInBackground(String ... params) { 34 | String content = DecodeUtils.url (params[0],3); 35 | if (content==null){ 36 | return null; 37 | }else { 38 | return content; 39 | } 40 | } 41 | 42 | @Override 43 | protected void onPostExecute(String string){ 44 | super.onPostExecute (string); 45 | if (string==null){ 46 | ga.GetResult (false); 47 | }else { 48 | RichText.fromHtml (string).into (textView); 49 | ga.GetResult (true); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/task/GetArticleListTask.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.task; 2 | 3 | import android.os.AsyncTask; 4 | 5 | import org.jsoup.Jsoup; 6 | import org.jsoup.nodes.Document; 7 | import org.jsoup.nodes.Element; 8 | import org.jsoup.select.Elements; 9 | 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | import cc.zsakvo.ninecswd.classes.ArticleList; 15 | import cc.zsakvo.ninecswd.listener.Interface; 16 | 17 | /** 18 | * Created by akvo on 2018/3/21. 19 | */ 20 | 21 | public class GetArticleListTask extends AsyncTask> { 22 | 23 | private Interface.GetArticleList gal; 24 | private int totalPage = 0; 25 | 26 | public GetArticleListTask(Interface.GetArticleList gal){ 27 | this.gal = gal; 28 | } 29 | 30 | @Override 31 | protected List doInBackground(String... strings) { 32 | String url = strings[0]; 33 | int page = Integer.parseInt (url.replace ("http://www.99lib.net/article/index.php?page=","")); 34 | List listDetails = new ArrayList<> (); 35 | try { 36 | Document doc = Jsoup.connect(url).timeout(20000).get(); 37 | if (page==1){ 38 | listDetails.clear(); 39 | totalPage = Integer.parseInt(doc.selectFirst("span.total").text().replace("1/","")); 40 | } 41 | Element element = doc.selectFirst("ul.list_box"); 42 | Elements ele_li = element.select("li"); 43 | for (Element e:ele_li){ 44 | Element n = e.select("a").get(1); 45 | String author = e.selectFirst("span").text().replace("(","").replace(")",""); 46 | String title = n.text(); 47 | String artical_url = "http://www.99lib.net"+n.attr("href"); 48 | listDetails.add(new ArticleList(title,author,artical_url)); 49 | } 50 | if (isCancelled()) 51 | { 52 | return (null); 53 | } 54 | return listDetails; 55 | } catch (IOException e) { 56 | e.printStackTrace(); 57 | return null; 58 | } 59 | } 60 | 61 | @Override 62 | protected void onPostExecute(List listDetails){ 63 | super.onPostExecute (listDetails); 64 | if (listDetails!=null) { 65 | gal.GetOK (listDetails,totalPage); 66 | }else { 67 | gal.GetFailed (); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/task/GetBookDetailTask.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.task; 2 | 3 | import android.os.AsyncTask; 4 | import android.util.Log; 5 | 6 | 7 | import org.jsoup.Jsoup; 8 | import org.jsoup.nodes.Document; 9 | import org.jsoup.nodes.Element; 10 | 11 | import java.io.IOException; 12 | 13 | import cc.zsakvo.ninecswd.listener.Interface; 14 | import cc.zsakvo.ninecswd.utils.SplitUtil; 15 | 16 | /** 17 | * Created by akvo on 2018/2/22. 18 | */ 19 | 20 | public class GetBookDetailTask extends AsyncTask{ 21 | 22 | private Interface.GetBookDetailFinish gbdf; 23 | 24 | 25 | 26 | public GetBookDetailTask(Interface.GetBookDetailFinish gbdf){ 27 | this.gbdf = gbdf; 28 | } 29 | 30 | @Override 31 | protected String[] doInBackground(String... strings) { 32 | String url = strings[0]; 33 | String title = ""; 34 | String intro = ""; 35 | String detail = ""; 36 | String coverUrl = ""; 37 | String searchStr = ""; 38 | try { 39 | Document doc = Jsoup.connect(url).timeout(20000).get(); 40 | Element element_info = doc.getElementById("book_info"); 41 | title = element_info.selectFirst("h2").text(); 42 | coverUrl = "http://www.99lib.net" + element_info.selectFirst("img").attr("src"); 43 | detail = "书籍简介:"+element_info.selectFirst("div.intro").text(); 44 | String author = SplitUtil.splitElement(element_info.selectFirst("h4")); 45 | // Log.e ("doInBackground: ",author.replace ("作者: ","") ); 46 | searchStr = title+" "+author.replace ("作者: ",""); 47 | int i = element_info.select("h4").size(); 48 | if (i == 2){ 49 | String label = SplitUtil.splitElement(element_info.select("h4").get(1),title,author.replace("作者:","")); 50 | intro = author+label; 51 | }else if (i == 3){ 52 | String trans = SplitUtil.splitElement(element_info.select("h4").get(1)); 53 | String label = SplitUtil.splitElement(element_info.select("h4").get(2),title,author.replace("作者:","")); 54 | author = author + " " + trans; 55 | intro = author+"\n\n"+label; 56 | } 57 | } catch (IOException e) { 58 | e.printStackTrace (); 59 | } 60 | 61 | if (isCancelled()) 62 | { 63 | return (null); 64 | } 65 | 66 | return new String[]{title,intro,detail,coverUrl,searchStr}; 67 | } 68 | 69 | @Override 70 | protected void onPostExecute(String[] strings){ 71 | super.onPostExecute (strings); 72 | if (strings[3].length ()!=0){ 73 | gbdf.GetSuccessful (strings[0],strings[1],strings[2],strings[3],strings[4]); 74 | }else { 75 | gbdf.GetFailed (); 76 | } 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/task/GetBookListTask.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.task; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.os.AsyncTask; 5 | 6 | 7 | import com.github.nukc.stateview.StateView; 8 | 9 | import org.jsoup.Jsoup; 10 | import org.jsoup.nodes.Document; 11 | import org.jsoup.nodes.Element; 12 | import org.jsoup.select.Elements; 13 | 14 | import java.io.IOException; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | import cc.zsakvo.ninecswd.adapter.ListAdapter; 19 | import cc.zsakvo.ninecswd.classes.BookList; 20 | import cc.zsakvo.ninecswd.listener.Interface; 21 | import cc.zsakvo.ninecswd.utils.SplitUtil; 22 | 23 | 24 | /** 25 | * Created by akvo on 2018/2/21. 26 | */ 27 | 28 | public class GetBookListTask extends AsyncTask> { 29 | 30 | private List listDetails; 31 | private ListAdapter adapter; 32 | @SuppressLint("StaticFieldLeak") 33 | private StateView mStateView; 34 | private Interface.GetBookListFinish gbf; 35 | 36 | public GetBookListTask(/*ListAdapter adapter, List listDetails, StateView mStateView, */Interface.GetBookListFinish gbf){ 37 | // this.listDetails = listDetails; 38 | // this.adapter = adapter; 39 | // this.mStateView = mStateView; 40 | this.gbf = gbf; 41 | } 42 | 43 | @Override 44 | protected void onPreExecute() { 45 | // mStateView.showLoading (); 46 | } 47 | 48 | @Override 49 | protected List doInBackground(String... strings) { 50 | String url = strings[0]; 51 | // String page = url.substring (url.indexOf ("page=")+5); 52 | List listDetails = new ArrayList<> (); 53 | try { 54 | Document doc = Jsoup.connect (url).timeout (20000).get (); 55 | Element element = doc.getElementById("list_box"); 56 | Elements ele_li = element.select("li"); 57 | for (Element e:ele_li){ 58 | String title = e.selectFirst("a").attr("title"); 59 | String author = SplitUtil.splitElement(e.select("h4").get(0)); 60 | String category = SplitUtil.splitElement(e.select("h4").get(1)); 61 | String label = SplitUtil.splitElement(e.select("h4").get(2),title,author.replace("作者:","")); 62 | String intro = "简介:"+e.selectFirst("div.intro").text(); 63 | String book_url = "http://www.99lib.net"+e.selectFirst("a").attr("href"); 64 | listDetails.add(new BookList (title,author+"\n"+category+"\n"+label,intro,book_url)); 65 | } 66 | return listDetails; 67 | } catch (IOException e) { 68 | e.printStackTrace (); 69 | return null; 70 | } 71 | } 72 | 73 | 74 | @Override 75 | protected void onPostExecute(List listDetails){ 76 | super.onPostExecute (listDetails); 77 | if (listDetails!=null) { 78 | gbf.bookList (listDetails); 79 | }else { 80 | gbf.booksGetFailed (); 81 | } 82 | // mStateView.showContent (); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/task/GetCategoryListTask.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.task; 2 | 3 | import android.os.AsyncTask; 4 | 5 | import org.jsoup.Jsoup; 6 | import org.jsoup.nodes.Document; 7 | import org.jsoup.nodes.Element; 8 | import org.jsoup.select.Elements; 9 | 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | import cc.zsakvo.ninecswd.adapter.ListAdapter; 15 | import cc.zsakvo.ninecswd.classes.BookList; 16 | import cc.zsakvo.ninecswd.listener.Interface; 17 | import cc.zsakvo.ninecswd.utils.SplitUtil; 18 | 19 | /** 20 | * Created by akvo on 2018/2/22. 21 | */ 22 | 23 | public class GetCategoryListTask extends AsyncTask> { 24 | 25 | private int totalPage; 26 | private List listDetails; 27 | private ListAdapter adapter; 28 | private Interface.GetCategoryList gcl; 29 | 30 | public GetCategoryListTask(int totalPage, List listDetails, ListAdapter adapter, Interface.GetCategoryList gcl){ 31 | this.totalPage = totalPage; 32 | this.adapter = adapter; 33 | this.gcl = gcl; 34 | } 35 | 36 | @Override 37 | protected List doInBackground(Object... objects) { 38 | String url = (String) objects[0]; 39 | int page = (int) objects[1]; 40 | List listDetails = new ArrayList<> (); 41 | try { 42 | Document doc = Jsoup.connect(url).timeout(20000).get(); 43 | if (page==1){ 44 | listDetails.clear(); 45 | totalPage = Integer.parseInt(doc.selectFirst("span.total").text().replace("1/","")); 46 | } 47 | Element element = doc.selectFirst("ul.list_box"); 48 | Elements ele_li = element.select("li"); 49 | for (Element e:ele_li){ 50 | String title = e.selectFirst("h2").text(); 51 | String author = SplitUtil.splitElement(e.select("h4").get(0)); 52 | String category = SplitUtil.splitElement(e.select("h4").get(1)); 53 | String label = SplitUtil.splitElement(e.select("h4").get(2),title,author.replace("作者:","")); 54 | String intro = "简介:"+e.selectFirst("div.intro").text(); 55 | String book_url = "http://www.99lib.net"+e.selectFirst("a").attr("href"); 56 | listDetails.add(new BookList(title,author+"\n"+category+"\n"+label,intro,book_url)); 57 | } 58 | return listDetails; 59 | } catch (IOException e) { 60 | e.printStackTrace (); 61 | return null; 62 | } 63 | } 64 | 65 | @Override 66 | protected void onPostExecute(List listDetails){ 67 | super.onPostExecute (listDetails); 68 | if (listDetails!=null){ 69 | gcl.GetOK (listDetails); 70 | }else { 71 | gcl.GetFailed (); 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/task/GetCoversTask.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.task; 2 | 3 | import android.os.AsyncTask; 4 | import android.util.Log; 5 | 6 | import com.alibaba.fastjson.JSON; 7 | import com.alibaba.fastjson.JSONArray; 8 | import com.alibaba.fastjson.JSONObject; 9 | import com.alibaba.fastjson.serializer.JSONSerializer; 10 | import com.alibaba.fastjson.serializer.PropertyFilter; 11 | import com.alibaba.fastjson.serializer.SerializeWriter; 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.Iterator; 21 | import java.util.List; 22 | 23 | import cc.zsakvo.ninecswd.listener.Interface; 24 | 25 | /** 26 | * Created by akvo on 2018/3/31. 27 | */ 28 | 29 | public class GetCoversTask extends AsyncTask> { 30 | 31 | private Interface.GetCoverUrls gcu; 32 | 33 | public GetCoversTask(Interface.GetCoverUrls gcu){ 34 | this.gcu = gcu; 35 | } 36 | 37 | @Override 38 | protected List doInBackground(String... strings) { 39 | String engine = strings[1]; 40 | switch (engine){ 41 | case "Bing": 42 | return searchBing(strings[0]); 43 | case "Baidu": 44 | return searchBaidu (strings[0]); 45 | } 46 | return null; 47 | } 48 | 49 | private List searchBaidu(String str){ 50 | 51 | PropertyFilter filter = new PropertyFilter () { 52 | public boolean apply(Object source, String name, Object value) { 53 | if (((String)name).contains ("objURL")) { 54 | return true; 55 | }else { 56 | return false; 57 | } 58 | } 59 | }; 60 | 61 | List list = new ArrayList<> (); 62 | 63 | try { 64 | Document document = Jsoup.connect("https://image.baidu.com/search/index?tn=baiduimage&word="+str).get(); 65 | String content = document.body().toString(); 66 | content = content.substring(content.indexOf("setData('imgData',") + "setData('imgData',".length ()); 67 | content = content.substring(0, content.indexOf(");")); 68 | JSONArray array = JSON.parseObject(content).getJSONArray("data"); 69 | String json = JSON.toJSONString(array, filter); 70 | JSONArray array_n = JSON.parseArray (json); 71 | for (Iterator iterator = array_n.iterator(); iterator.hasNext();) { 72 | JSONObject job = (JSONObject) iterator.next(); 73 | try { 74 | list.add (job.get ("objURL").toString ()); 75 | }catch (Exception e){ 76 | 77 | } 78 | } 79 | return list; 80 | } catch (IOException e) { 81 | e.printStackTrace (); 82 | } 83 | return null; 84 | } 85 | 86 | private List searchBing(String str){ 87 | List urls = new ArrayList<> (); 88 | try { 89 | Document doc = Jsoup.connect("http://cn.bing.com/images/search?sp=-1&q="+str+"&qft=+filterui:aspect-tall+filterui:imagesize-custom_300_430&FORM=IRFLTR").get(); 90 | Elements elements = elements = doc.select("a[m*=murl]"); 91 | for (Element e: elements){ 92 | String s = e.toString (); 93 | String url = s.substring (s.indexOf ("murl")+4,s.indexOf ("turl")); 94 | String url_c = url.replace (":"","") 95 | .replace (","","") 96 | .replace (""",""); 97 | urls.add (url_c); 98 | } 99 | return urls; 100 | } catch (IOException e) { 101 | e.printStackTrace (); 102 | return null; 103 | } 104 | } 105 | 106 | @Override 107 | protected void onPostExecute(List list){ 108 | super.onPostExecute (list); 109 | if (list!=null){ 110 | gcu.GetCoverUrls (list); 111 | }else{ 112 | gcu.GetCoverUrlsFailed (); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/task/GetDownloadInfoTask.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.task; 2 | 3 | import android.os.AsyncTask; 4 | 5 | import org.jsoup.Jsoup; 6 | import org.jsoup.nodes.Document; 7 | import org.jsoup.nodes.Element; 8 | import org.jsoup.select.Elements; 9 | 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | import cc.zsakvo.ninecswd.classes.DownloadDetails; 15 | import cc.zsakvo.ninecswd.listener.OnDataFinishedListener; 16 | import cc.zsakvo.ninecswd.utils.DialogUtils; 17 | import cc.zsakvo.ninecswd.utils.ReplaceUtils; 18 | import cc.zsakvo.ninecswd.utils.SplitUtil; 19 | 20 | /** 21 | * Created by akvo on 2018/2/22. 22 | */ 23 | 24 | public class GetDownloadInfoTask extends AsyncTask { 25 | 26 | private OnDataFinishedListener onDataFinishedListener; 27 | private String[] chapt; 28 | private int size; 29 | private DialogUtils dialogUtils; 30 | 31 | public GetDownloadInfoTask(DialogUtils dialogUtils){ 32 | this.dialogUtils = dialogUtils; 33 | } 34 | 35 | @Override 36 | protected void onPreExecute() { 37 | dialogUtils.initDialog (); 38 | dialogUtils.setDialogTitle ("正在获取书籍信息,请稍后……"); 39 | } 40 | 41 | @Override 42 | protected DownloadDetails doInBackground(Object... objs) { 43 | String url = (String)objs[0]; 44 | // DownloadDetails downloadDetails = (DownloadDetails)objs[1]; 45 | Document doc = null; 46 | String bookID = ""; 47 | String bookName = ""; 48 | String bookAuthor = ""; 49 | String bookCoverURL = ""; 50 | List titles = new ArrayList<> (); 51 | List chapters = new ArrayList<> (); 52 | List chapterIDs = new ArrayList<> (); 53 | bookID = url.replace ("http://www.99lib.net/book/","").replace ("/index.htm",""); 54 | try { 55 | doc = Jsoup.connect(url).timeout(20000).get(); 56 | doc.select ("dt").remove (); 57 | bookName = doc.selectFirst("h2").text(); 58 | bookAuthor = SplitUtil.splitElement(doc.selectFirst("h4")); 59 | bookCoverURL = "http://www.99lib.net"+doc.selectFirst("img").attr("src"); 60 | Elements elements_drags = doc.getElementById("right").select("dd"); 61 | titles = new ArrayList<> (); 62 | chapters = new ArrayList<>(); 63 | for (Element e:elements_drags){ 64 | titles.add(e.selectFirst("a").text()); 65 | chapterIDs.add(ReplaceUtils.getChapterID (bookID,e.selectFirst("a").attr("href"))); 66 | } 67 | size = chapters.size (); 68 | chapt = new String[size]; 69 | } catch (IOException e) { 70 | e.printStackTrace (); 71 | } 72 | return new DownloadDetails (bookID, 73 | bookName, 74 | bookAuthor, 75 | bookCoverURL, 76 | titles, 77 | chapterIDs, 78 | null); 79 | } 80 | 81 | @Override 82 | protected void onPostExecute(DownloadDetails downloadDetails) { 83 | super.onPostExecute (downloadDetails); 84 | onDataFinishedListener.onDataSuccessfully(downloadDetails); 85 | } 86 | 87 | public void setOnDataFinishedListener( 88 | OnDataFinishedListener onDataFinishedListener) { 89 | this.onDataFinishedListener = onDataFinishedListener; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/task/GetSearchListTask.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.task; 2 | 3 | import android.os.AsyncTask; 4 | 5 | import org.jsoup.Jsoup; 6 | import org.jsoup.nodes.Document; 7 | import org.jsoup.nodes.Element; 8 | import org.jsoup.select.Elements; 9 | 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | import cc.zsakvo.ninecswd.classes.BookList; 15 | import cc.zsakvo.ninecswd.listener.Interface; 16 | import cc.zsakvo.ninecswd.utils.SplitUtil; 17 | 18 | /** 19 | * Created by akvo on 2018/2/22. 20 | */ 21 | 22 | public class GetSearchListTask extends AsyncTask> { 23 | private int totalPage; 24 | private Interface.GetSearch gs; 25 | 26 | public GetSearchListTask( Interface.GetSearch gs){ 27 | this.gs = gs; 28 | } 29 | 30 | @Override 31 | protected List doInBackground(Object... objects) { 32 | String url = (String) objects[0]; 33 | int page = (int) objects[1]; 34 | List listDetails = new ArrayList<> (); 35 | try { 36 | Document doc = Jsoup.connect(url).timeout(20000).get(); 37 | if (page==1){ 38 | listDetails.clear(); 39 | try { 40 | totalPage = (int) Math.ceil ((double) Integer.parseInt (doc.selectFirst ("strong").text ()) / 15.0); 41 | }catch (Exception e){ 42 | return null; 43 | } 44 | } 45 | Element element = doc.selectFirst("ul.list_box"); 46 | Elements ele_li = element.select("li"); 47 | for (Element e:ele_li){ 48 | if (e.selectFirst("h2")==null){ 49 | return null; 50 | } 51 | String title = e.selectFirst("h2").text(); 52 | String author = SplitUtil.splitElement(e.select("h4").get(0)); 53 | String category = SplitUtil.splitElement(e.select("h4").get(1)); 54 | String label = SplitUtil.splitElement(e.select("h4").get(2),title,author.replace("作者:","")); 55 | String intro = "简介:"+e.selectFirst("div.intro").text(); 56 | String book_url = "http://www.99lib.net"+e.selectFirst("a").attr("href"); 57 | listDetails.add(new BookList(title,author+"\n"+category+"\n"+label,intro,book_url)); 58 | } 59 | if (isCancelled()) 60 | { 61 | return (null); 62 | } 63 | return listDetails; 64 | } catch (IOException e) { 65 | e.printStackTrace (); 66 | return null; 67 | } 68 | } 69 | 70 | @Override 71 | protected void onPostExecute(List listDetails){ 72 | super.onPostExecute (listDetails); 73 | if (listDetails==null){ 74 | gs.GetFailed (); 75 | }else { 76 | gs.GetOK (listDetails,totalPage); 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/task/OutPutTxtTask.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.task; 2 | 3 | import android.os.AsyncTask; 4 | 5 | import cc.zsakvo.ninecswd.listener.Interface; 6 | import cc.zsakvo.ninecswd.utils.TxtUtils; 7 | 8 | /** 9 | * Created by akvo on 2018/3/20. 10 | */ 11 | 12 | public class OutPutTxtTask extends AsyncTask { 13 | 14 | private String bookName; 15 | private Interface.OutPutTxtFinish opf; 16 | 17 | public OutPutTxtTask(String bookName, Interface.OutPutTxtFinish opf){ 18 | this.bookName = bookName; 19 | this.opf = opf; 20 | } 21 | 22 | @Override 23 | protected Integer doInBackground(String... strings) { 24 | TxtUtils.generateTXT (bookName,strings[0]); 25 | opf.outPutSuccess (1); 26 | return null; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/task/SetCoverTask.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.task; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import android.os.AsyncTask; 6 | 7 | import java.io.InputStream; 8 | import java.net.HttpURLConnection; 9 | import java.net.URL; 10 | 11 | import cc.zsakvo.ninecswd.listener.Interface; 12 | 13 | /** 14 | * Created by akvo on 2018/3/21. 15 | */ 16 | 17 | public class SetCoverTask extends AsyncTask { 18 | 19 | Interface.GetCover gc; 20 | 21 | public SetCoverTask(Interface.GetCover gc){ 22 | this.gc = gc; 23 | } 24 | 25 | @Override 26 | protected Bitmap doInBackground(String... strings) { 27 | String imgUrl = strings[0]; 28 | Bitmap bitmap; 29 | try { 30 | URL url = new URL (imgUrl); 31 | HttpURLConnection connection = (HttpURLConnection)url.openConnection (); 32 | connection.setConnectTimeout (20000); 33 | connection.setRequestMethod ("GET"); 34 | if (connection.getResponseCode ()==200){ 35 | InputStream in = connection.getInputStream (); 36 | bitmap = BitmapFactory.decodeStream (in); 37 | }else { 38 | bitmap = null; 39 | } 40 | return bitmap; 41 | } catch (Exception e) { 42 | e.printStackTrace (); 43 | return null; 44 | } 45 | } 46 | @Override 47 | protected void onPostExecute(Bitmap bitmap) { 48 | super.onPostExecute(bitmap); 49 | gc.GetCoverOK (bitmap); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/utils/DecodeUtils.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.utils; 2 | 3 | import android.util.Log; 4 | 5 | import org.jsoup.Jsoup; 6 | import org.jsoup.nodes.Document; 7 | import org.jsoup.nodes.Element; 8 | import org.jsoup.select.Elements; 9 | 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | import static com.chad.library.adapter.base.listener.SimpleClickListener.TAG; 15 | 16 | 17 | /** 18 | * Created by akvo on 2018/2/8. 19 | */ 20 | 21 | public class DecodeUtils { 22 | 23 | 24 | public static class Decode99{ 25 | 26 | private String url; 27 | private String title; 28 | private int type; 29 | String client = ""; 30 | Element content; 31 | 32 | String getContent(String url,int type){ 33 | this.type = type; 34 | try { 35 | this.url = url; 36 | Document doc = Jsoup.connect(url).timeout(13000).get(); 37 | this.title = doc.selectFirst("h2").text(); 38 | doc.select("strike,acronym,bdo,big,site,code,dfn,kbd,q,s,samp,tt,u,var,cite") 39 | .remove(); 40 | this.client = doc.select("meta").get(4).attr("content"); 41 | this.content = doc.getElementById("content"); 42 | return deal(); 43 | } catch (IOException e) { 44 | return null; 45 | } 46 | } 47 | 48 | private String random(){ 49 | return String.valueOf(Math.floor(Math.random() * 25 + 97) + Math.floor(Math.random() * (1000000000))); 50 | } 51 | 52 | public String deal() { 53 | int star = 0; 54 | Elements childNotes = content.children(); 55 | int childNodesLength = childNotes.size(); 56 | for (int i = 0; i < childNodesLength; i++) { 57 | if (childNotes.get(i).tagName().equals("h2")) { 58 | star = i + 1; 59 | } 60 | if (childNotes.get(i).tagName().equals("div") && !childNotes.get(i).className().equals("chapter")) { 61 | break; 62 | } 63 | } 64 | String text = new String (); 65 | switch (type){ 66 | case 0: 67 | text = this.title+"\n\n"+load(childNotes,star)+"\n\n\n"; 68 | break; 69 | case 1: 70 | text = "

"+this.title+"

\n"+load(childNotes,star); 71 | break; 72 | case 2: 73 | text = load(childNotes,star); 74 | break; 75 | case 3: 76 | text = ""+this.title+"\n\n"+load(childNotes,star)+"\n\n\n"; 77 | break; 78 | 79 | default: 80 | text = load(childNotes,star); 81 | break; 82 | } 83 | return text; 84 | } 85 | 86 | private String load(Elements childNotes,int star){ 87 | String t = base64(client).replaceAll("[^0-9%]",""); 88 | String[] e = t.split("%"); 89 | int k = 0; 90 | int size =0; 91 | for (int i=0;i"+childNode[i].text()+"

\n"); 123 | break; 124 | case 2: 125 | content.append(childNode[i].text()+"\n"); 126 | break; 127 | case 3: 128 | content.append("

    "+childNode[i].text()+"

\n"); 129 | break; 130 | } 131 | } 132 | } 133 | return content.toString(); 134 | } 135 | 136 | private String base64(String a){ 137 | String map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 138 | String b = ""; 139 | String binary = b; 140 | String[] sc = {"00000","0000","000","00","0",""}; 141 | List binarys = new ArrayList<>(); 142 | for (int i = 0; i < a.length(); i++) { 143 | if (a.substring(i, i+1).equals("=")) { 144 | break; 145 | } 146 | String c = Integer.toBinaryString(map.indexOf(a.charAt(i))); 147 | binary += sc[c.length()-1]+c; 148 | }; 149 | for (int i=0;i=binary.length()){ 151 | binarys.add(binary.substring(i)); 152 | }else { 153 | binarys.add(binary.substring(i, i + 8)); 154 | } 155 | } 156 | for (int i = 0; i < binarys.size(); i++) { 157 | b += "" + (char)(Integer.parseInt(binarys.get(i),2)); 158 | }; 159 | return b; 160 | } 161 | }; 162 | 163 | public static String url(String url,int type){ 164 | return new Decode99().getContent(url,type); 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/utils/DialogUtils.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.utils; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.util.DisplayMetrics; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.widget.LinearLayout; 9 | import android.widget.TextView; 10 | 11 | import cc.zsakvo.ninecswd.R; 12 | 13 | /** 14 | * Created by akvo on 2018/3/17. 15 | */ 16 | 17 | public class DialogUtils { 18 | 19 | private Context context; 20 | private Dialog dialog; 21 | private int progress = 0; 22 | private int allNum; 23 | 24 | public DialogUtils(Context context,Dialog dialog){ 25 | this.context = context; 26 | this.dialog = dialog; 27 | } 28 | 29 | public void setAllNum(int i){ 30 | this.allNum = i; 31 | } 32 | 33 | public void initDialog(){ 34 | progress = 0; 35 | LayoutInflater inflater = LayoutInflater.from (context); 36 | View v = inflater.inflate (R.layout.dialog, null); // 得到加载view 37 | DisplayMetrics displaymetrics = new DisplayMetrics (); 38 | displaymetrics = context.getResources ().getDisplayMetrics (); 39 | int screenWidth = displaymetrics.widthPixels; 40 | v.setMinimumWidth ((int) (screenWidth * 0.8)); 41 | LinearLayout layout = (LinearLayout) v.findViewById (R.id.dia_lay); // 加载布局 42 | dialog = new Dialog (context); // 创建自定义样式dialog 43 | dialog.setCancelable (false); // 不可以用"返回键"取消 44 | dialog.setContentView (layout, new LinearLayout.LayoutParams ( 45 | LinearLayout.LayoutParams.WRAP_CONTENT, 46 | LinearLayout.LayoutParams.WRAP_CONTENT)); 47 | dialog.show (); 48 | } 49 | 50 | public void setDialogTitle(String title){ 51 | TextView d_tv = dialog.findViewById(R.id.dia_text); 52 | d_tv.setText(title); 53 | } 54 | 55 | public void concelDialog(){ 56 | dialog.dismiss (); 57 | } 58 | 59 | public void addProgress(int allNum){ 60 | progress++; 61 | String text = "正在下载章节……"+progress+"/"+allNum; 62 | setDialogTitle (text); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/utils/EpubUtils.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.utils; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.os.Environment; 5 | import android.os.Handler; 6 | import android.os.Message; 7 | 8 | import org.jsoup.Jsoup; 9 | import org.jsoup.nodes.Element; 10 | import org.zeroturnaround.zip.NameMapper; 11 | import org.zeroturnaround.zip.ZipUtil; 12 | 13 | import java.io.BufferedWriter; 14 | import java.io.File; 15 | import java.io.FileOutputStream; 16 | import java.io.FileWriter; 17 | import java.io.IOException; 18 | import java.io.InputStream; 19 | import java.io.OutputStream; 20 | import java.net.MalformedURLException; 21 | import java.net.URL; 22 | import java.net.URLConnection; 23 | import java.util.List; 24 | 25 | /** 26 | * Created by akvo on 2018/2/1. 27 | */ 28 | 29 | public class EpubUtils { 30 | private static String BOOKTOC = "\n" + 31 | "\n" + 32 | "\n" + 33 | "\n" + 34 | "\n" + 35 | "\n" + 36 | "Table Of Contents\n" + 37 | "\n" + 38 | "\n" + 39 | "\n" + 40 | "\n" + 41 | "

目录

\n" + 42 | "
\n" + 43 | "
\n" + 44 | "toreplace0\n" + 45 | "
\n" + 46 | "
\n" + 47 | "\n" + 48 | "\n"; 49 | public static String CHAPTER = "\n" + 50 | "\n" + 51 | "\n" + 52 | "\n" + 53 | "\n" + 54 | "\n" + 55 | "\n" + 56 | "toreplace0 - 0\n" + 57 | "\n" + 58 | "\n" + 59 | "\n" + 60 | "\n" + 61 | "toreplace1\n"+ 62 | "\n" + 63 | ""; 64 | private static String CONTAINER = "\n" + 65 | "\n" + 66 | " \n" + 67 | " \n" + 68 | " \n" + 69 | ""; 70 | private static String CONTENT = "\n" + 71 | "\n" + 72 | "\n" + 73 | "easypub-c260e840\n" + 74 | "toreplace0\n" + 75 | "toreplace1\n" + 76 | "2018\n" + 77 | "Created with EasyPub v1.50\n" + 78 | "zh-CN\n" + 79 | "\n" + 80 | "\n" + 81 | "toreplace2\n" + 82 | "toreplace3" + 83 | "\n" + 84 | "\n" + 85 | "\n" + 86 | "\n" + 87 | "\n" + 88 | "\n"; 89 | private static String MIMETYPE = "application/epub+zip"; 90 | private static String STYLE = "@font-face {\n" + 91 | " font-family: \"easypub\";\n" + 92 | " src: url(res:///system/fonts/DroidSansFallback.ttf),\n" + 93 | " url(res:///ebook/fonts/../../system/fonts/DroidSansFallback.ttf);\n" + 94 | "}\n" + 95 | "\n" + 96 | "@page { \n" + 97 | " margin-top: 0px;\n" + 98 | " margin-bottom: 0px;\n" + 99 | "}\n" + 100 | "\n" + 101 | "body { \n" + 102 | " font-family: \"easypub\";\n" + 103 | " padding: 0;\n" + 104 | " margin-left: 0px;\n" + 105 | " margin-right: 0px;\n" + 106 | " orphans: 0;\n" + 107 | " widows: 0;\n" + 108 | "}\n" + 109 | "\n" + 110 | "p { \n" + 111 | " font-family: \"easypub\";\n" + 112 | " font-size: 120%;\n" + 113 | " line-height: 125%;\n" + 114 | " margin-top: 5px;\n" + 115 | " margin-bottom: 0;\n" + 116 | " margin-left: 0;\n" + 117 | " margin-right: 0;\n" + 118 | " orphans: 0;\n" + 119 | " widows: 0;\n" + 120 | "}\n" + 121 | "\n" + 122 | ".a { \n" + 123 | " text-indent: 0em;\n" + 124 | "}\n" + 125 | "\n" + 126 | "div.centeredimage {\n" + 127 | " text-align:center;\n" + 128 | " display:block;\n" + 129 | " margin-top: 0.5em;\n" + 130 | " margin-bottom: 0.5em;\n" + 131 | "}\n" + 132 | "\n" + 133 | "img.attpic {\n" + 134 | " border: 1px solid #000000;\n" + 135 | " max-width: 100%;\n" + 136 | " margin: 0;\n" + 137 | "}\n" + 138 | "\n" + 139 | ".booktitle {\n" + 140 | " margin-top: 30%;\n" + 141 | " margin-bottom: 0;\n" + 142 | " border-style: none solid none none;\n" + 143 | " border-width: 50px;\n" + 144 | " border-color: #4E594D;\n" + 145 | " font-size: 3em;\n" + 146 | " line-height: 120%;\n" + 147 | " text-align: right;\n" + 148 | "}\n" + 149 | "\n" + 150 | ".bookauthor {\n" + 151 | " margin-top: 0;\n" + 152 | " border-style: none solid none none;\n" + 153 | " border-width: 50px;\n" + 154 | " border-color: #4E594D;\n" + 155 | " page-break-after: always;\n" + 156 | " font-size: large;\n" + 157 | " line-height: 120%;\n" + 158 | " text-align: right;\n" + 159 | "}\n" + 160 | "\n" + 161 | ".titletoc, .titlel1top, .titlel1std,.titlel2top, .titlel2std,.titlel3top, .titlel3std,.titlel4std {\n" + 162 | " margin-top: 0;\n" + 163 | " border-style: none double none solid;\n" + 164 | " border-width: 0px 5px 0px 20px;\n" + 165 | " border-color: #586357;\n" + 166 | " background-color: #C1CCC0;\n" + 167 | " padding: 45px 5px 5px 5px;\n" + 168 | " font-size: x-large;\n" + 169 | " line-height: 115%;\n" + 170 | " text-align: justify;\n" + 171 | "}\n" + 172 | "\n" + 173 | ".titlel1single,.titlel2single,.titlel3single {\n" + 174 | " margin-top: 35%;\n" + 175 | " border-style: none solid none none;\n" + 176 | " border-width: 30px;\n" + 177 | " border-color: #4E594D;\n" + 178 | " padding: 30px 5px 5px 5px;\n" + 179 | " font-size: x-large;\n" + 180 | " line-height: 125%;\n" + 181 | " text-align: right;\n" + 182 | "}\n" + 183 | "\n" + 184 | ".toc {\n" + 185 | " margin-left:16%;\n" + 186 | " padding:0px;\n" + 187 | " line-height:130%;\n" + 188 | " text-align: justify;\n" + 189 | "}\n" + 190 | "\n" + 191 | ".toc a { text-decoration: none; color: #000000; }\n" + 192 | "\n" + 193 | ".tocl1 {\n" + 194 | " margin-top:0.5em;\n" + 195 | " margin-left:-30px;\n" + 196 | " border-style: none double double solid;\n" + 197 | " border-width: 0px 5px 2px 20px;\n" + 198 | " border-color: #6B766A;\n" + 199 | " line-height: 135%;\n" + 200 | " font-size: 132%;\n" + 201 | "}\n" + 202 | "\n" + 203 | ".tocl2 {\n" + 204 | " margin-top: 0.5em;\n" + 205 | " margin-left:-20px;\n" + 206 | " border-style: none double none solid;\n" + 207 | " border-width: 0px 2px 0px 10px;\n" + 208 | " border-color: #939E92;\n" + 209 | " line-height: 123%;\n" + 210 | " font-size: 120%;\n" + 211 | "}\n" + 212 | "\n" + 213 | ".tocl3 {\n" + 214 | " margin-top: 0.5em;\n" + 215 | " margin-left:-20px;\n" + 216 | " border-style: none double none solid;\n" + 217 | " border-width: 0px 2px 0px 8px;\n" + 218 | " border-color: #939E92;\n" + 219 | " line-height: 112%;\n" + 220 | " font-size: 109%;\n" + 221 | "}\n" + 222 | "\n" + 223 | ".tocl4 {\n" + 224 | " margin-top: 0.5em;\n" + 225 | " margin-left:-20px;\n" + 226 | " border-style: none double none solid;\n" + 227 | " border-width: 0px 2px 0px 6px;\n" + 228 | " border-color: #939E92;\n" + 229 | " line-height: 115%;\n" + 230 | " font-size: 110%;\n" + 231 | "}\n" + 232 | "\n" + 233 | ".subtoc {\n" + 234 | " margin-left:15%;\n" + 235 | " padding:0px;\n" + 236 | " text-align: justify;\n" + 237 | "}\n" + 238 | "\n" + 239 | ".subtoclist {\n" + 240 | " margin-top: 0.5em;\n" + 241 | " margin-left:-20px;\n" + 242 | " border-style: none double none solid;\n" + 243 | " border-width: 0px 2px 0px 10px;\n" + 244 | " border-color: #939E92;\n" + 245 | " line-height: 123%;\n" + 246 | " font-size: 120%;\n" + 247 | "}\n" + 248 | "\n"; 249 | private static String TOC = "\n" + 250 | "\n" + 251 | "\n" + 252 | "\n" + 253 | "\n" + 254 | "\n" + 255 | "\n" + 256 | "\n" + 257 | "\n" + 258 | "\n" + 259 | "\n" + 260 | "\n" + 261 | "\n" + 262 | "toreplace0\n" + 263 | "\n" + 264 | "\n" + 265 | "toreplace1\n" + 266 | "\n" + 267 | "\n" + 268 | "toreplace2" + 269 | "\n"; 270 | 271 | private static String COVERHTML="\n" + 272 | "\n" + 273 | "\n" + 274 | "\n" + 275 | "\n" + 276 | "\n" + 277 | "\n" + 278 | "Cover\n" + 279 | "\n" + 280 | "\n" + 286 | "\n" + 287 | "\n" + 288 | "\n" + 289 | "
\n" + 290 | "
\n" + 291 | "
\n" + 292 | "\"toreplace0\"\n" + 293 | "
\n" + 294 | "
\n" + 295 | "\n" + 296 | ""; 297 | 298 | private static String ELE_DT_A = "
Table
"; 299 | 300 | private static String ELE_MANIFEST = "\n" + 301 | "\n" + 302 | "\n" + 303 | "\n" + 304 | "\n" + 305 | "\n" + 306 | ""; 307 | 308 | private static String ELE_SPINE = "\n" + 309 | "\n" + 310 | "\n" + 311 | ""; 312 | 313 | private static String ELE_NAV_MAP = "\n" + 314 | "\n" + 315 | "THETEXT\n" + 316 | "\n" + 317 | "\n"; 318 | 319 | private static String ELE_CHAPTER_BODY = "\n" + 320 | "

\n" + 321 | "

\n" + 322 | ""; 323 | 324 | private String sdPath = Environment.getExternalStorageDirectory().getPath()+"/99lib/"; 325 | private String cachePath; 326 | private String bookPath; 327 | private String bookID; 328 | private String bookName; 329 | private String bookAuthor; 330 | private String bookCoverURL; 331 | private List chapters; 332 | private List titles; 333 | private int chapterNums = 0; 334 | private getResult gr; 335 | int threadNum = 4; 336 | 337 | public Boolean getOthersOK() { 338 | return isOthersOK; 339 | } 340 | 341 | public void setOthersOK(Boolean othersOK) { 342 | isOthersOK = othersOK; 343 | } 344 | 345 | public Boolean getChaptersOK() { 346 | return isChaptersOK; 347 | } 348 | 349 | public void setChaptersOK(Boolean chaptersOK) { 350 | isChaptersOK = chaptersOK; 351 | } 352 | 353 | private Boolean isOthersOK; 354 | private Boolean isChaptersOK; 355 | 356 | public interface getResult{ 357 | void isGenerOk(int i); 358 | } 359 | 360 | public EpubUtils(String bookID, String bookName, String bookAuthor, String bookCoverURL, List chapters, List titles,getResult gr){ 361 | this.bookID = bookID; 362 | this.bookName = bookName; 363 | this.bookAuthor = bookAuthor; 364 | this.bookCoverURL = bookCoverURL; 365 | this.chapters = chapters; 366 | this.titles = titles; 367 | this.gr = gr; 368 | chapterNums = chapters.size(); 369 | cachePath = Environment.getExternalStorageDirectory().getPath()+"/99lib/cache/"+bookID; 370 | bookPath = Environment.getExternalStorageDirectory().getPath()+"/99lib/Epub/"; 371 | new File(cachePath).mkdirs(); 372 | if (!new File(bookPath).exists ()){ 373 | new File(bookPath).mkdirs (); 374 | } 375 | } 376 | 377 | private void writeStr(String path,String str){ 378 | File file = new File(path); 379 | if (file.exists()) file.delete(); 380 | try { 381 | file.createNewFile(); 382 | BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file)); 383 | bufferedWriter.write(str); 384 | bufferedWriter.flush(); 385 | bufferedWriter.close(); 386 | } catch (IOException e) { 387 | e.printStackTrace(); 388 | } 389 | } 390 | 391 | private void generateOthers(){ 392 | System.out.println(cachePath); 393 | new File(cachePath+"/META-INF").mkdirs(); 394 | new File(cachePath+"/OEBPS").mkdirs(); 395 | writeStr(cachePath+"/mimetype",MIMETYPE); 396 | writeStr(cachePath+"/META-INF/container.xml",CONTAINER); 397 | writeStr(cachePath+"/OEBPS/style.css",STYLE); 398 | generateCover(); 399 | generateTocNcx(); 400 | generateContentOpf(); 401 | generateBookToc(); 402 | generateCoverHtml(); 403 | } 404 | 405 | private void generateCover(){ 406 | try { 407 | URL url_cover = new URL(bookCoverURL); 408 | URLConnection uri = url_cover.openConnection(); 409 | InputStream is = uri.getInputStream(); 410 | OutputStream os = new FileOutputStream(new File(cachePath+"/OEBPS/cover.jpg")); 411 | byte[] buf = new byte[1024]; 412 | int len = -1; 413 | while ((len = is.read(buf)) != -1) { 414 | os.write(buf, 0, len); 415 | } 416 | } catch (MalformedURLException e) { 417 | e.printStackTrace(); 418 | } catch (IOException e) { 419 | generateCover(); 420 | } 421 | } 422 | 423 | private void generateTocNcx(){ 424 | String fileText = TOC; 425 | { 426 | StringBuilder d = new StringBuilder(); 427 | String e = ELE_NAV_MAP; 428 | d.append(e.replace("POD","1").replace("THETEXT","封面").replace("THEHTML","cover.html")); 429 | d.append(e.replace("POD","2").replace("THETEXT","目录").replace("THEHTML","book-toc.html")); 430 | int playorder = 3; 431 | int chapter = 0; 432 | for (int i=0;i list, int num) { 42 | int size = list.size(); 43 | int remainder = size % num; 44 | int threadNum; 45 | int[][] result; 46 | if (remainder == 0) { 47 | threadNum = size / num; 48 | result = new int[threadNum][num]; 49 | for (int i = 0; i < threadNum; i++) { 50 | for (int j = 0; j < num; j++) { 51 | result[i][j] = list.get(i * num + j); 52 | } 53 | } 54 | } else { 55 | threadNum = size / num + 1; 56 | result = new int[threadNum][num]; 57 | for (int i = 0; i < threadNum - 1; i++) { 58 | for (int j = 0; j < num; j++) { 59 | result[i][j] = list.get(i * num + j); 60 | } 61 | } 62 | for (int k = 0; k < remainder; k++) { 63 | result[threadNum - 1][k] = list.get((threadNum - 1) * num + k); 64 | } 65 | } 66 | return result; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/cc/zsakvo/ninecswd/utils/TxtUtils.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.ninecswd.utils; 2 | 3 | import android.os.Environment; 4 | 5 | import java.io.BufferedWriter; 6 | import java.io.File; 7 | import java.io.FileWriter; 8 | import java.io.IOException; 9 | 10 | /** 11 | * Created by akvo on 2018/3/20. 12 | */ 13 | 14 | public class TxtUtils { 15 | 16 | private String cachePath; 17 | 18 | public static void generateTXT(String bookName,String BookChapters){ 19 | new TxtUtils (bookName,BookChapters); 20 | } 21 | 22 | public TxtUtils(String bookName, String bookChapters){ 23 | File dir = new File (Environment.getExternalStorageDirectory().getPath()+"/99lib/txt/"); 24 | if (!dir.exists ()){ 25 | dir.mkdirs (); 26 | } 27 | cachePath = Environment.getExternalStorageDirectory().getPath()+"/99lib/txt/"+bookName+".txt"; 28 | writeStr (cachePath,bookChapters); 29 | } 30 | 31 | private void writeStr(String path,String bookChapters){ 32 | File file = new File(path); 33 | if (file.exists()) file.delete(); 34 | try { 35 | file.createNewFile(); 36 | BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter (file)); 37 | bufferedWriter.write(bookChapters); 38 | bufferedWriter.flush(); 39 | bufferedWriter.close(); 40 | } catch (IOException e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baidu.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bing.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_article.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 17 | 23 | 24 | 29 | 32 | 33 | 34 | 41 | 42 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_category.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 16 | 17 | 23 | 24 | 25 | 31 | 34 | 35 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_change_cover.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 15 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 18 | 25 | 26 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 18 | 19 | 20 | 27 | 33 | 34 | 40 | 43 | 44 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /app/src/main/res/layout/articlelist.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 26 | 27 | 35 | 36 | 37 | 38 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/res/layout/booklist.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 20 | 21 | 30 | 31 | 41 | 42 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/res/layout/categorylist.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/coverlist.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_99lib.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 14 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_article.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 11 | 14 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_category.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/n_activity_book_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 17 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | 44 | 45 | 57 | 58 | 59 | 67 | 68 | 72 | 80 | 81 | 82 | 88 | 89 | 93 | 94 | 101 | 102 | 109 | 110 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/menu/search_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/select_engine_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/99LibraryDownloader/7cdde347dd734830c0ee7dfa3b97cc0cf2d7dfbf/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/99LibraryDownloader/7cdde347dd734830c0ee7dfa3b97cc0cf2d7dfbf/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/99LibraryDownloader/7cdde347dd734830c0ee7dfa3b97cc0cf2d7dfbf/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/99LibraryDownloader/7cdde347dd734830c0ee7dfa3b97cc0cf2d7dfbf/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/99LibraryDownloader/7cdde347dd734830c0ee7dfa3b97cc0cf2d7dfbf/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/99LibraryDownloader/7cdde347dd734830c0ee7dfa3b97cc0cf2d7dfbf/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/99LibraryDownloader/7cdde347dd734830c0ee7dfa3b97cc0cf2d7dfbf/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/99LibraryDownloader/7cdde347dd734830c0ee7dfa3b97cc0cf2d7dfbf/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/99LibraryDownloader/7cdde347dd734830c0ee7dfa3b97cc0cf2d7dfbf/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 九九藏书 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/test/java/cc/zsakvo/a99demo/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package cc.zsakvo.a99demo; 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 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.0.1' 11 | 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | maven { url 'https://jitpack.io' } 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | ## Project-wide Gradle settings. 2 | # 3 | # For more details on how to configure your build environment visit 4 | # http://www.gradle.org/docs/current/userguide/build_environment.html 5 | # 6 | # Specifies the JVM arguments used for the daemon process. 7 | # The setting is particularly useful for tweaking memory settings. 8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m 9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 10 | # 11 | # When configured, Gradle will run in incubating parallel mode. 12 | # This option should only be used with decoupled projects. More details, visit 13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 14 | # org.gradle.parallel=true 15 | #Wed Feb 14 17:16:12 CST 2018 16 | systemProp.https.proxyPort=1087 17 | systemProp.http.proxyHost=127.0.0.1 18 | org.gradle.jvmargs=-Xmx1536m 19 | systemProp.https.proxyHost=127.0.0.1 20 | systemProp.http.proxyPort=1087 21 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/99LibraryDownloader/7cdde347dd734830c0ee7dfa3b97cc0cf2d7dfbf/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Feb 14 17:16:07 CST 2018 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-4.1-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 | --------------------------------------------------------------------------------