From 3a26f670c49a3d6ff27ca0f8ae55db8e7b8da30d Mon Sep 17 00:00:00 2001 From: mwang <8205347@qq.com> Date: Sat, 11 May 2019 23:21:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8B=86=E5=88=86api=20=E5=A2=9E=E5=8A=A0umeng?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zhuike/build.gradle | 76 ++- zhuike/proguard-rules.pro | 272 ++++++++++- zhuike/src/main/AndroidManifest.xml | 10 + .../com/novelbook/android/Activity_base.java | 12 + .../com/novelbook/android/Activity_cache.java | 101 +++- .../com/novelbook/android/BookActivity.java | 9 +- .../android/Fragments/BasicFragment.java | 13 + .../android/Fragments/Fragment_Shelf.java | 5 +- .../android/Fragments/Fragment_booklist.java | 2 +- .../android/Fragments/Fragment_paihang.java | 18 +- .../com/novelbook/android/Main2Activity.java | 8 +- .../java/com/novelbook/android/MyApp.java | 9 + .../novelbook/android/db/DownloadTask.java | 2 +- .../com/novelbook/android/netapi/HttpApi.java | 3 +- .../novelbook/android/netapi/RandomHost.java | 70 +++ .../novelbook/android/netapi/URLConstant.java | 30 +- .../novelbook/android/netapi/UrlFactory.java | 61 +++ .../android/netsubscribe/BookSubscribe.java | 36 +- .../android/netutils/HttpMethods.java | 26 +- .../novelbook/android/netutils/NetUtil.java | 41 ++ .../netutils/OnSuccessAndFaultSub.java | 14 +- .../android/netutils/RetryInterceptor.java | 124 +++++ .../android/service/ServiceDownload.java | 142 ++++-- .../service/ServiceDownloadIntent.java | 6 +- .../android/upgrade/ParseXmlService.java | 67 +++ .../android/upgrade/UpdateManager.java | 440 ++++++++++++++++++ .../com/novelbook/android/utils/BookUtil.java | 19 +- .../com/novelbook/android/utils/Config.java | 17 +- .../novelbook/android/utils/Constants.java | 2 + .../novelbook/android/utils/FileUtils.java | 9 + .../android/utils/NovelParseUtil.java | 16 - .../novelbook/android/utils/PageFactory.java | 7 +- zhuike/src/main/res/layout/activitycache.xml | 8 + .../res/layout/recycle_list_item_cache.xml | 24 +- .../main/res/layout/softupgrade_progress.xml | 0 .../main/res/menu/activity_main2_drawer.xml | 17 +- zhuike/src/main/res/values/strings.xml | 9 +- zhuike/zhuike.iml | 88 +++- 38 files changed, 1606 insertions(+), 207 deletions(-) create mode 100644 zhuike/src/main/java/com/novelbook/android/netapi/RandomHost.java create mode 100644 zhuike/src/main/java/com/novelbook/android/netapi/UrlFactory.java create mode 100644 zhuike/src/main/java/com/novelbook/android/netutils/RetryInterceptor.java create mode 100644 zhuike/src/main/java/com/novelbook/android/upgrade/ParseXmlService.java create mode 100644 zhuike/src/main/java/com/novelbook/android/upgrade/UpdateManager.java rename {qy => zhuike}/src/main/res/layout/softupgrade_progress.xml (100%) diff --git a/zhuike/build.gradle b/zhuike/build.gradle index e0b5616..c105d9e 100644 --- a/zhuike/build.gradle +++ b/zhuike/build.gradle @@ -12,23 +12,82 @@ android { versionName "1.0" // testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - // vectorDrawables.useSupportLibrary = true - - vectorDrawables.useSupportLibrary = true renderscriptTargetApi 24 //blurkit renderscriptSupportModeEnabled true //blurkit + multiDexEnabled true //突破65535 + manifestPlaceholders = [UMENG_CHANNEL_CALUE:"umeng"] //默认为uMeng + flavorDimensions "default" } buildTypes { - release { + debug { + // 显示Log + buildConfigField "boolean", "LOG_DEBUG", "true" + versionNameSuffix "-debug" minifyEnabled false + zipAlignEnabled false + shrinkResources false + signingConfig signingConfigs.debug + } + release { + // 不显示Log + buildConfigField "boolean", "LOG_DEBUG", "false" + //混淆 + minifyEnabled true + //Zipalign优化 + zipAlignEnabled true + + // 移除无用的resource文件 + shrinkResources true + + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + applicationVariants.all{ variant -> + variant.outputs.all{ output -> + def outFile = output.outputFile + if (outFile != null && outFile.name.endsWith(".apk")){ + def fileName = "${variant.productFlavors[0].name}" + ".apk" + outputFileName = fileName; + // output.outputFile = new File(outFile.parent, fileName); + } + } + + } } } + //渠道 + productFlavors { + // googleplay {} + huawei { applicationId "com.novelbook.android.huawei" + versionName "version-a-1.0"} + xiaomi { applicationId "com.novelbook.android.xiaomi" + versionName "version-a-1.0"} + /* wandoujia {} + baidu {} + yingyongbao {} + android360 {} + uc {} + umeng {} + meizu{} + */ + //批量配置 + productFlavors.all { flavor -> + flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] + } + + } + + + android { + lintOptions { + abortOnError false + } + } + sourceSets { main { jniLibs.srcDirs = ['libs'] @@ -40,9 +99,14 @@ android { } - } + + + + + + dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'com.android.support:appcompat-v7:28.0.0' @@ -84,4 +148,6 @@ dependencies { // implementation 'com.github.tangguna:SearchBox:1.0.1' implementation 'com.github.chengzipi:Searchbox:v1.0.0' implementation 'com.github.ixiaow:multilayout:1.0.0' + implementation 'com.umeng.umsdk:analytics:8.0.2' + implementation 'com.umeng.umsdk:common:2.0.2' } diff --git a/zhuike/proguard-rules.pro b/zhuike/proguard-rules.pro index f1b4245..21bf02e 100644 --- a/zhuike/proguard-rules.pro +++ b/zhuike/proguard-rules.pro @@ -1,21 +1,273 @@ # Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# By default, the flags in this file are appended to flags specified +# in D:\Android\sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html +# Add any project specific keep options here: + # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; +-keepclassmembers class fqcn.of.javascript.interface.for.webview { + public *; +} + +#ָѹ +-optimizationpasses 5 + +#ϴСд +-dontusemixedcaseclassnames + +#ȥԷǹĿ +-dontskipnonpubliclibraryclasses + + #Ż Żļ +# -dontoptimize + + #ԤУ +-dontpreverify + + #ʱǷ¼־ +-verbose + + # ʱõ㷨 +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +#ע +-keepattributes *Annotation* + +# Щ಻ +-keep public class * extends android.app.Fragment +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService +#v4 +-keep public class * extends android.support.v4.app.Fragment + + +#Ծ +-ignorewarning + +##¼ɵ־,gradle buildʱڱĿĿ¼## +#apk class ڲṹ +-dump proguard/class_files.txt +#δͳԱ +-printseeds proguard/seeds.txt +#г apk ɾĴ +-printusage proguard/unused.txt +#ǰӳ +-printmapping proguard/mapping.txt +########¼ɵ־ݣgradle buildʱ ڱĿĿ¼-end###### + +#v4v7 +-dontwarn android.support.** +-keep class com.google.** { *; } +-keep class android.support.v4.** +-dontwarn android.support.v4.** + +-keep class android.support.v7.** +-dontwarn android.support.v7.** +####ԼĿIJִԼõĵjarlibrary-end#### + + + +# native +-keepclasseswithmembernames class * { + native ; +} + +#Զؼ಻ +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet); +} + +#Զؼ಻ +-keepclassmembers class * extends android.app.Activity { + public void *(android.view.View); +} + +-keep public class * extends android.view.View { + public (android.content.Context); + public (android.content.Context, android.util.AttributeSet); + public (android.content.Context, android.util.AttributeSet, int); + public void set*(...); +} + +# Parcelable +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} + +# Serializable +-keepnames class * implements java.io.Serializable + +# Serializable enum Ҳ +-keepclassmembers class * implements java.io.Serializable { + static final long serialVersionUID; + private static final java.io.ObjectStreamField[] serialPersistentFields; + !static !transient ; + !private ; + !private ; + private void writeObject(java.io.ObjectOutputStream); + private void readObject(java.io.ObjectInputStream); + java.lang.Object writeReplace(); + java.lang.Object readResolve(); +} + +#ö enum ಻ +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keepclassmembers class * { + public void *ButtonClicked(android.view.View); +} + +#Դ +-keepclassmembers class **.R$* { + public static ; +} + +# ص +#-keepattributes Signature + +#ƳLogӡȼ־Ĵ룬ʽʱΪlogʹãΪֹlogӡĹʹãһʵַͨBuildConfig.DEBUGı +#-assumenosideeffects class android.util.Log { +# public static *** v(...); +# public static *** i(...); +# public static *** d(...); +# public static *** w(...); +# public static *** e(...); #} -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable +############################################################################################# +######################## ͨ ################################## +############################################################################################# + +####################### õģĻѡ ################################### +#gson +#õGsonģֱ⼸оܳɹȻᱨ +-keepattributes Signature +# Gson specific classes +-keep class sun.misc.Unsafe { *; } +# Application classes that will be serialized/deserialized over Gson +-keep class com.google.gson.** { *; } +-keep class com.google.gson.stream.** { *; } +-keep class com.google.**{*;} + +#butterknife +-keep class butterknife.** { *; } +-dontwarn butterknife.internal.** +-keep class **$$ViewBinder { *; } + +-keepclasseswithmembernames class * { + @butterknife.* ; +} + +-keepclasseswithmembernames class * { + @butterknife.* ; +} + +######õModuleֱappļ + +# ʹGson֮ĹҪʹJavaBean༴ʵ಻ +-keep class com.novelbook.android.bean.** { *; } +-keep class com.novelbook.android.db.** { *; } +#####ԼĿIJִԼõĵjarlibrary####### +#ڵǰapplication modulelibrary moduleʹ˵Ŀ⣬Ҫʽӹ +#-libraryjars xxx +#˷пڴʱͬһjarαָĴһֻҪӺԾͱijЩclass +#libarayʽ˿ԴĿ, keep modulebuild.gradleminifyEnabled=false + +# banner +-keep class com.youth.banner** { *; } +-keep interface com.youth.banner.** { *; } +-dontwarn com.youth.banner.** + +#LitePal +-keep class org.litepal.** { *; } +-keep class * extends org.litepal.crud.DataSupport { *; } + +#pagerslidingtabstrip +-keep class com.astuetz.** { *; } + + +#UMENG +-keep class com.umeng.** {*;} +-keepclassmembers class * { + public (org.json.JSONObject); +} + +#okhttp3 + +-dontwarn okio.** +-keepattributes Signature +-keepattributes *Annotation* +-keep class okhttp3.** { *; } +-keep interface okhttp3.** { *; } +-dontwarn okhttp3.** + +-dontwarn com.squareup.okhttp3.** +-keep class com.squareup.okhttp3.** { *;} +-dontwarn okhttp3.logging.** +-keep class okhttp3.internal.**{*;} +# -keep class com.novelbook.android.netapi.**{*;} + + +# Retrofit + +-dontwarn retrofit2.** +-keep class retrofit2.** { *; } +-keepattributes Signature +-keepattributes Exceptions + +-keepclasseswithmembers class * { + @retrofit2.http.* ; +} + +# RxJava RxAndroid +-dontwarn sun.misc.** +-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* { + long producerIndex; + long consumerIndex; +} +-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef { + rx.internal.util.atomic.LinkedQueueNode producerNode; +} +-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef { + rx.internal.util.atomic.LinkedQueueNode consumerNode; +} + +#glide +-keep public class * implements com.bumptech.glide.module.GlideModule +-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { + **[] $VALUES; + public *; +} + + # ڴлصonXXEvent**On*Listenerģܱ +-keepclassmembers class * { + void *(**On*Event); + void *(**On*Listener); +} + + -assumenosideeffects class android.util.Log { + public static boolean isLoggable(java.lang.String,int); + public static int v(...); + public static int i(...); + public static int w(...); + public static int d(...); + public static int e(...); + } + -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/zhuike/src/main/AndroidManifest.xml b/zhuike/src/main/AndroidManifest.xml index 77f87af..bfd507e 100644 --- a/zhuike/src/main/AndroidManifest.xml +++ b/zhuike/src/main/AndroidManifest.xml @@ -6,6 +6,9 @@ + + + + + + + + + + \ No newline at end of file diff --git a/zhuike/src/main/java/com/novelbook/android/Activity_base.java b/zhuike/src/main/java/com/novelbook/android/Activity_base.java index 89eaeb2..eeeedde 100644 --- a/zhuike/src/main/java/com/novelbook/android/Activity_base.java +++ b/zhuike/src/main/java/com/novelbook/android/Activity_base.java @@ -26,10 +26,12 @@ import com.novelbook.android.db.Novel; import com.novelbook.android.netsubscribe.MovieSubscribe; import com.novelbook.android.netutils.OnSuccessAndFaultListener; import com.novelbook.android.netutils.OnSuccessAndFaultSub; +import com.novelbook.android.upgrade.UpdateManager; import com.novelbook.android.utils.ImageUtil; import com.novelbook.android.utils.MyImageLoader; import com.novelbook.android.utils.OnItemClickListener; import com.novelbook.android.adapter.BookListAdapter; +import com.umeng.analytics.MobclickAgent; import java.util.ArrayList; import java.util.List; @@ -71,6 +73,7 @@ public abstract class Activity_base extends AppCompatActivity { setTitle(); initData(); initViews(); + } protected void setupToolbar(){ @@ -85,11 +88,13 @@ public abstract class Activity_base extends AppCompatActivity { @Override protected void onResume() { super.onResume(); + // MobclickAgent.onResume(this); } @Override protected void onPause(){ super.onPause(); hideProgress(); + // MobclickAgent.onPause(this); } protected BookListAdapter getBookListAdapter(List mDatas,int itemResourceId){ BookListAdapter mAdapter = new BookListAdapter(this ,mDatas,itemResourceId,new OnItemClickListener() @@ -252,6 +257,13 @@ public abstract class Activity_base extends AppCompatActivity { ImageUtil.loadImage( this, url , imageView); } + public void checkUpdate(boolean isSilence){ + UpdateManager manager = new UpdateManager(this); + if(isSilence) + manager.checkUpdateSilence(); + else + manager.checkUpdate(); + } /* class BookListAdapter extends RecyclerView.Adapter { private final int EMPTY_VIEW = 1; diff --git a/zhuike/src/main/java/com/novelbook/android/Activity_cache.java b/zhuike/src/main/java/com/novelbook/android/Activity_cache.java index 7438b59..e73f9a9 100644 --- a/zhuike/src/main/java/com/novelbook/android/Activity_cache.java +++ b/zhuike/src/main/java/com/novelbook/android/Activity_cache.java @@ -6,6 +6,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; +import android.os.Build; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; @@ -26,11 +27,14 @@ import com.novelbook.android.db.Chapter; import com.novelbook.android.db.DownloadTask; import com.novelbook.android.db.Novel; import com.novelbook.android.service.ServiceDownload; +import com.novelbook.android.utils.FileUtils; +import com.novelbook.android.utils.Fileutil; import com.novelbook.android.utils.ImageUtil; import org.litepal.LitePal; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import butterknife.BindView; @@ -40,6 +44,8 @@ public class Activity_cache extends Activity_base { public static final String TAG=Activity_cache.class.getSimpleName(); @BindView(R.id.recycleView) RecyclerView mRecyclerView; + @BindView(R.id.tvMsg) + TextView tvMsg; private List mData; private CacheAdapter mAdapter; @Override @@ -60,7 +66,33 @@ public class Activity_cache extends Activity_base { @Override protected void initData() { initiDownloadReceiver(); - mData = LitePal.findAll(DownloadTask.class); + + showProgressDialog(true,"正在加载..."); + + new Thread() { + + @Override + public void run() { + // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + mData = LitePal.where("id >0").order("id desc").find(DownloadTask.class);//findAll(DownloadTask.class); + + /* mData.sort(new Comparator(){ + public int compare(DownloadTask arg0, DownloadTask arg1) { + int i = arg0.getFinishedChpats()/arg0.getTotalChapts() > arg1.getFinishedChpats()/arg1.getTotalChapts() ?1:-1; + + return i; }});*/ + + // } + + handler.sendEmptyMessage(1); + + } + }.start(); + + } + + @Override + public void fillData() { mAdapter = new CacheAdapter(this,mData,R.layout.recycle_list_item_cache,new OnItemClickLitener() { @Override @@ -115,13 +147,6 @@ public class Activity_cache extends Activity_base { mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mRecyclerView.setAdapter(mAdapter ); - - - } - - @Override - public void fillData() { - } private IntentFilter filter; @@ -137,6 +162,16 @@ public class Activity_cache extends Activity_base { public void onReceive(Context context, Intent intent){ int taskId =0; int progress=0; + int status=0; + + tvMsg.setVisibility(View.GONE); + if( intent.hasExtra("network")){ + String txt = intent.getStringExtra("network"); + tvMsg.setText(txt); + tvMsg.setVisibility(View.VISIBLE); + return; + + } if( intent.hasExtra("progress")){ progress = intent.getIntExtra("progress",0); @@ -144,16 +179,28 @@ public class Activity_cache extends Activity_base { if( intent.hasExtra("taskId")){ taskId = intent.getIntExtra("taskId",0); } + if( intent.hasExtra("status")){ + status = intent.getIntExtra("status",0); + } + Log.d(TAG, String.format("onReceive: taskId %s progress %s ",taskId,progress)); for(DownloadTask dt : mData){ if(taskId == dt.getId()){ - dt.setFinishedChpats(progress); - if(dt.getDownSatus()!=DownloadTask.DownStatus.等待下载) { + dt.setFinishedChpats(progress); + if(status==1){ + dt.setStatus(1); + dt.setDownSatus(DownloadTask.DownStatus.下载完成); + }else + if(dt.getDownSatus()!=DownloadTask.DownStatus.暂停下载) { dt.setDownSatus(DownloadTask.DownStatus.正在下载); + dt.setStatus(0); } + + // dt = LitePal.find(DownloadTask.class,taskId); + }else{ - if(dt.getDownSatus()!=DownloadTask.DownStatus.正在下载) { + if(dt.getDownSatus()==DownloadTask.DownStatus.正在下载) { dt.setDownSatus(DownloadTask.DownStatus.排队中); } } @@ -240,28 +287,36 @@ public class Activity_cache extends Activity_base { holder.tvTitle.setText(mDatas.get(position).getNovelTitle()); holder.tvSource.setText(mDatas.get(position).getDomainName()); boolean finished = mData.get(position).getFinishedChpats() == mData.get(position).getTotalChapts(); - + holder.tvSize.setText( FileUtils.getCacheSizeK(mData.get(position).getNovelId())); if( mData.get(position).getTotalChapts() >0) { float progress = mData.get(position).getFinishedChpats() *100/ mData.get(position).getTotalChapts() ; - holder.tvProgress.setText(String.format("%s/%s",mData.get(position).getFinishedChpats() , mData.get(position).getTotalChapts())); + holder.tvProgress.setText(String.format("%s/%s",mData.get(position).getFinishedChpats() >mData.get(position).getTotalChapts()?mData.get(position).getTotalChapts():mData.get(position).getFinishedChpats() , mData.get(position).getTotalChapts())); + holder.barProgress.setProgress((int) progress); holder.tvStatus.setText( mData.get(position).getDownSatus() == DownloadTask.DownStatus.正在下载 ?"正在下载" - : mData.get(position).getDownSatus() == DownloadTask.DownStatus.等待下载? "暂停下载" :"休眠中"); + : mData.get(position).getDownSatus() == DownloadTask.DownStatus.暂停下载? "暂停下载" :"休眠中"); - holder.tvStatus.setText( mData.get(position).getStatus()==0 || mData.get(position).getFinishedChpats() >=mData.get(position).getTotalChapts() - ? holder.tvStatus.getText():"下载完成" ); + holder.tvStatus.setText( mData.get(position).getStatus()==1 || mData.get(position).getFinishedChpats() >=mData.get(position).getTotalChapts() + ? "下载完成" : holder.tvStatus.getText() ); - holder.tvStatus.setText( mData.get(position).getStatus()==0? holder.tvStatus.getText():"下载完成" ); holder.tvStatus.setText( mData.get(position).getDownSatus() == DownloadTask.DownStatus.排队中?"排队中": holder.tvStatus.getText() ); - holder.barProgress.setProgress((int)progress); + int img = R.mipmap.play; + img = mData.get(position).getDownSatus() == DownloadTask.DownStatus.正在下载 ? R.mipmap.pause : R.mipmap.play; + + holder.imgStart.setImageResource( img); + holder.imgStart.setEnabled(true); + if( mData.get(position).getStatus()==1|| mData.get(position).getFinishedChpats() >=mData.get(position).getTotalChapts()) { + holder.tvStatus.setText( "下载完成"); + holder.imgStart.setEnabled(false); + holder.imgStart.setImageResource( R.mipmap.pause); + + } + } // holder.imgStart.setVisibility(View.GONE); - int img = R.mipmap.play; - img = mData.get(position).getDownSatus() == DownloadTask.DownStatus.正在下载 ? R.mipmap.pause : R.mipmap.play; - holder.imgStart.setImageResource( img); holder.imgStart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -275,7 +330,7 @@ public class Activity_cache extends Activity_base { }else{ startDownloadService(mData.get(pos).getId(),false); holder.imgStart.setImageResource( R.mipmap.play); - mData.get(pos).setDownSatus(DownloadTask.DownStatus.等待下载); + mData.get(pos).setDownSatus(DownloadTask.DownStatus.暂停下载); } mData.get(pos).update( mData.get(pos).getId()); @@ -339,6 +394,8 @@ public class Activity_cache extends Activity_base { ImageView imgStart; @BindView(R.id.tvSource) TextView tvSource; + @BindView(R.id.tvSize) + TextView tvSize; public MyViewHolder(View view) { super(view); ButterKnife.bind(this, view); diff --git a/zhuike/src/main/java/com/novelbook/android/BookActivity.java b/zhuike/src/main/java/com/novelbook/android/BookActivity.java index 5ed9400..f979d36 100644 --- a/zhuike/src/main/java/com/novelbook/android/BookActivity.java +++ b/zhuike/src/main/java/com/novelbook/android/BookActivity.java @@ -497,7 +497,8 @@ public class BookActivity extends Activity_base { private void startDownloadService(int taskId) { Intent serviceIntent = getSvrIntent(); - serviceIntent.putExtra("taskId",taskId); + // serviceIntent.putExtra("taskId",taskId); + // serviceIntent.putExtra("start",true); startService(serviceIntent); } @@ -758,7 +759,11 @@ void onResponseProcess( String content ,String url){ } if(novelId == mNovel.getId()){ - btnCach.setText(progress +"/" +pageFactory.getChapters().size()); + try { + btnCach.setText(progress + "/" + pageFactory.getChapters().size()); + }catch (Exception e){ + Log.e(TAG, "onReceive: ", e); + } } diff --git a/zhuike/src/main/java/com/novelbook/android/Fragments/BasicFragment.java b/zhuike/src/main/java/com/novelbook/android/Fragments/BasicFragment.java index e5e250c..f9c3d5a 100644 --- a/zhuike/src/main/java/com/novelbook/android/Fragments/BasicFragment.java +++ b/zhuike/src/main/java/com/novelbook/android/Fragments/BasicFragment.java @@ -54,6 +54,7 @@ import com.novelbook.android.utils.ImageUtil; import com.novelbook.android.utils.MyImageLoader; import com.novelbook.android.utils.OnItemClickListener; import com.novelbook.android.utils.PageFactory; +import com.umeng.analytics.MobclickAgent; import com.youth.banner.loader.ImageLoader; import org.litepal.LitePal; @@ -391,4 +392,16 @@ public abstract class BasicFragment extends Fragment { public void loadData() { initData(); } //on tab changed + + @Override + public void onResume() { + super.onResume(); + MobclickAgent.onPageStart(TAG); + } + @Override + public void onPause(){ + super.onPause(); + hideProgress(); + MobclickAgent.onPageEnd(TAG); + } } diff --git a/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_Shelf.java b/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_Shelf.java index cb2a24d..07a80f5 100644 --- a/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_Shelf.java +++ b/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_Shelf.java @@ -356,9 +356,8 @@ void test(int maxAge){ } }); TextView tvCache =(TextView) bottomSheetDialog.findViewById(R.id.tvCache); - long size = FileUtils.getCacheSize(bookLists.get(position).getId()); - size = size/1024; - tvCache.setText(String.format("%sK",size)); + + tvCache.setText(FileUtils.getCacheSizeK(bookLists.get(position).getId())); LinearLayout llClearCache =(LinearLayout) bottomSheetDialog.findViewById(R.id.llClearCache); llClearCache.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { diff --git a/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_booklist.java b/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_booklist.java index cdd0795..d364950 100644 --- a/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_booklist.java +++ b/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_booklist.java @@ -274,7 +274,7 @@ public class Fragment_booklist extends BasicFragment { }else if(!TextUtils.isEmpty(keyWord)){ //搜索 // showProgressDialog(true, "正在加载搜索"); - mAdapter.setShowTop(true); + // mAdapter.setShowTop(true); BookSubscribe.getSearchNovelList( keyWord,pageNo, Constants.SEX, new OnSuccessAndFaultSub(successAndFaultListener, getActivity())); }else if(!TextUtils.isEmpty(history)){ loadHistory(); diff --git a/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_paihang.java b/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_paihang.java index af5a13a..1f1799f 100644 --- a/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_paihang.java +++ b/zhuike/src/main/java/com/novelbook/android/Fragments/Fragment_paihang.java @@ -20,6 +20,7 @@ import com.novelbook.android.R; import com.novelbook.android.adapter.JudgeNestedScrollView; import com.novelbook.android.bean.Progress; import com.novelbook.android.db.Novel; +import com.novelbook.android.netapi.RandomHost; import com.novelbook.android.netsubscribe.BookSubscribe; import com.novelbook.android.netutils.NetUtil; import com.novelbook.android.netutils.OnSuccessAndFaultListener; @@ -498,6 +499,8 @@ final String TAG = Fragment_paihang.class.getSimpleName(); } void getSearchTabTtitle(){ + + BookSubscribe.getSearchTitles(new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() { @Override public void onSuccess(String result) { @@ -508,17 +511,6 @@ final String TAG = Fragment_paihang.class.getSimpleName(); Constants.lstSex = GsonUtil.parserStringBlocks(result,"sex"); Constants.lstNt =GsonUtil.parserStringBlocks(result,"nt"); // Constants.lstProgress =GsonUtil.parserProgressBlocks(result,"progress"); - /* getActivity().runOnUiThread(new Runnable() { - - @Override - - public void run() { - initTabs(); // refresh ui 的操作代码 - - - } - - });*/ initTabs(); loadSearchData(); } catch (Exception e) { @@ -533,8 +525,8 @@ final String TAG = Fragment_paihang.class.getSimpleName(); public void onFault(String errorMsg) { //失败 Log.d(TAG, "error on get firstpage: " + errorMsg); - - + // getSearchTabTtitle(); + handler.sendEmptyMessage(0); } },getActivity())); diff --git a/zhuike/src/main/java/com/novelbook/android/Main2Activity.java b/zhuike/src/main/java/com/novelbook/android/Main2Activity.java index 62cf466..d4c9e15 100644 --- a/zhuike/src/main/java/com/novelbook/android/Main2Activity.java +++ b/zhuike/src/main/java/com/novelbook/android/Main2Activity.java @@ -69,6 +69,7 @@ public class Main2Activity extends Activity_base @Override protected void onCreate(Bundle savedInstanceState) { + getHostPolicy(); super.onCreate(savedInstanceState); //PageFactory.createPageFactory(this); app =(MyApp) getApplicationContext(); @@ -77,6 +78,7 @@ public class Main2Activity extends Activity_base // ButterKnife.bind(this); initialSexOption(); + checkUpdate(true); // getSearchTabTtitle(); } @@ -532,8 +534,10 @@ private int bottomSelectedIndex; // mFirstPage= gson.fromJson(result, FirstPage.class); try { JSONObject jsonObject = new JSONObject(result); - String resultstr = jsonObject.getString("nts"); - + String resultstr = jsonObject.getString("hosts"); + Config config =Config.createConfig(Main2Activity.this); + config.setBaseUrl(resultstr); + // config.setRootUrl( jsonObject.getString("masterDomains")); } catch (Exception e) { e.printStackTrace(); diff --git a/zhuike/src/main/java/com/novelbook/android/MyApp.java b/zhuike/src/main/java/com/novelbook/android/MyApp.java index a0bd2a0..af60b3d 100644 --- a/zhuike/src/main/java/com/novelbook/android/MyApp.java +++ b/zhuike/src/main/java/com/novelbook/android/MyApp.java @@ -3,9 +3,13 @@ package com.novelbook.android; import android.app.Application; import android.content.Context; +import com.novelbook.android.netutils.HttpMethods; +import com.novelbook.android.netutils.NetUtil; import com.novelbook.android.utils.Config; import com.novelbook.android.utils.LogcatHelper; import com.novelbook.android.utils.PageFactory; +import com.umeng.analytics.MobclickAgent; +import com.umeng.commonsdk.UMConfigure; import org.litepal.LitePal; @@ -14,6 +18,7 @@ public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); + HttpMethods.USERAGENT = NetUtil.getUserAgent(); applicationContext = getApplicationContext(); Config.createConfig(this); PageFactory.createPageFactory(this); @@ -23,6 +28,10 @@ public class MyApp extends Application { LitePal.initialize(this); } + public void initApi(){ + UMConfigure.init(applicationContext,UMConfigure.DEVICE_TYPE_PHONE,null); + MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO); + } public boolean exit() { System.exit(0); return true; diff --git a/zhuike/src/main/java/com/novelbook/android/db/DownloadTask.java b/zhuike/src/main/java/com/novelbook/android/db/DownloadTask.java index 9f56a5d..a30fbe4 100644 --- a/zhuike/src/main/java/com/novelbook/android/db/DownloadTask.java +++ b/zhuike/src/main/java/com/novelbook/android/db/DownloadTask.java @@ -91,7 +91,7 @@ public class DownloadTask extends LitePalSupport implements Serializable { } public static enum DownStatus{ - 初始状态,等待下载, 正在下载,排队中,下载完成 + 初始状态,暂停下载, 正在下载,排队中,下载完成 } } diff --git a/zhuike/src/main/java/com/novelbook/android/netapi/HttpApi.java b/zhuike/src/main/java/com/novelbook/android/netapi/HttpApi.java index a2633c5..c975774 100644 --- a/zhuike/src/main/java/com/novelbook/android/netapi/HttpApi.java +++ b/zhuike/src/main/java/com/novelbook/android/netapi/HttpApi.java @@ -91,7 +91,8 @@ public interface HttpApi { @GET("page/hot-keywords") Observable getSearchHotKeys(); - + @GET("download/version.xml") + Observable getVersion(); } diff --git a/zhuike/src/main/java/com/novelbook/android/netapi/RandomHost.java b/zhuike/src/main/java/com/novelbook/android/netapi/RandomHost.java new file mode 100644 index 0000000..fb1bdad --- /dev/null +++ b/zhuike/src/main/java/com/novelbook/android/netapi/RandomHost.java @@ -0,0 +1,70 @@ +package com.novelbook.android.netapi; + +import java.util.Random; + + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +public class RandomHost { + + private static final int MAX = 10; + private static final Random random = new Random(); + //private static final Map indexsMap = new HashMap(); + + private JSONObject hosts = null; + private String uri = null; + + private int[] indexs = new int[10]; + + public RandomHost(JSONObject hosts, String uri) throws JSONException { + this.hosts = hosts; + this.uri = uri; + String hostName = UrlFactory.getHost(uri); + indexs = new int[MAX]; + JSONArray us = hosts.getJSONArray(hostName); + int maxFixIndex = us == null ||us.length()==0 ? 0 :us.length(); + if (maxFixIndex > 0) { + randomFill(indexs, 0, 0, maxFixIndex - 1); + } + for (int i = maxFixIndex; i < 10; i++) { + indexs[i] = i; + } + //randomFill(indexs, maxFixIndex, maxFixIndex, MAX - 1); + } + + private static boolean in(int[] values, int maxIndex, int value) { + for (int i = 0; i <= maxIndex; i++) { + if (values[i] == value) return true; + } + + return false; + } + + private static void randomFill(int[] indexs, int fromIndex, int min, int max) { + for (int i = min; i <= max; i++) { + while (true) { + int value = random.nextInt(max + 1); + if (value < min) continue; + if (in(indexs, fromIndex + i - min - 1, value)) continue; + indexs[ fromIndex + i - min] = value; + break; + } + } + } + + private int currentIndex = 0; + public String next() { + if (currentIndex >= indexs.length ) + return ""; + else { + try { + return UrlFactory.getUrl(hosts, uri, indexs[currentIndex++]); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return ""; + } +} diff --git a/zhuike/src/main/java/com/novelbook/android/netapi/URLConstant.java b/zhuike/src/main/java/com/novelbook/android/netapi/URLConstant.java index b942b64..b6ee494 100644 --- a/zhuike/src/main/java/com/novelbook/android/netapi/URLConstant.java +++ b/zhuike/src/main/java/com/novelbook/android/netapi/URLConstant.java @@ -4,13 +4,17 @@ import android.text.TextUtils; import com.novelbook.android.utils.Config; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + /** * Created by 眼神 on 2018/3/27. */ public class URLConstant { //存放全部的URL(可分为开发、测试、正式) - private static String BASE_URL = Config.getInstance().getBaseUrl() ;//https://api.douban.com/v2/movie/"; + private static String ROOT_URL = Config.getInstance().getRootUrl() ;//https://api.douban.com/v2/movie/"; public static String[] BASE_URLS = {"http://xiaoshuofenxiang.com/api/"}; @@ -18,29 +22,29 @@ public class URLConstant { * 取新的baseURL * @return */ - public static String newBaseUrl(){ + public static String newRootUrl(){ + for (String url:BASE_URLS) { - if(!url.equals(BASE_URL)){ - BASE_URL = url; + if(!url.equals(ROOT_URL)){ + ROOT_URL = url; break; } } - if(! Config.getInstance().getBaseUrl().equals(BASE_URL)){ - Config.getInstance().setBaseUrl(BASE_URL); + if(! Config.getInstance().getBaseUrl().equals(ROOT_URL)){ + Config.getInstance().setBaseUrl(ROOT_URL); } - return BASE_URL; + return ROOT_URL; } /** * app初始化取上次保存的baseurl * @return */ - public static String getBaseUrl(){ - BASE_URL=Config.getInstance().getBaseUrl(); - if(TextUtils.isEmpty(BASE_URL)){ - BASE_URL = newBaseUrl(); - } - return BASE_URL; + public static String getRootUrl() { + + ROOT_URL=Config.getInstance().getRootUrl(); + + return ROOT_URL; } diff --git a/zhuike/src/main/java/com/novelbook/android/netapi/UrlFactory.java b/zhuike/src/main/java/com/novelbook/android/netapi/UrlFactory.java new file mode 100644 index 0000000..ecd3bac --- /dev/null +++ b/zhuike/src/main/java/com/novelbook/android/netapi/UrlFactory.java @@ -0,0 +1,61 @@ +package com.novelbook.android.netapi; + + + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +public class UrlFactory { + + public static String getHost(String uri) { + String key = "master"; + if (uri.startsWith("/api/search/")) { + key = "search"; + } else if (uri.startsWith("/api/n/")) { + key = "novel"; + } else if (uri.startsWith("/api/novels/")) { + key = "novelsbydot"; + } else if (uri.startsWith("/api/r/")) { + key = "report"; + } else if (uri.startsWith("/api/page/")) { + key = "page"; + } else if (uri.startsWith("/api/u/")) { + key = "user"; + } + return key; + } + public static String getUrl(JSONObject host, String uri, int index) throws JSONException { + if (uri == null) return ""; + + String key = getHost(uri); + JSONArray us = null; + if (host != null) { + us = host.getJSONArray(key); + if (us != null && us.length() > index) { + return us.getString(index) ;//+ uri; + } + } + + int value = (us == null || us.length()==0) ? index : index - us.length(); + + int second = 90 + 7; + int a1 = value / 2 +1; + int a2 = value % 2; + return String.format("http://%s%s%s.%s%s%s%s.com", key.charAt(0), (char)(second + a2), a1, "xiao", "shuo", "fen", "xiang"); + } + + public static void main(String[] args) { + /*String[] keys = new String[] {"/api/search/", "/api/n/", "/api/novels/", "/api/r/", "/api/page/", "/api/u/", "/api/g/"}; + String text = FileUtil.read("C:\\MyWorkSpace\\WorkRoom\\cms4\\app\\xiaoshuofenxiang\\web\\api\\g\\Setting.json", "utf-8"); + JSONObject hosts = JSONObject.parseObject(text).getJSONObject("data").getJSONObject("hosts"); + + for (String key : keys ) { + RandomHost rh = new RandomHost(hosts, key); + for (int i = 0; i < 11; i++) { + String url = rh.next(); + System.out.println(String.format("for %s and index = %s, url=%s", key, i, url)); + } + }*/ + } +} diff --git a/zhuike/src/main/java/com/novelbook/android/netsubscribe/BookSubscribe.java b/zhuike/src/main/java/com/novelbook/android/netsubscribe/BookSubscribe.java index 04b21b9..5285541 100644 --- a/zhuike/src/main/java/com/novelbook/android/netsubscribe/BookSubscribe.java +++ b/zhuike/src/main/java/com/novelbook/android/netsubscribe/BookSubscribe.java @@ -18,74 +18,78 @@ public class BookSubscribe { HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getMastDomain(DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getMasterDomain(); + Observable observable = HttpMethods.getInstance("/api/g").getHttpApi().getMasterDomain(); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getNovel(int novelId,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getNovel(novelId); + Observable observable = HttpMethods.getInstance(String.format("/api/n/%s",novelId)).getHttpApi().getNovel(novelId); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getNovelSites(int novelId,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getNovelSites(novelId); + Observable observable = HttpMethods.getInstance(String.format("/api/n/%s/mulu-urls",novelId)).getHttpApi().getNovelSites(novelId); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getSiteRule(String domain,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getNovelRule(domain); + Observable observable = HttpMethods.getInstance(String.format("/api/s/%s.json",domain)).getHttpApi().getNovelRule(domain); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getFirstPage(int sex,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getFirstPage(sex); + Observable observable = HttpMethods.getInstance(String.format("/api/page/index" )).getHttpApi().getFirstPage(sex); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getCates(int sex,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getCates(sex); + Observable observable = HttpMethods.getInstance("/api/page/noveltype").getHttpApi().getCates(sex); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getCateNovelList(String cate,int pageno,int sex,int progress,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getCateNovels(cate,pageno,sex,progress); + Observable observable = HttpMethods.getInstance(String.format("/api/search/nt/%s/%s",cate,pageno ) ).getHttpApi().getCateNovels(cate,pageno,sex,progress); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getNovelPaihang(String fn,int sex,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getNovelPaihang(fn,sex); + Observable observable = HttpMethods.getInstance("/api/page/rank").getHttpApi().getNovelPaihang(fn,sex); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getNovelsRelated(int novelId,int sex,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getNovelsRelated(novelId,sex); + Observable observable = HttpMethods.getInstance(String.format("/api/n/%s/about",novelId ) ).getHttpApi().getNovelsRelated(novelId,sex); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getNovelsSameAuthor(int novelId,int sex,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getNovelsSameAuthor(novelId,sex); + Observable observable = HttpMethods.getInstance(String.format("/api/n/%s/author",novelId ) ).getHttpApi().getNovelsSameAuthor(novelId,sex); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getSiteRanks( int sex,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getSiteRanks(sex); + Observable observable = HttpMethods.getInstance("/api/page/siteranks").getHttpApi().getSiteRanks(sex); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getSiteRankDetail( String fn,int pageNo,int sex,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getSiteRankDetail(fn,pageNo,sex); + Observable observable = HttpMethods.getInstance("/api/page/siteranks").getHttpApi().getSiteRankDetail(fn,pageNo,sex); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getSearchNovelList( String keyWord,int pageNo,int sex,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getSeachNolvelist(keyWord,pageNo,sex); + Observable observable = HttpMethods.getInstance(String.format("/api/search/%s/%s",keyWord ,pageNo)).getHttpApi().getSeachNolvelist(keyWord,pageNo,sex); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getSearchTitles(DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getSearchTitles(); + Observable observable = HttpMethods.getInstance("/api/page/topdata").getHttpApi().getSearchTitles(); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getHotKeyWords(DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getSearchHotKeys(); + Observable observable = HttpMethods.getInstance("/api/page/hot-keywords").getHttpApi().getSearchHotKeys(); HttpMethods.getInstance().toSubscribe(observable, subscriber); } public static void getNovelsByIds(String ids,DisposableObserver subscriber){ - Observable observable = HttpMethods.getInstance().getHttpApi().getNovelsByIds(ids); + Observable observable = HttpMethods.getInstance("/api/novels").getHttpApi().getNovelsByIds(ids); + HttpMethods.getInstance().toSubscribe(observable, subscriber); + } + public static void getVersion(DisposableObserver subscriber){ + Observable observable = HttpMethods.getInstance("download/version.xml").getHttpApi().getVersion(); HttpMethods.getInstance().toSubscribe(observable, subscriber); } diff --git a/zhuike/src/main/java/com/novelbook/android/netutils/HttpMethods.java b/zhuike/src/main/java/com/novelbook/android/netutils/HttpMethods.java index bff4670..904b403 100644 --- a/zhuike/src/main/java/com/novelbook/android/netutils/HttpMethods.java +++ b/zhuike/src/main/java/com/novelbook/android/netutils/HttpMethods.java @@ -6,12 +6,13 @@ import android.util.Log; import com.novelbook.android.MyApp; import com.novelbook.android.netapi.HttpApi; +import com.novelbook.android.netapi.RandomHost; import com.novelbook.android.netapi.URLConstant; import com.novelbook.android.utils.CommonUtil; import com.novelbook.android.utils.FileUtils; - +import org.json.JSONException; import java.io.File; import java.io.IOException; @@ -42,8 +43,8 @@ import retrofit2.Retrofit; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; -import static com.novelbook.android.netapi.URLConstant.getBaseUrl; -import static com.novelbook.android.netapi.URLConstant.newBaseUrl; +import static com.novelbook.android.netapi.URLConstant.getRootUrl; +import static com.novelbook.android.netapi.URLConstant.newRootUrl; public class HttpMethods { public String TAG = "HttpMethods"; @@ -52,6 +53,7 @@ public class HttpMethods { private static final int DEFAULT_CONNECT_TIMEOUT = 5; private static final int DEFAULT_WRITE_TIMEOUT = 5; private static final int DEFAULT_READ_TIMEOUT = 5; + public static String USERAGENT=""; private Retrofit retrofit; private HttpApi httpApi; /** @@ -70,7 +72,7 @@ public class HttpMethods { .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create())//json转换成JavaBean .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .baseUrl(getBaseUrl()) + .baseUrl(getRootUrl()) .build(); httpApi = retrofit.create(HttpApi.class); } @@ -81,6 +83,12 @@ public class HttpMethods { } + //获取单例 + public static HttpMethods getInstance(String keyUrl) { + SingletonHolder.INSTANCE.changeBaseUrl(NetUtil.getUrl(keyUrl)); + return SingletonHolder.INSTANCE; + } + //获取单例 public static HttpMethods getInstance() { return SingletonHolder.INSTANCE; @@ -104,6 +112,8 @@ public class HttpMethods { } public void changeBaseUrl(String baseUrl) { + okHttpBuilder.addInterceptor(new RetryInterceptor()); + // okHttpBuilder.retryOnConnectionFailure(false); retrofit = new Retrofit.Builder() .client(okHttpBuilder.build()) .addConverterFactory(GsonConverterFactory.create()) @@ -112,9 +122,9 @@ public class HttpMethods { .build(); httpApi = retrofit.create(HttpApi.class); } - public void changeBaseUrl() { + /* public void changeBaseUrl() { changeBaseUrl(newBaseUrl()); - } + }*/ /** * 获取httpService * @@ -167,7 +177,7 @@ public class HttpMethods { // .addHeader("Accept", "application/json") // .addHeader("Content-Type", "application/json; charset=utf-8") // .addHeader("Device", "Android") - .removeHeader("User-Agent").addHeader("User-Agent",NetUtil.getUserAgent()) //加 随机agent + .removeHeader("User-Agent").addHeader("User-Agent",USERAGENT) //加 随机agent .tag(NetUtil.currentRequestTag) .method(originalRequest.method(), originalRequest.body()); @@ -207,6 +217,8 @@ public class HttpMethods { //错误重连 okHttpBuilder.retryOnConnectionFailure(true); + + // Install the all-trusting trust manager final SSLContext sslContext; try { diff --git a/zhuike/src/main/java/com/novelbook/android/netutils/NetUtil.java b/zhuike/src/main/java/com/novelbook/android/netutils/NetUtil.java index c3f0ffb..307ef7c 100644 --- a/zhuike/src/main/java/com/novelbook/android/netutils/NetUtil.java +++ b/zhuike/src/main/java/com/novelbook/android/netutils/NetUtil.java @@ -8,6 +8,12 @@ import android.util.Log; import android.widget.ImageView; import com.novelbook.android.MyApp; +import com.novelbook.android.netapi.RandomHost; +import com.novelbook.android.netapi.URLConstant; +import com.novelbook.android.utils.Config; + +import org.json.JSONException; +import org.json.JSONObject; import java.util.Random; @@ -22,10 +28,45 @@ public class NetUtil { private static final String TAG= NetUtil.class.getSimpleName(); public static int currentRequestTag =0; + public static String hosts; + public static String getUrl(String key){ + try { + JSONObject jsonObject = getHost(); + if(jsonObject==null && key == "/api/g"){ + return URLConstant.getRootUrl(); + } + RandomHost rh = new RandomHost(jsonObject,key); + String url = rh.next(); + if(!url.endsWith("/api/")){ + url+="/api/"; + } + return url; + } catch (JSONException e) { + e.printStackTrace(); + } + return ""; + } + public static JSONObject getHost() { + if (TextUtils.isEmpty(hosts)) { + Config config = Config.getInstance(); + hosts = config.getBaseUrl(); + } + Log.d(TAG, "getUrl: host is " + hosts); + if (TextUtils.isEmpty(hosts)) { + Log.e(TAG, "getHosts: error on get hosts"); + } + + try { + return new JSONObject(hosts); + } catch (Exception er) { + + } + return null; + } /** * 判断是否有网络连接 * diff --git a/zhuike/src/main/java/com/novelbook/android/netutils/OnSuccessAndFaultSub.java b/zhuike/src/main/java/com/novelbook/android/netutils/OnSuccessAndFaultSub.java index 486cda7..616e673 100644 --- a/zhuike/src/main/java/com/novelbook/android/netutils/OnSuccessAndFaultSub.java +++ b/zhuike/src/main/java/com/novelbook/android/netutils/OnSuccessAndFaultSub.java @@ -14,8 +14,10 @@ import java.net.UnknownHostException; import javax.net.ssl.SSLHandshakeException; import io.reactivex.observers.DisposableObserver; +import okhttp3.HttpUrl; import okhttp3.ResponseBody; import retrofit2.HttpException; +import retrofit2.Response; /** * Created by 眼神 on 2018/3/27. @@ -125,6 +127,16 @@ public class OnSuccessAndFaultSub extends DisposableObserver mOnSuccessAndFaultListener.onFault("安全证书异常"); } else if (e instanceof HttpException) {//请求的地址不存在 int code = ((HttpException) e).code(); + + Response response = ((HttpException) e).response(); + HttpUrl url= response.raw().request().url(); + String host = url.host(); + String key = url.query(); + + + + + if (code == 504) { Toast.makeText(context,"网络异常,请检查您的网络状态",Toast.LENGTH_LONG).show(); mOnSuccessAndFaultListener.onFault("网络异常,请检查您的网络状态"); @@ -142,7 +154,7 @@ public class OnSuccessAndFaultSub extends DisposableObserver //sleep 200 mOnSuccessAndFaultListener.onFault("服务限制"); }else if(code == 502) { - HttpMethods.getInstance().changeBaseUrl(); //更新基本信息 + // HttpMethods.getInstance().changeBaseUrl(); //更新基本信息 try { Toast.makeText(context, "服务器开小差了,请重试", Toast.LENGTH_LONG).show(); }catch (Exception e3){ diff --git a/zhuike/src/main/java/com/novelbook/android/netutils/RetryInterceptor.java b/zhuike/src/main/java/com/novelbook/android/netutils/RetryInterceptor.java new file mode 100644 index 0000000..401a487 --- /dev/null +++ b/zhuike/src/main/java/com/novelbook/android/netutils/RetryInterceptor.java @@ -0,0 +1,124 @@ +package com.novelbook.android.netutils; + +import android.text.TextUtils; +import android.util.Log; + +import com.novelbook.android.netapi.RandomHost; + +import org.json.JSONException; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class RetryInterceptor implements Interceptor { + private static final String TAG=RetryInterceptor.class.getSimpleName(); + int RetryCount = 13; + RandomHost rh ; + public RetryInterceptor(){ + + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + // try the request + Response response = doRequest(chain, request); + if(response!=null &&( response.isSuccessful() || response.code() ==200)){ + return response; + } + + int tryCount = 0; + String oldUrl = request.url().toString(); + + + String key = oldUrl.substring(oldUrl.lastIndexOf(".com/")+5,oldUrl.length()); + if(rh==null) + { + try { + rh = new RandomHost(NetUtil.getHost(), key); + Log.d(TAG, "HttpMethods intercept: create new RandomHost--------------------------"); + } catch (JSONException e) { + Log.e(TAG, "intercept: ", e); + } + } + String url =oldUrl; + while ( (response==null ||!response.isSuccessful()) && tryCount <= RetryCount) { + + // if(tryCount>3) + { //三次不成功后换其他url + url = switchServer(key); + if (url.equals(oldUrl)) { + url = switchServer(key); + } + if(TextUtils.isEmpty(url)){ + return null; + } + } + Request newRequest = null; + try { + newRequest = request.newBuilder().url(url).build(); + } catch (Exception e) { + Log.e(TAG, "HttpMethods intercept: "+url); + Log.e(TAG, "HttpMethods intercept: ", e); + return null; + } + + + Log.d("HttpMethods intercept", "Request is not successful - " + tryCount); + + Log.d(TAG, "HttpMethods intercept: trying url is "+url); + tryCount++; + // retry the request + response = doRequest(chain, newRequest); + } + if (response == null) { + throw new IOException(); + } + return response; + + } + + private Response doRequest(Chain chain, Request request) { + Response response = null; + try { + response = chain.proceed(request); + } catch (Exception e) { + } + return response; + } + + private String switchServer(String key) { + String newUrl = rh.next(); + + if(TextUtils.isEmpty(newUrl)){ + return newUrl; + } + + if(!newUrl.endsWith("/")){ + newUrl+="/"; + } + return newUrl +key; + } + + + + + + + + + + + + + + + + + + + +} diff --git a/zhuike/src/main/java/com/novelbook/android/service/ServiceDownload.java b/zhuike/src/main/java/com/novelbook/android/service/ServiceDownload.java index 85ecc67..6482436 100644 --- a/zhuike/src/main/java/com/novelbook/android/service/ServiceDownload.java +++ b/zhuike/src/main/java/com/novelbook/android/service/ServiceDownload.java @@ -15,6 +15,7 @@ import com.novelbook.android.db.Chapter; import com.novelbook.android.db.DownloadTask; import com.novelbook.android.db.SiteRule; import com.novelbook.android.netutils.HttpMethods; +import com.novelbook.android.netutils.NetUtil; import com.novelbook.android.utils.BookUtil; import com.novelbook.android.utils.NovelParseUtil; @@ -146,7 +147,7 @@ public class ServiceDownload extends Service { cancelId.add(taskId); for(DownloadTask t : downloadTasks){ if( t.getId() == taskId){ - t.setDownSatus(DownloadTask.DownStatus.等待下载); + t.setDownSatus(DownloadTask.DownStatus.暂停下载); break; } } @@ -246,11 +247,20 @@ public class ServiceDownload extends Service { /* if(msg.what ==1){ startTask(); }else*/ - if(msg.what==2){ + if (msg.what == 2) { + if(!NetUtil.isNetworkConnected()) { + /* Intent broadcastIntent = new Intent(); + broadcastIntent.setAction("ServiceDownload.ChapterContent.finished"); + broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT); + broadcastIntent.putExtra("network", "没有网络了,下载失败"); + sendBroadcast(broadcastIntent);*/ + return; + } + int tIndex = msg.getData().getInt("tIndex"); - if(tIndex>=downloadTasks.size()) { + if (tIndex >= downloadTasks.size()) { return; } int taskId = downloadTasks.get(tIndex).getId(); @@ -262,61 +272,98 @@ public class ServiceDownload extends Service { } */ - if(tasksMap.get(taskId)==null){ + if (tasksMap.get(taskId) == null) { return; } - Log.d(TAG,String.format("%s start new chapt download---- taskId :%s, chapter count %s,chaptIndex %s",TAG + Log.d(TAG, String.format("%s start new chapt download---- taskId :%s, chapter count %s,chaptIndex %s", TAG , processingTask.getId(), - tasksMap.get(processingTask.getId()).size(),chaptIndex )); + tasksMap.get(processingTask.getId()).size(), chaptIndex)); - // if(taskIndex==tIndex+1){ + // if(taskIndex==tIndex+1){ - Intent broadcastIntent = new Intent(); + Intent broadcastIntent = new Intent(); + broadcastIntent.setAction("ServiceDownload.ChapterContent.finished"); + broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT); + broadcastIntent.putExtra("progress", processingTask.getFinishedChpats() > processingTask.getTotalChapts() ? processingTask.getTotalChapts() : processingTask.getFinishedChpats()); + broadcastIntent.putExtra("novelId", processingTask.getNovelId()); + broadcastIntent.putExtra("taskId", processingTask.getId()); + sendBroadcast(broadcastIntent); + + // } + // + if (downloadTasks.get(tIndex).getDownSatus() != DownloadTask.DownStatus.正在下载) { + + startNewTask(); + return; + + } + // if( Chapter.getUnCachedChapters(taskId).size() >0 ){ + //if( tasksMap.get(taskId).size()-1 > chaptIndex){ + + if (tasksMap.get(taskId).size() - 1 > chaptIndex) { + chaptIndex++; + // } + + /* else{ + startNewTask(); + return; + }*/ + + + } else { + Log.d(TAG, String.format("%s task done ---- taskId :%s, chapter count %s,chaptIndex %s", TAG, processingTask.getId(), + tasksMap.get(processingTask.getId()).size(), chaptIndex)); + //章节全部处理完毕了 + + if (taskId == processingTask.getId() + && tasksMapDone.get(taskId) != null + && tasksMapDone.get(taskId).size() == tasksMap.get(taskId).size()) { + int abc = 1; + abc++; + processingTask.setFinishedChpats(processingTask.getTotalChapts()); + processingTask.setStatus(1); + processingTask.setDownSatus(DownloadTask.DownStatus.下载完成); + processingTask.update(processingTask.getId()); + tasksMap.remove(taskId); + + + broadcastIntent = new Intent(); broadcastIntent.setAction("ServiceDownload.ChapterContent.finished"); broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT); - broadcastIntent.putExtra("progress", processingTask.getFinishedChpats()>processingTask.getTotalChapts() ?processingTask.getTotalChapts():processingTask.getFinishedChpats()); - broadcastIntent.putExtra("novelId", processingTask.getNovelId()); + broadcastIntent.putExtra("progress", processingTask.getTotalChapts()); + broadcastIntent.putExtra("status", processingTask.getStatus()); broadcastIntent.putExtra("taskId", processingTask.getId()); sendBroadcast(broadcastIntent); - // } - - if( tasksMap.get(taskId).size()-1 > chaptIndex){ - if( downloadTasks.get(tIndex).getDownSatus() == DownloadTask.DownStatus.正在下载) { - chaptIndex++; - }else{ - return; - } - - }else{ - Log.d(TAG,String.format("%s task done ---- taskId :%s, chapter count %s,chaptIndex %s",TAG , processingTask.getId(), - tasksMap.get(processingTask.getId()).size(),chaptIndex )); - //章节全部处理完毕了 - - if(taskId == processingTask.getId()) { - int abc = 1; - abc++; - if(tasksMap.get(taskId).size() == tasksMapDone.get(taskId).size()) { - processingTask.setStatus(1); - processingTask.update(processingTask.getId()); - // tasksMap.remove(processingTask.getId()); //会不会线程冲突? - } - } - //startTask(); //auto start next task + startNewTask(); return; } - doDownloadContent(tIndex,chaptIndex); + doDownloadContent(tIndex, chaptIndex); } } }; + void startNewTask(){ + if(!NetUtil.isNetworkConnected()){ + Intent broadcastIntent = new Intent(); + broadcastIntent.setAction("ServiceDownload.ChapterContent.finished"); + broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT); + + broadcastIntent.putExtra("network", "没有网络了,下载失败"); + sendBroadcast(broadcastIntent); + + return; + } + taskIndex=0; + startTask(); //auto start next task + } private void stopTask(int taskId) { @@ -354,7 +401,9 @@ public class ServiceDownload extends Service { * auto next task */ private void startTask() { - if ( downloadTasks.size()==0){ + if ( downloadTasks.size()==0 || downloadTasks.size() <=taskIndex){ + Log.d(TAG,"ServiceDownload No Task to do, exit."); + return; } if(processingTask!=null) { @@ -363,15 +412,17 @@ public class ServiceDownload extends Service { Log.d(TAG,"ServiceDownload start task to download,index " +taskIndex); - if(downloadTasks.size() <=taskIndex){ + /* if(downloadTasks.size() <=taskIndex){ taskIndex=0; processingTask =null; // Log.d(TAG,"No task to download."); // return; - } + }*/ processingTask = downloadTasks.get(taskIndex); - if(processingTask.getDownSatus()== DownloadTask.DownStatus.等待下载){ + if(processingTask.getDownSatus()== DownloadTask.DownStatus.暂停下载 + ||processingTask.getDownSatus()== DownloadTask.DownStatus.下载完成 + ){ taskIndex++; startTask(); return; @@ -397,7 +448,15 @@ public class ServiceDownload extends Service { if(chps!=null && chps.size()>0 && chps.size() >chaptIndex) { Chapter chapter = chps.get(chaptIndex); - if (TextUtils.isEmpty(chapter.getChapterPath())) { + /* while(!NetUtil.isNetworkConnected() ){ + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }*/ + + if (NetUtil.isNetworkConnected() && TextUtils.isEmpty(chapter.getChapterPath())) { try { ServiceDownload(taskIndex,chapter); } catch (JSONException e) { @@ -510,7 +569,8 @@ public class ServiceDownload extends Service { } try { - String bodyStr = body.string(); + // NovelParseUtil.enconding(body, siteRuleMap.get(chapter.getNovelId()).getEncoding()); + String bodyStr =NovelParseUtil.enconding(body, siteRuleMap.get(chapter.getNovelId()).getEncoding());; //body.string(); String title = chapter.getChapterName(); String chapterContent = title+ "\n" + NovelParseUtil.getChapterContent(bodyStr, siteJson); char[] buf = chapterContent.toCharArray(); diff --git a/zhuike/src/main/java/com/novelbook/android/service/ServiceDownloadIntent.java b/zhuike/src/main/java/com/novelbook/android/service/ServiceDownloadIntent.java index d64a61c..750d2be 100644 --- a/zhuike/src/main/java/com/novelbook/android/service/ServiceDownloadIntent.java +++ b/zhuike/src/main/java/com/novelbook/android/service/ServiceDownloadIntent.java @@ -155,7 +155,7 @@ public class ServiceDownloadIntent extends IntentService { private void stopTask(int taskId) { for(DownloadTask dt : downloadTasks){ if(dt.getId() == taskId){ - dt.setDownSatus(DownloadTask.DownStatus.等待下载); + dt.setDownSatus(DownloadTask.DownStatus.暂停下载); } } @@ -169,7 +169,7 @@ public class ServiceDownloadIntent extends IntentService { startTask(); }else if(msg.what==2){ - if( downloadTasks.get(taskIndex).getDownSatus() == DownloadTask.DownStatus.等待下载){ + if( downloadTasks.get(taskIndex).getDownSatus() == DownloadTask.DownStatus.暂停下载){ return; } if(tasksMap.get(processingTask.getId())==null){ @@ -229,7 +229,7 @@ public class ServiceDownloadIntent extends IntentService { } processingTask = downloadTasks.get(taskIndex); - if(processingTask.getDownSatus()== DownloadTask.DownStatus.等待下载){ + if(processingTask.getDownSatus()== DownloadTask.DownStatus.暂停下载){ taskIndex++; startTask(); return; diff --git a/zhuike/src/main/java/com/novelbook/android/upgrade/ParseXmlService.java b/zhuike/src/main/java/com/novelbook/android/upgrade/ParseXmlService.java new file mode 100644 index 0000000..0d3d4b7 --- /dev/null +++ b/zhuike/src/main/java/com/novelbook/android/upgrade/ParseXmlService.java @@ -0,0 +1,67 @@ +package com.novelbook.android.upgrade; + +import java.io.InputStream; +import java.util.HashMap; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + + */ +public class ParseXmlService +{ + public HashMap parseXml(InputStream inStream) throws Exception + { + HashMap hashMap = new HashMap(); + + // 实例化一个文档构建器工厂 + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + // 通过文档构建器工厂获取一个文档构建器 + DocumentBuilder builder = factory.newDocumentBuilder(); + // 通过文档通过文档构建器构建一个文档实例 + Document document = builder.parse(inStream); + //获取XML文件根节点 + Element root = document.getDocumentElement(); + //获得所有子节点 + NodeList childNodes = root.getChildNodes(); + for (int j = 0; j < childNodes.getLength(); j++) + { + //遍历子节点 + Node childNode = childNodes.item(j); + if (childNode.getNodeType() == Node.ELEMENT_NODE){ + Element childElement = (Element) childNode; + hashMap.put(childElement.getNodeName(),childElement.getFirstChild().getNodeValue()); + } + /*if (childNode.getNodeType() == Node.ELEMENT_NODE) + { + Element childElement = (Element) childNode; + //版本号 + if ("version".equals(childElement.getNodeName())) + { + hashMap.put("version",childElement.getFirstChild().getNodeValue()); + } + //软件名称 + else if (("name".equals(childElement.getNodeName()))) + { + hashMap.put("name",childElement.getFirstChild().getNodeValue()); + } + //下载地址 + else if (("url".equals(childElement.getNodeName()))) + { + hashMap.put("url",childElement.getFirstChild().getNodeValue()); + } + else if (("details".equals(childElement.getNodeName()))) + { + hashMap.put("details",childElement.getFirstChild().getNodeValue()); + } + }*/ + } + return hashMap; + } +} diff --git a/zhuike/src/main/java/com/novelbook/android/upgrade/UpdateManager.java b/zhuike/src/main/java/com/novelbook/android/upgrade/UpdateManager.java new file mode 100644 index 0000000..4e3f472 --- /dev/null +++ b/zhuike/src/main/java/com/novelbook/android/upgrade/UpdateManager.java @@ -0,0 +1,440 @@ +package com.novelbook.android.upgrade; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; + + + +import android.app.AlertDialog; +import android.app.AlertDialog.Builder; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.Intent; +import android.content.pm.PackageManager.NameNotFoundException; +import android.net.Uri; +import android.os.Environment; +import android.os.Handler; +import android.os.Message; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ProgressBar; +import android.widget.Toast; + +import com.novelbook.android.R; +import com.novelbook.android.ReadActivity; +import com.novelbook.android.db.Novel; +import com.novelbook.android.netsubscribe.BookSubscribe; +import com.novelbook.android.netutils.HttpMethods; +import com.novelbook.android.netutils.OnSuccessAndFaultListener; +import com.novelbook.android.netutils.OnSuccessAndFaultSub; +import com.novelbook.android.utils.Constants; +import com.novelbook.android.utils.GsonUtil; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; + +import static com.novelbook.android.netapi.URLConstant.getRootUrl; + + +public class UpdateManager { + + public static final String TAG ="com.qiyou.UpdateManager"; + public static final String dTAG ="com.qiyou"; + private static final int DOWNLOAD = 1; + private static final int DOWNLOAD_FINISH = 2; + private static final int showDialog =3; + HashMap mHashMap; + private String mSavePath; + private int progress; + private boolean cancelUpdate = false; + private Context mContext; + private ProgressBar mProgress; + private Dialog mDownloadDialog; + private Handler mHandler = new Handler() + { + @Override + public void handleMessage(Message msg) + { + switch (msg.what) + { + case DOWNLOAD: + mProgress.setProgress(progress); + break; + case DOWNLOAD_FINISH: + installApk(); + break; + case showDialog: + showNoticeDialog(); + break; + default: + break; + } + }; + }; + + public UpdateManager(Context context) + { + this.mContext = context; +// app =(QiYouApplication)context; + } + + /** + * 濡拷绁存潪顖欐閺囧瓨鏌� + */ + public void checkUpdate() + { + String urlStr = getRootUrl()+ Constants.VERSION_ADDRESS; + urlStr ="http://xiaoshuofenxiang.com/version.xml"; + checkUpdate(urlStr); + /*if (isUpdate()) + { + showNoticeDialog(); + } else + { + Toast.makeText(mContext, R.string.soft_update_no, Toast.LENGTH_LONG).show(); + }*/ + } + boolean isSilence =false; + public void checkUpdateSilence() + { + isSilence=true; + checkUpdate(); + } + + + + + + + + void checkUpdate(String url){ + Request request = new Request.Builder() + .url(url).build(); + + + HttpMethods.getOkClient().newCall(request).enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + Log.d(TAG, " 版本检查错误 onFailure(int, Header[],byte[], Throwable ) was received"); + if(!isSilence) + Toast.makeText(mContext, "版本检查出错了", Toast.LENGTH_LONG).show(); + } + + @Override + public void onResponse(Call call, Response response) throws IOException { + if(response.code()!=200) { + Log.e(TAG, "check update onResponse:return code" +response.code() ); + } + ResponseBody body = response.body(); + + + try { + byte[] bytes = body.bytes(); + // String s = body.string(); + // Log.d(TAG, "onSuccess: response is " + s); + if (bytes != null) { + processTxtOnSuccess(bytes); + } + // body.close(); + }catch (Exception e){ + Log.e(TAG, "onResponse: ",e ); + }finally { + + } + } + }); + + + + + + + + } + + void processTxtOnSuccess(byte[] paramArrayOfByte) { + + boolean isUpdate=false; + int versionCode = getVersionCode(mContext); + InputStream inputStream = null; + inputStream =new ByteArrayInputStream(paramArrayOfByte); + ParseXmlService service = new ParseXmlService(); + try + { + + if(inputStream!=null) + mHashMap = service.parseXml(inputStream); + + } catch (Exception e) + { + e.printStackTrace(); + } + if (null != mHashMap) + { + int serviceCode = Integer.valueOf(mHashMap.get("version")); + // need update or not + isUpdate =serviceCode > versionCode; + } + + if (isUpdate) + { + mHandler.sendEmptyMessage(showDialog); + + } else + { + if(!isSilence) + Toast.makeText(mContext, R.string.soft_update_no, Toast.LENGTH_LONG).show(); + } + + + } + + + + + /** + * 閼惧嘲褰囨潪顖欐閻楀牊婀伴崣锟� * + * @param context + * @return + */ + public int getVersionCode(Context context) + { + int versionCode = 0; + try + { + // 閼惧嘲褰囨潪顖欐閻楀牊婀伴崣鍑ょ礉鐎电懓绨睞ndroidManifest.xml娑撳獘ndroid:versionCode + versionCode = context.getPackageManager().getPackageInfo("com.novelbook.android", 0).versionCode; + } catch (NameNotFoundException e) + { + + Log.e(TAG, "getVersionCode: ",e); + } + return versionCode; + } + + /** + * 閼惧嘲褰囨潪顖欐閻楀牊婀伴崣锟� * + * @param context + * @return + */ + public static String getVersionName(Context context) + { + String versionName = ""; + try + { + // 閼惧嘲褰囨潪顖欐閻楀牊婀伴崣鍑ょ礉鐎电懓绨睞ndroidManifest.xml娑撳獘ndroid:versionCode + versionName = context.getPackageManager().getPackageInfo("com.qiyou.mb.android", 0).versionName; + } catch (NameNotFoundException e) + { + Log.e(TAG, "getVersionCode: ",e); + } + return versionName; + } + + /** + * 閺勫墽銇氭潪顖欐閺囧瓨鏌婄�纭呯樈濡楋拷 + */ + private void showNoticeDialog() + { + + + /*final AlertDialog.Builder normalDialog = + new AlertDialog.Builder(mContext); + + normalDialog.setTitle("退出阅读"); + normalDialog.setMessage("确定退出阅读吗?"); + normalDialog.setPositiveButton("继续阅读", + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }); + normalDialog.setNegativeButton("退出阅读", + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }); + + normalDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + + } + }); + + // 显示 + normalDialog.show(); +*/ + + + // 閺嬪嫰锟界�纭呯樈濡楋拷 + Builder builder = new Builder(mContext); + builder.setTitle(R.string.soft_update_title); + String upgradeDetails=mHashMap.get("details"); + + builder.setMessage( mContext.getString(R.string.soft_update_info) +upgradeDetails ); + builder.setPositiveButton(R.string.soft_update_updatebtn, new OnClickListener() + { + @Override + public void onClick(DialogInterface dialog, int which) + { + dialog.dismiss(); + showDownloadDialog(); + } + }); + // 缁嬪秴鎮楅弴瀛樻煀 + builder.setNegativeButton(R.string.soft_update_later, new OnClickListener() + { + @Override + public void onClick(DialogInterface dialog, int which) + { + dialog.dismiss(); + } + }); + Dialog noticeDialog = builder.create(); + noticeDialog.show(); + + + } + + /** + * 閺勫墽銇氭潪顖欐娑撳娴囩�纭呯樈濡楋拷 + */ + private void showDownloadDialog() + { + // 閺嬪嫰锟芥潪顖欐娑撳娴囩�纭呯樈濡楋拷 + Builder builder = new Builder(mContext); + builder.setTitle(R.string.soft_updating); + // 缂佹瑤绗呮潪钘夘嚠鐠囨繃顢嬫晶鐐插鏉╂稑瀹抽弶锟� + final LayoutInflater inflater = LayoutInflater.from(mContext); + View v = inflater.inflate(R.layout.softupgrade_progress, null); + mProgress = (ProgressBar) v.findViewById(R.id.update_progress); + builder.setView(v); + // 閸欐牗绉烽弴瀛樻煀 + builder.setNegativeButton(R.string.soft_update_cancel, new OnClickListener() + { + @Override + public void onClick(DialogInterface dialog, int which) + { + dialog.dismiss(); + // 鐠佸墽鐤嗛崣鏍ㄧХ閻樿埖锟� + cancelUpdate = true; + } + }); + mDownloadDialog = builder.create(); + mDownloadDialog.setCancelable(false); + mDownloadDialog.show(); + // 閻滄澘婀弬鍥︽ + downloadApk(); + } + + /** + * 娑撳娴嘺pk閺傚洣娆� + */ + private void downloadApk() + { + // 閸氼垰濮╅弬鎵殠缁嬪绗呮潪鍊熻拫娴狅拷 + new downloadApkThread().start(); + } + + /** + * 娑撳娴囬弬鍥︽缁捐法鈻� + */ + private class downloadApkThread extends Thread + { + @Override + public void run() + { + try + { + // 閸掋倖鏌嘢D閸椻剝妲搁崥锕�摠閸︻煉绱濋獮鏈电瑬閺勵垰鎯侀崗閿嬫箒鐠囪鍟撻弶鍐 + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) + { + // 閼惧嘲绶辩�妯哄亶閸楋紕娈戠捄顖氱窞 + String sdpath = Environment.getExternalStorageDirectory() + "/"; + mSavePath = sdpath + "download"; + URL url = new URL(mHashMap.get("url")); + // 閸掓稑缂撴潻鐐村复 + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.connect(); + // 閼惧嘲褰囬弬鍥︽婢堆冪毈 + int length = conn.getContentLength(); + // 閸掓稑缂撴潏鎾冲弳濞达拷 + InputStream is = conn.getInputStream(); + + File file = new File(mSavePath); + // 閸掋倖鏌囬弬鍥︽閻╊喖缍嶉弰顖氭儊鐎涙ê婀� + if (!file.exists()) + { + file.mkdir(); + } + File apkFile = new File(mSavePath, mHashMap.get("name")); + FileOutputStream fos = new FileOutputStream(apkFile); + int count = 0; + // 缂傛挸鐡� + byte buf[] = new byte[1024]; + // 閸愭瑥鍙嗛崚鐗堟瀮娴犳湹鑵� + do + { + int numread = is.read(buf); + count += numread; + // 鐠侊紕鐣绘潻娑樺閺夆�缍呯純锟� + progress = (int) (((float) count / length) * 100); + // 閺囧瓨鏌婃潻娑樺 + mHandler.sendEmptyMessage(DOWNLOAD); + if (numread <= 0) + { + // 娑撳娴囩�灞惧灇 + mHandler.sendEmptyMessage(DOWNLOAD_FINISH); + break; + } + // 閸愭瑥鍙嗛弬鍥︽ + fos.write(buf, 0, numread); + } while (!cancelUpdate);// 閻愮懓鍤崣鏍ㄧХ鐏忓崬浠犲顤嶇瑓鏉烇拷 + fos.close(); + is.close(); + } + } catch (MalformedURLException e) + { + Log.e(TAG, "run: ", e); + } catch (IOException e) + { + Log.e(TAG, "run: ", e); + } + // 閸欐牗绉锋稉瀣祰鐎电鐦藉鍡樻▔缁�拷 + mDownloadDialog.dismiss(); + } + }; + + /** + * 鐎瑰顥朅PK閺傚洣娆� + */ + private void installApk() + { + File apkfile = new File(mSavePath, mHashMap.get("name")); + if (!apkfile.exists()) + { + return; + } + // 闁俺绻僆ntent鐎瑰顥朅PK閺傚洣娆� + Intent i = new Intent(Intent.ACTION_VIEW); + i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive"); + mContext.startActivity(i); + } +} diff --git a/zhuike/src/main/java/com/novelbook/android/utils/BookUtil.java b/zhuike/src/main/java/com/novelbook/android/utils/BookUtil.java index 832c946..f02391c 100644 --- a/zhuike/src/main/java/com/novelbook/android/utils/BookUtil.java +++ b/zhuike/src/main/java/com/novelbook/android/utils/BookUtil.java @@ -11,6 +11,7 @@ import android.os.Handler; import android.os.Message; import android.text.TextUtils; import android.util.Log; +import android.widget.TextView; import android.widget.Toast; import com.google.gson.Gson; @@ -749,7 +750,7 @@ int muluRetryCount =0; return; } String url = mSite.getMuluUrl(); - Request request = getTagRequest(url,mNovel.getMaxAge()); + Request request = getTagRequest(url,mSite.getDomain(), mNovel.getMaxAge()); mMuluStatus = MuluStatus.isDownloading; long startTime= new Date().getTime(); @@ -1345,7 +1346,7 @@ int muluRetryCount =0; String targetSiteName = msg.getData().getString("siteName"); Log.d(TAG, String.format("prepare book changing Source:target %s -- %s to open chapter %s" ,mNovel.getDomain(),targetSiteName,msg.arg1)); - + if(pagefactory!=null) pagefactory.changeSource(targetSiteName, mNovel.getDomain(),msg.arg1,getChapter(msg.arg1).getChapterName()); @@ -1436,7 +1437,7 @@ int muluRetryCount =0; char[] block=null; if(chaptCache.containsKey(Integer.valueOf(index))) { block = chaptCache .get(index).getData().get(); - // Log.d(TAG, String.format("prepare book get block in cache, chapter: %s", index)); + Log.d(TAG, String.format("read content get block in cache, chapter: %s", index)); } // Log.d(TAG, String.format("prepare book begin to load content for chapter %s", index)); if (block == null) { @@ -1626,6 +1627,10 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte } Chapter chapter = mChapters.get(index -1); + String refUrl=""; + if(index>1){ + refUrl = mChapters.get(index -2).getChapterUrl(); + } String url = chapter.getChapterUrl(); if( TextUtils.isEmpty( url)){ handler.sendEmptyMessage(1); @@ -1640,7 +1645,7 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte JSONObject siteJson = new JSONObject(); siteJson.put("chapterContentRegex", mSiteRule.getChapterContentRegex()); siteJson.put("chapterContentDumpRegex", mSiteRule.getChapterContentDumpRegex()); - Request request = getTagRequest(url, -1); + Request request = getTagRequest(url, refUrl,-1); HttpMethods.getOkClient().newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { @@ -1742,13 +1747,17 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte * @param maxAge * @return */ - private Request getTagRequest(String url, int maxAge) { + private Request getTagRequest(String url, String refUrl ,int maxAge) { Request.Builder builder = new Request.Builder() .tag(mNovel.getNovelId()) //标记 请求的tag,切换小说或离开小说界面(BookActivity) 时 取消未执行完毕的 此tag的所有请求 .url(url) .removeHeader("Pragma"); + if(!TextUtils.isEmpty(refUrl)){ + builder.header("Referer",refUrl); + } + for (int i = 0; i < mSiteRule.getHeaders().length; i += 2) { builder.header(mSiteRule.getHeaders()[i], mSiteRule.getHeaders()[i + 1]); diff --git a/zhuike/src/main/java/com/novelbook/android/utils/Config.java b/zhuike/src/main/java/com/novelbook/android/utils/Config.java index 72b6bdf..9b57c2e 100644 --- a/zhuike/src/main/java/com/novelbook/android/utils/Config.java +++ b/zhuike/src/main/java/com/novelbook/android/utils/Config.java @@ -18,7 +18,7 @@ public class Config { private final static String SYSTEM_LIGHT_KEY = "systemlight"; private final static String PAGE_MODE_KEY = "pagemode"; private final static String KEY_BASE_URY = "baseurl"; - + private final static String KEY_ROOT_URL = "rooturl"; public final static String FONTTYPE_DEFAULT = ""; public final static String FONTTYPE_QIHEI = "font/qihei.ttf"; public final static String FONTTYPE_WAWA = "font/font1.ttf"; @@ -182,13 +182,22 @@ public class Config { } - public String getBaseUrl(){ - return sp.getString(KEY_BASE_URY,""); - } public void setBaseUrl(String baseUrl){ sp.edit().putString(KEY_BASE_URY,baseUrl).commit(); } + public String getBaseUrl(){ + return sp.getString(KEY_BASE_URY,""); + } + + + public String getRootUrl(){ + return sp.getString(KEY_ROOT_URL,"http://xiaoshuofenxiang.com/api/"); + } + + public void setRootUrl(String baseUrl){ + sp.edit().putString(KEY_ROOT_URL,baseUrl).commit(); + } } diff --git a/zhuike/src/main/java/com/novelbook/android/utils/Constants.java b/zhuike/src/main/java/com/novelbook/android/utils/Constants.java index 1d67a68..1b0b59e 100644 --- a/zhuike/src/main/java/com/novelbook/android/utils/Constants.java +++ b/zhuike/src/main/java/com/novelbook/android/utils/Constants.java @@ -11,6 +11,7 @@ public class Constants { public static final boolean SHOWAD =false ; public static final int MAXAGE_MAX =60*60*24*28; //28 天 ; public static final int MAXAGE_MULU = 60*60*24*7*2; //2周;; + public static final String VERSION_ADDRESS ="version.xml"; public static String[] HOT_KEYS_VALUE = {}; public static int SEX=1; //1 男,2女 public static String A_Regex = "]+href[\\s]*=[\\s]*['\"]?([^'\"]+)['\"\\s]?[^>]*>([^<]+)<"; //TODO: 从服务器更新 @@ -24,4 +25,5 @@ public class Constants { // public static List lstProgress=null; public static boolean showDialogOnUi =true; public static boolean showDialogOnUiPage =false; + } diff --git a/zhuike/src/main/java/com/novelbook/android/utils/FileUtils.java b/zhuike/src/main/java/com/novelbook/android/utils/FileUtils.java index df99140..7a9fb58 100644 --- a/zhuike/src/main/java/com/novelbook/android/utils/FileUtils.java +++ b/zhuike/src/main/java/com/novelbook/android/utils/FileUtils.java @@ -109,7 +109,16 @@ public class FileUtils { Fileutil.deleteDir(getNovelDir(novelId)); } + public static String getCacheSizeK(int noveId) { + float size = getCacheSize( noveId) ; + size = size/1024.00f; + if(size >1024){ + size = size/1024.00f; + return String.format("%.1fM",size); + } + return String.format("%.1fK",size); + } public static long getCacheSize(int noveId) { return Fileutil.getDirSize(getNovelDir(noveId)); } diff --git a/zhuike/src/main/java/com/novelbook/android/utils/NovelParseUtil.java b/zhuike/src/main/java/com/novelbook/android/utils/NovelParseUtil.java index b545fb1..d301da2 100644 --- a/zhuike/src/main/java/com/novelbook/android/utils/NovelParseUtil.java +++ b/zhuike/src/main/java/com/novelbook/android/utils/NovelParseUtil.java @@ -332,22 +332,6 @@ public static String enconding(ResponseBody body, String encode) throws Unsupp } return s; - /* //Log.i(TAG, " encoding covert from :" +source ); - long st = new java.util.Date().getTime(); - byte[] b = source.getBytes("utf-8"); - // String info = new String(b, "utf-8"); - String info = new String(b); - //Log.i(TAG, " encoding covert to :" +info ); - //Log.i(TAG, "encoding covert :" + encode +", cost " +( new Date().getTime() -st)); - return info;*/ - -/* long st = new java.util.Date().getTime(); - byte[] b = source.getBytes(encode); - // String info = new String(b, "utf-8"); - String info = new String(b,"utf-8"); - //Log.i(TAG, " encoding covert to :" +info ); - //Log.i(TAG, "encoding covert :" + encode +", cost " +( new Date().getTime() -st)); - return info;*/ } diff --git a/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java b/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java index 4bdc2d3..728ece6 100644 --- a/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java +++ b/zhuike/src/main/java/com/novelbook/android/utils/PageFactory.java @@ -232,7 +232,7 @@ public class PageFactory implements ChangeSource{ chaptId = chaptId > 0 ? chaptId : 1; final File file = new File(getChapterFileName(chaptId)); - if (!file.exists()) { //待下载 + if (!file.exists() && getChapters().size()>0) { //待下载 chaptId = chaptId > getChapters().size() ? getChapters().size() : chaptId; chaptId = chaptId > 0 ? chaptId : 1; @@ -290,7 +290,7 @@ public class PageFactory implements ChangeSource{ @Override public void run() { Log.d(TAG, String.format("prepare book to download chapter %s ,thread.name %s",chid,Thread.currentThread().getName() ) ); - mBookUtil.chaptChars(chid); + mBookUtil.chaptChars(chid); //TODO: 读取到上一章block后,file还是不存在的,现在就死循环了 super.run(); }}.start(); @@ -891,6 +891,7 @@ public static boolean busy(){ m_islastPage = false; if(null == currentPage){ + changeChapter(mBookUtil.getChapterNo()); return; } if(mBookUtil.isBusy()){ @@ -900,7 +901,7 @@ public static boolean busy(){ if (currentPage.getEnd() >= mBookUtil.getBookLen()) { Log.d(TAG,"已经是本章最后一页了"); - m_islastPage =currentChapter >= mBookUtil.getChapters().size(); + m_islastPage =currentChapter == mBookUtil.getChapters().size(); if ( m_islastPage){ Toast.makeText(mContext, "已经是最后一页了", Toast.LENGTH_SHORT).show(); return; diff --git a/zhuike/src/main/res/layout/activitycache.xml b/zhuike/src/main/res/layout/activitycache.xml index 55aa51d..e8fd124 100644 --- a/zhuike/src/main/res/layout/activitycache.xml +++ b/zhuike/src/main/res/layout/activitycache.xml @@ -23,6 +23,14 @@ + + + + + - + + + + diff --git a/qy/src/main/res/layout/softupgrade_progress.xml b/zhuike/src/main/res/layout/softupgrade_progress.xml similarity index 100% rename from qy/src/main/res/layout/softupgrade_progress.xml rename to zhuike/src/main/res/layout/softupgrade_progress.xml diff --git a/zhuike/src/main/res/menu/activity_main2_drawer.xml b/zhuike/src/main/res/menu/activity_main2_drawer.xml index 6f0f13b..0d3007b 100644 --- a/zhuike/src/main/res/menu/activity_main2_drawer.xml +++ b/zhuike/src/main/res/menu/activity_main2_drawer.xml @@ -4,22 +4,16 @@ tools:showIn="navigation_view"> - + - + + android:title="下载管理" /> - + Main5Activity 加入书架 立即阅读 - 下载序列 + 下载管理 Main6Activity Hello World from section: %1$d @@ -191,6 +191,13 @@ 书架空空如也 正在加载... 重试 + 已是最新版本 + 有新版本了 + 更新日志 + 更新 + 以后再说 + 正在更新 + 取消更新 小燕—女青、中英、普通话 diff --git a/zhuike/zhuike.iml b/zhuike/zhuike.iml index 60310cc..0fe264c 100644 --- a/zhuike/zhuike.iml +++ b/zhuike/zhuike.iml @@ -8,11 +8,11 @@ - - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -104,13 +146,17 @@ + + + + @@ -120,6 +166,8 @@ + + @@ -173,6 +221,7 @@ + @@ -189,6 +238,7 @@ +