parent
3c4872a58e
commit
3a26f670c4
|
@ -12,23 +12,82 @@ android {
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
|
|
||||||
// testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
// testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
// vectorDrawables.useSupportLibrary = true
|
// vectorDrawables.useSupportLibrary = true
|
||||||
|
|
||||||
|
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|
||||||
renderscriptTargetApi 24 //blurkit
|
renderscriptTargetApi 24 //blurkit
|
||||||
renderscriptSupportModeEnabled true //blurkit
|
renderscriptSupportModeEnabled true //blurkit
|
||||||
|
|
||||||
|
multiDexEnabled true //突破65535
|
||||||
|
manifestPlaceholders = [UMENG_CHANNEL_CALUE:"umeng"] //默认为uMeng
|
||||||
|
flavorDimensions "default"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
debug {
|
||||||
|
// 显示Log
|
||||||
|
buildConfigField "boolean", "LOG_DEBUG", "true"
|
||||||
|
versionNameSuffix "-debug"
|
||||||
minifyEnabled false
|
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'
|
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 {
|
sourceSets {
|
||||||
main {
|
main {
|
||||||
jniLibs.srcDirs = ['libs']
|
jniLibs.srcDirs = ['libs']
|
||||||
|
@ -40,9 +99,14 @@ android {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
implementation 'com.android.support:appcompat-v7:28.0.0'
|
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.tangguna:SearchBox:1.0.1'
|
||||||
implementation 'com.github.chengzipi:Searchbox:v1.0.0'
|
implementation 'com.github.chengzipi:Searchbox:v1.0.0'
|
||||||
implementation 'com.github.ixiaow:multilayout:1.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'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,273 @@
|
||||||
# Add project specific ProGuard rules here.
|
# Add project specific ProGuard rules here.
|
||||||
# You can control the set of applied configuration files using the
|
# By default, the flags in this file are appended to flags specified
|
||||||
# proguardFiles setting in build.gradle.
|
# 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
|
# For more details, see
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
# 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
|
# If your project uses WebView with JS, uncomment the following
|
||||||
# and specify the fully qualified class name to the JavaScript interface
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
# class:
|
# class:
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
# public *;
|
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######
|
||||||
|
|
||||||
|
#如果引用了v4或者v7包
|
||||||
|
-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.**
|
||||||
|
####混淆保护自己项目的部分代码以及引用的第三方jar包library-end####
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#保持 native 方法不被混淆
|
||||||
|
-keepclasseswithmembernames class * {
|
||||||
|
native <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#保持自定义控件类不被混淆
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
public <init>(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 <init>(android.content.Context);
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet);
|
||||||
|
public <init>(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 <fields>;
|
||||||
|
!private <fields>;
|
||||||
|
!private <methods>;
|
||||||
|
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 <fields>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#避免混淆泛型 如果混淆报错建议关掉
|
||||||
|
#-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.* <fields>;
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclasseswithmembernames class * {
|
||||||
|
@butterknife.* <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
######引用的其他Module可以直接在app的这个混淆文件里配置
|
||||||
|
|
||||||
|
# 如果使用了Gson之类的工具要使被它解析的JavaBean类即实体类不被混淆。
|
||||||
|
-keep class com.novelbook.android.bean.** { *; }
|
||||||
|
-keep class com.novelbook.android.db.** { *; }
|
||||||
|
#####混淆保护自己项目的部分代码以及引用的第三方jar包library#######
|
||||||
|
#如果在当前的application module或者依赖的library module中使用了第三方的库,并不需要显式添加规则
|
||||||
|
#-libraryjars xxx
|
||||||
|
#添加了反而有可能在打包的时候遭遇同一个jar多次被指定的错误,一般只需要添加忽略警告和保持某些class不被混淆的声明。
|
||||||
|
#以libaray的形式引用了开源项目,如果不想混淆 keep 掉,在引入的module的build.gradle中设置minifyEnabled=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 <init> (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.* <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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
|
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".MyApp"
|
android:name=".MyApp"
|
||||||
|
@ -75,6 +78,13 @@
|
||||||
<service
|
<service
|
||||||
android:name=".service.ServiceDownload"
|
android:name=".service.ServiceDownload"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- UMENG -->
|
||||||
|
<meta-data android:value="5cd6238a570df375c3000cc9" android:name="UMENG_APPKEY"/>
|
||||||
|
<meta-data android:name="UMENG_CHANNEL" android:value="${UMENG_CHANNEL_VALUE}"/>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -26,10 +26,12 @@ import com.novelbook.android.db.Novel;
|
||||||
import com.novelbook.android.netsubscribe.MovieSubscribe;
|
import com.novelbook.android.netsubscribe.MovieSubscribe;
|
||||||
import com.novelbook.android.netutils.OnSuccessAndFaultListener;
|
import com.novelbook.android.netutils.OnSuccessAndFaultListener;
|
||||||
import com.novelbook.android.netutils.OnSuccessAndFaultSub;
|
import com.novelbook.android.netutils.OnSuccessAndFaultSub;
|
||||||
|
import com.novelbook.android.upgrade.UpdateManager;
|
||||||
import com.novelbook.android.utils.ImageUtil;
|
import com.novelbook.android.utils.ImageUtil;
|
||||||
import com.novelbook.android.utils.MyImageLoader;
|
import com.novelbook.android.utils.MyImageLoader;
|
||||||
import com.novelbook.android.utils.OnItemClickListener;
|
import com.novelbook.android.utils.OnItemClickListener;
|
||||||
import com.novelbook.android.adapter.BookListAdapter;
|
import com.novelbook.android.adapter.BookListAdapter;
|
||||||
|
import com.umeng.analytics.MobclickAgent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -71,6 +73,7 @@ public abstract class Activity_base extends AppCompatActivity {
|
||||||
setTitle();
|
setTitle();
|
||||||
initData();
|
initData();
|
||||||
initViews();
|
initViews();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setupToolbar(){
|
protected void setupToolbar(){
|
||||||
|
@ -85,11 +88,13 @@ public abstract class Activity_base extends AppCompatActivity {
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
// MobclickAgent.onResume(this);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onPause(){
|
protected void onPause(){
|
||||||
super.onPause();
|
super.onPause();
|
||||||
hideProgress();
|
hideProgress();
|
||||||
|
// MobclickAgent.onPause(this);
|
||||||
}
|
}
|
||||||
protected BookListAdapter getBookListAdapter(List<Novel> mDatas,int itemResourceId){
|
protected BookListAdapter getBookListAdapter(List<Novel> mDatas,int itemResourceId){
|
||||||
BookListAdapter mAdapter = new BookListAdapter(this ,mDatas,itemResourceId,new OnItemClickListener()
|
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);
|
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<MyViewHolder> {
|
class BookListAdapter extends RecyclerView.Adapter<MyViewHolder> {
|
||||||
private final int EMPTY_VIEW = 1;
|
private final int EMPTY_VIEW = 1;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.os.Build;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.widget.GridLayoutManager;
|
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.DownloadTask;
|
||||||
import com.novelbook.android.db.Novel;
|
import com.novelbook.android.db.Novel;
|
||||||
import com.novelbook.android.service.ServiceDownload;
|
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 com.novelbook.android.utils.ImageUtil;
|
||||||
|
|
||||||
import org.litepal.LitePal;
|
import org.litepal.LitePal;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
|
@ -40,6 +44,8 @@ public class Activity_cache extends Activity_base {
|
||||||
public static final String TAG=Activity_cache.class.getSimpleName();
|
public static final String TAG=Activity_cache.class.getSimpleName();
|
||||||
@BindView(R.id.recycleView)
|
@BindView(R.id.recycleView)
|
||||||
RecyclerView mRecyclerView;
|
RecyclerView mRecyclerView;
|
||||||
|
@BindView(R.id.tvMsg)
|
||||||
|
TextView tvMsg;
|
||||||
private List<DownloadTask> mData;
|
private List<DownloadTask> mData;
|
||||||
private CacheAdapter mAdapter;
|
private CacheAdapter mAdapter;
|
||||||
@Override
|
@Override
|
||||||
|
@ -60,7 +66,33 @@ public class Activity_cache extends Activity_base {
|
||||||
@Override
|
@Override
|
||||||
protected void initData() {
|
protected void initData() {
|
||||||
initiDownloadReceiver();
|
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<DownloadTask>(){
|
||||||
|
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() {
|
mAdapter = new CacheAdapter(this,mData,R.layout.recycle_list_item_cache,new OnItemClickLitener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -115,13 +147,6 @@ public class Activity_cache extends Activity_base {
|
||||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
|
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||||
mRecyclerView.setAdapter(mAdapter );
|
mRecyclerView.setAdapter(mAdapter );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void fillData() {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntentFilter filter;
|
private IntentFilter filter;
|
||||||
|
@ -137,6 +162,16 @@ public class Activity_cache extends Activity_base {
|
||||||
public void onReceive(Context context, Intent intent){
|
public void onReceive(Context context, Intent intent){
|
||||||
int taskId =0;
|
int taskId =0;
|
||||||
int progress=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")){
|
if( intent.hasExtra("progress")){
|
||||||
progress = intent.getIntExtra("progress",0);
|
progress = intent.getIntExtra("progress",0);
|
||||||
|
@ -144,16 +179,28 @@ public class Activity_cache extends Activity_base {
|
||||||
if( intent.hasExtra("taskId")){
|
if( intent.hasExtra("taskId")){
|
||||||
taskId = intent.getIntExtra("taskId",0);
|
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));
|
Log.d(TAG, String.format("onReceive: taskId %s progress %s ",taskId,progress));
|
||||||
for(DownloadTask dt : mData){
|
for(DownloadTask dt : mData){
|
||||||
if(taskId == dt.getId()){
|
if(taskId == dt.getId()){
|
||||||
dt.setFinishedChpats(progress);
|
dt.setFinishedChpats(progress);
|
||||||
if(dt.getDownSatus()!=DownloadTask.DownStatus.等待下载) {
|
if(status==1){
|
||||||
|
dt.setStatus(1);
|
||||||
|
dt.setDownSatus(DownloadTask.DownStatus.下载完成);
|
||||||
|
}else
|
||||||
|
if(dt.getDownSatus()!=DownloadTask.DownStatus.暂停下载) {
|
||||||
dt.setDownSatus(DownloadTask.DownStatus.正在下载);
|
dt.setDownSatus(DownloadTask.DownStatus.正在下载);
|
||||||
|
dt.setStatus(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dt = LitePal.find(DownloadTask.class,taskId);
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
if(dt.getDownSatus()!=DownloadTask.DownStatus.正在下载) {
|
if(dt.getDownSatus()==DownloadTask.DownStatus.正在下载) {
|
||||||
dt.setDownSatus(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.tvTitle.setText(mDatas.get(position).getNovelTitle());
|
||||||
holder.tvSource.setText(mDatas.get(position).getDomainName());
|
holder.tvSource.setText(mDatas.get(position).getDomainName());
|
||||||
boolean finished = mData.get(position).getFinishedChpats() == mData.get(position).getTotalChapts();
|
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) {
|
if( mData.get(position).getTotalChapts() >0) {
|
||||||
float progress = mData.get(position).getFinishedChpats() *100/ mData.get(position).getTotalChapts() ;
|
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.正在下载 ?"正在下载"
|
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.setText( mData.get(position).getStatus()==1 || mData.get(position).getFinishedChpats() >=mData.get(position).getTotalChapts()
|
||||||
? holder.tvStatus.getText():"下载完成" );
|
? "下载完成" : 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.tvStatus.setText( mData.get(position).getDownSatus() == DownloadTask.DownStatus.排队中?"排队中": holder.tvStatus.getText() );
|
||||||
|
|
||||||
holder.barProgress.setProgress((int)progress);
|
|
||||||
}
|
|
||||||
// holder.imgStart.setVisibility(View.GONE);
|
|
||||||
int img = R.mipmap.play;
|
int img = R.mipmap.play;
|
||||||
img = mData.get(position).getDownSatus() == DownloadTask.DownStatus.正在下载 ? R.mipmap.pause : R.mipmap.play;
|
img = mData.get(position).getDownSatus() == DownloadTask.DownStatus.正在下载 ? R.mipmap.pause : R.mipmap.play;
|
||||||
|
|
||||||
holder.imgStart.setImageResource( img);
|
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);
|
||||||
|
|
||||||
holder.imgStart.setOnClickListener(new View.OnClickListener() {
|
holder.imgStart.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
@ -275,7 +330,7 @@ public class Activity_cache extends Activity_base {
|
||||||
}else{
|
}else{
|
||||||
startDownloadService(mData.get(pos).getId(),false);
|
startDownloadService(mData.get(pos).getId(),false);
|
||||||
holder.imgStart.setImageResource( R.mipmap.play);
|
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());
|
mData.get(pos).update( mData.get(pos).getId());
|
||||||
|
|
||||||
|
@ -339,6 +394,8 @@ public class Activity_cache extends Activity_base {
|
||||||
ImageView imgStart;
|
ImageView imgStart;
|
||||||
@BindView(R.id.tvSource)
|
@BindView(R.id.tvSource)
|
||||||
TextView tvSource;
|
TextView tvSource;
|
||||||
|
@BindView(R.id.tvSize)
|
||||||
|
TextView tvSize;
|
||||||
public MyViewHolder(View view) {
|
public MyViewHolder(View view) {
|
||||||
super(view);
|
super(view);
|
||||||
ButterKnife.bind(this, view);
|
ButterKnife.bind(this, view);
|
||||||
|
|
|
@ -497,7 +497,8 @@ public class BookActivity extends Activity_base {
|
||||||
|
|
||||||
private void startDownloadService(int taskId) {
|
private void startDownloadService(int taskId) {
|
||||||
Intent serviceIntent = getSvrIntent();
|
Intent serviceIntent = getSvrIntent();
|
||||||
serviceIntent.putExtra("taskId",taskId);
|
// serviceIntent.putExtra("taskId",taskId);
|
||||||
|
// serviceIntent.putExtra("start",true);
|
||||||
startService(serviceIntent);
|
startService(serviceIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,7 +759,11 @@ void onResponseProcess( String content ,String url){
|
||||||
}
|
}
|
||||||
|
|
||||||
if(novelId == mNovel.getId()){
|
if(novelId == mNovel.getId()){
|
||||||
|
try {
|
||||||
btnCach.setText(progress + "/" + pageFactory.getChapters().size());
|
btnCach.setText(progress + "/" + pageFactory.getChapters().size());
|
||||||
|
}catch (Exception e){
|
||||||
|
Log.e(TAG, "onReceive: ", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ import com.novelbook.android.utils.ImageUtil;
|
||||||
import com.novelbook.android.utils.MyImageLoader;
|
import com.novelbook.android.utils.MyImageLoader;
|
||||||
import com.novelbook.android.utils.OnItemClickListener;
|
import com.novelbook.android.utils.OnItemClickListener;
|
||||||
import com.novelbook.android.utils.PageFactory;
|
import com.novelbook.android.utils.PageFactory;
|
||||||
|
import com.umeng.analytics.MobclickAgent;
|
||||||
import com.youth.banner.loader.ImageLoader;
|
import com.youth.banner.loader.ImageLoader;
|
||||||
|
|
||||||
import org.litepal.LitePal;
|
import org.litepal.LitePal;
|
||||||
|
@ -391,4 +392,16 @@ public abstract class BasicFragment extends Fragment {
|
||||||
public void loadData() {
|
public void loadData() {
|
||||||
initData();
|
initData();
|
||||||
} //on tab changed
|
} //on tab changed
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
MobclickAgent.onPageStart(TAG);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onPause(){
|
||||||
|
super.onPause();
|
||||||
|
hideProgress();
|
||||||
|
MobclickAgent.onPageEnd(TAG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -356,9 +356,8 @@ void test(int maxAge){
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
TextView tvCache =(TextView) bottomSheetDialog.findViewById(R.id.tvCache);
|
TextView tvCache =(TextView) bottomSheetDialog.findViewById(R.id.tvCache);
|
||||||
long size = FileUtils.getCacheSize(bookLists.get(position).getId());
|
|
||||||
size = size/1024;
|
tvCache.setText(FileUtils.getCacheSizeK(bookLists.get(position).getId()));
|
||||||
tvCache.setText(String.format("%sK",size));
|
|
||||||
LinearLayout llClearCache =(LinearLayout) bottomSheetDialog.findViewById(R.id.llClearCache);
|
LinearLayout llClearCache =(LinearLayout) bottomSheetDialog.findViewById(R.id.llClearCache);
|
||||||
llClearCache.setOnClickListener(new View.OnClickListener() {
|
llClearCache.setOnClickListener(new View.OnClickListener() {
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
|
|
@ -274,7 +274,7 @@ public class Fragment_booklist extends BasicFragment {
|
||||||
|
|
||||||
}else if(!TextUtils.isEmpty(keyWord)){ //搜索
|
}else if(!TextUtils.isEmpty(keyWord)){ //搜索
|
||||||
// showProgressDialog(true, "正在加载搜索");
|
// showProgressDialog(true, "正在加载搜索");
|
||||||
mAdapter.setShowTop(true);
|
// mAdapter.setShowTop(true);
|
||||||
BookSubscribe.getSearchNovelList( keyWord,pageNo, Constants.SEX, new OnSuccessAndFaultSub(successAndFaultListener, getActivity()));
|
BookSubscribe.getSearchNovelList( keyWord,pageNo, Constants.SEX, new OnSuccessAndFaultSub(successAndFaultListener, getActivity()));
|
||||||
}else if(!TextUtils.isEmpty(history)){
|
}else if(!TextUtils.isEmpty(history)){
|
||||||
loadHistory();
|
loadHistory();
|
||||||
|
|
|
@ -20,6 +20,7 @@ import com.novelbook.android.R;
|
||||||
import com.novelbook.android.adapter.JudgeNestedScrollView;
|
import com.novelbook.android.adapter.JudgeNestedScrollView;
|
||||||
import com.novelbook.android.bean.Progress;
|
import com.novelbook.android.bean.Progress;
|
||||||
import com.novelbook.android.db.Novel;
|
import com.novelbook.android.db.Novel;
|
||||||
|
import com.novelbook.android.netapi.RandomHost;
|
||||||
import com.novelbook.android.netsubscribe.BookSubscribe;
|
import com.novelbook.android.netsubscribe.BookSubscribe;
|
||||||
import com.novelbook.android.netutils.NetUtil;
|
import com.novelbook.android.netutils.NetUtil;
|
||||||
import com.novelbook.android.netutils.OnSuccessAndFaultListener;
|
import com.novelbook.android.netutils.OnSuccessAndFaultListener;
|
||||||
|
@ -498,6 +499,8 @@ final String TAG = Fragment_paihang.class.getSimpleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void getSearchTabTtitle(){
|
void getSearchTabTtitle(){
|
||||||
|
|
||||||
|
|
||||||
BookSubscribe.getSearchTitles(new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() {
|
BookSubscribe.getSearchTitles(new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(String result) {
|
public void onSuccess(String result) {
|
||||||
|
@ -508,17 +511,6 @@ final String TAG = Fragment_paihang.class.getSimpleName();
|
||||||
Constants.lstSex = GsonUtil.parserStringBlocks(result,"sex");
|
Constants.lstSex = GsonUtil.parserStringBlocks(result,"sex");
|
||||||
Constants.lstNt =GsonUtil.parserStringBlocks(result,"nt");
|
Constants.lstNt =GsonUtil.parserStringBlocks(result,"nt");
|
||||||
// Constants.lstProgress =GsonUtil.parserProgressBlocks(result,"progress");
|
// Constants.lstProgress =GsonUtil.parserProgressBlocks(result,"progress");
|
||||||
/* getActivity().runOnUiThread(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
initTabs(); // refresh ui 的操作代码
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});*/
|
|
||||||
initTabs();
|
initTabs();
|
||||||
loadSearchData();
|
loadSearchData();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -533,8 +525,8 @@ final String TAG = Fragment_paihang.class.getSimpleName();
|
||||||
public void onFault(String errorMsg) {
|
public void onFault(String errorMsg) {
|
||||||
//失败
|
//失败
|
||||||
Log.d(TAG, "error on get firstpage: " + errorMsg);
|
Log.d(TAG, "error on get firstpage: " + errorMsg);
|
||||||
|
// getSearchTabTtitle();
|
||||||
|
handler.sendEmptyMessage(0);
|
||||||
}
|
}
|
||||||
},getActivity()));
|
},getActivity()));
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ public class Main2Activity extends Activity_base
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
getHostPolicy();
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
//PageFactory.createPageFactory(this);
|
//PageFactory.createPageFactory(this);
|
||||||
app =(MyApp) getApplicationContext();
|
app =(MyApp) getApplicationContext();
|
||||||
|
@ -77,6 +78,7 @@ public class Main2Activity extends Activity_base
|
||||||
// ButterKnife.bind(this);
|
// ButterKnife.bind(this);
|
||||||
|
|
||||||
initialSexOption();
|
initialSexOption();
|
||||||
|
checkUpdate(true);
|
||||||
// getSearchTabTtitle();
|
// getSearchTabTtitle();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -532,8 +534,10 @@ private int bottomSelectedIndex;
|
||||||
// mFirstPage= gson.fromJson(result, FirstPage.class);
|
// mFirstPage= gson.fromJson(result, FirstPage.class);
|
||||||
try {
|
try {
|
||||||
JSONObject jsonObject = new JSONObject(result);
|
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) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
@ -3,9 +3,13 @@ package com.novelbook.android;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.content.Context;
|
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.Config;
|
||||||
import com.novelbook.android.utils.LogcatHelper;
|
import com.novelbook.android.utils.LogcatHelper;
|
||||||
import com.novelbook.android.utils.PageFactory;
|
import com.novelbook.android.utils.PageFactory;
|
||||||
|
import com.umeng.analytics.MobclickAgent;
|
||||||
|
import com.umeng.commonsdk.UMConfigure;
|
||||||
|
|
||||||
import org.litepal.LitePal;
|
import org.litepal.LitePal;
|
||||||
|
|
||||||
|
@ -14,6 +18,7 @@ public class MyApp extends Application {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
HttpMethods.USERAGENT = NetUtil.getUserAgent();
|
||||||
applicationContext = getApplicationContext();
|
applicationContext = getApplicationContext();
|
||||||
Config.createConfig(this);
|
Config.createConfig(this);
|
||||||
PageFactory.createPageFactory(this);
|
PageFactory.createPageFactory(this);
|
||||||
|
@ -23,6 +28,10 @@ public class MyApp extends Application {
|
||||||
LitePal.initialize(this);
|
LitePal.initialize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void initApi(){
|
||||||
|
UMConfigure.init(applicationContext,UMConfigure.DEVICE_TYPE_PHONE,null);
|
||||||
|
MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO);
|
||||||
|
}
|
||||||
public boolean exit() {
|
public boolean exit() {
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class DownloadTask extends LitePalSupport implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum DownStatus{
|
public static enum DownStatus{
|
||||||
初始状态,等待下载, 正在下载,排队中,下载完成
|
初始状态,暂停下载, 正在下载,排队中,下载完成
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,8 @@ public interface HttpApi {
|
||||||
@GET("page/hot-keywords")
|
@GET("page/hot-keywords")
|
||||||
Observable<ResponseBody> getSearchHotKeys();
|
Observable<ResponseBody> getSearchHotKeys();
|
||||||
|
|
||||||
|
@GET("download/version.xml")
|
||||||
|
Observable<ResponseBody> getVersion();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<String, int[]> indexsMap = new HashMap<String, int[]>();
|
||||||
|
|
||||||
|
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 "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,13 +4,17 @@ import android.text.TextUtils;
|
||||||
|
|
||||||
import com.novelbook.android.utils.Config;
|
import com.novelbook.android.utils.Config;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by 眼神 on 2018/3/27.
|
* Created by 眼神 on 2018/3/27.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class URLConstant {
|
public class URLConstant {
|
||||||
//存放全部的URL(可分为开发、测试、正式)
|
//存放全部的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/"};
|
public static String[] BASE_URLS = {"http://xiaoshuofenxiang.com/api/"};
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,29 +22,29 @@ public class URLConstant {
|
||||||
* 取新的baseURL
|
* 取新的baseURL
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static String newBaseUrl(){
|
public static String newRootUrl(){
|
||||||
|
|
||||||
for (String url:BASE_URLS) {
|
for (String url:BASE_URLS) {
|
||||||
if(!url.equals(BASE_URL)){
|
if(!url.equals(ROOT_URL)){
|
||||||
BASE_URL = url;
|
ROOT_URL = url;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(! Config.getInstance().getBaseUrl().equals(BASE_URL)){
|
if(! Config.getInstance().getBaseUrl().equals(ROOT_URL)){
|
||||||
Config.getInstance().setBaseUrl(BASE_URL);
|
Config.getInstance().setBaseUrl(ROOT_URL);
|
||||||
}
|
}
|
||||||
return BASE_URL;
|
return ROOT_URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* app初始化取上次保存的baseurl
|
* app初始化取上次保存的baseurl
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static String getBaseUrl(){
|
public static String getRootUrl() {
|
||||||
BASE_URL=Config.getInstance().getBaseUrl();
|
|
||||||
if(TextUtils.isEmpty(BASE_URL)){
|
ROOT_URL=Config.getInstance().getRootUrl();
|
||||||
BASE_URL = newBaseUrl();
|
|
||||||
}
|
return ROOT_URL;
|
||||||
return BASE_URL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,74 +18,78 @@ public class BookSubscribe {
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
public static void getMastDomain(DisposableObserver<ResponseBody> subscriber){
|
public static void getMastDomain(DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getMasterDomain();
|
Observable<ResponseBody> observable = HttpMethods.getInstance("/api/g").getHttpApi().getMasterDomain();
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
public static void getNovel(int novelId,DisposableObserver<ResponseBody> subscriber){
|
public static void getNovel(int novelId,DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getNovel(novelId);
|
Observable<ResponseBody> observable = HttpMethods.getInstance(String.format("/api/n/%s",novelId)).getHttpApi().getNovel(novelId);
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
public static void getNovelSites(int novelId,DisposableObserver<ResponseBody> subscriber){
|
public static void getNovelSites(int novelId,DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getNovelSites(novelId);
|
Observable<ResponseBody> observable = HttpMethods.getInstance(String.format("/api/n/%s/mulu-urls",novelId)).getHttpApi().getNovelSites(novelId);
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
public static void getSiteRule(String domain,DisposableObserver<ResponseBody> subscriber){
|
public static void getSiteRule(String domain,DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getNovelRule(domain);
|
Observable<ResponseBody> observable = HttpMethods.getInstance(String.format("/api/s/%s.json",domain)).getHttpApi().getNovelRule(domain);
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void getFirstPage(int sex,DisposableObserver<ResponseBody> subscriber){
|
public static void getFirstPage(int sex,DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getFirstPage(sex);
|
Observable<ResponseBody> observable = HttpMethods.getInstance(String.format("/api/page/index" )).getHttpApi().getFirstPage(sex);
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
public static void getCates(int sex,DisposableObserver<ResponseBody> subscriber){
|
public static void getCates(int sex,DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getCates(sex);
|
Observable<ResponseBody> observable = HttpMethods.getInstance("/api/page/noveltype").getHttpApi().getCates(sex);
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
public static void getCateNovelList(String cate,int pageno,int sex,int progress,DisposableObserver<ResponseBody> subscriber){
|
public static void getCateNovelList(String cate,int pageno,int sex,int progress,DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getCateNovels(cate,pageno,sex,progress);
|
Observable<ResponseBody> observable = HttpMethods.getInstance(String.format("/api/search/nt/%s/%s",cate,pageno ) ).getHttpApi().getCateNovels(cate,pageno,sex,progress);
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void getNovelPaihang(String fn,int sex,DisposableObserver<ResponseBody> subscriber){
|
public static void getNovelPaihang(String fn,int sex,DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getNovelPaihang(fn,sex);
|
Observable<ResponseBody> observable = HttpMethods.getInstance("/api/page/rank").getHttpApi().getNovelPaihang(fn,sex);
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void getNovelsRelated(int novelId,int sex,DisposableObserver<ResponseBody> subscriber){
|
public static void getNovelsRelated(int novelId,int sex,DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getNovelsRelated(novelId,sex);
|
Observable<ResponseBody> observable = HttpMethods.getInstance(String.format("/api/n/%s/about",novelId ) ).getHttpApi().getNovelsRelated(novelId,sex);
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void getNovelsSameAuthor(int novelId,int sex,DisposableObserver<ResponseBody> subscriber){
|
public static void getNovelsSameAuthor(int novelId,int sex,DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getNovelsSameAuthor(novelId,sex);
|
Observable<ResponseBody> observable = HttpMethods.getInstance(String.format("/api/n/%s/author",novelId ) ).getHttpApi().getNovelsSameAuthor(novelId,sex);
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void getSiteRanks( int sex,DisposableObserver<ResponseBody> subscriber){
|
public static void getSiteRanks( int sex,DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getSiteRanks(sex);
|
Observable<ResponseBody> observable = HttpMethods.getInstance("/api/page/siteranks").getHttpApi().getSiteRanks(sex);
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
public static void getSiteRankDetail( String fn,int pageNo,int sex,DisposableObserver<ResponseBody> subscriber){
|
public static void getSiteRankDetail( String fn,int pageNo,int sex,DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getSiteRankDetail(fn,pageNo,sex);
|
Observable<ResponseBody> observable = HttpMethods.getInstance("/api/page/siteranks").getHttpApi().getSiteRankDetail(fn,pageNo,sex);
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void getSearchNovelList( String keyWord,int pageNo,int sex,DisposableObserver<ResponseBody> subscriber){
|
public static void getSearchNovelList( String keyWord,int pageNo,int sex,DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getSeachNolvelist(keyWord,pageNo,sex);
|
Observable<ResponseBody> observable = HttpMethods.getInstance(String.format("/api/search/%s/%s",keyWord ,pageNo)).getHttpApi().getSeachNolvelist(keyWord,pageNo,sex);
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
public static void getSearchTitles(DisposableObserver<ResponseBody> subscriber){
|
public static void getSearchTitles(DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getSearchTitles();
|
Observable<ResponseBody> observable = HttpMethods.getInstance("/api/page/topdata").getHttpApi().getSearchTitles();
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
public static void getHotKeyWords(DisposableObserver<ResponseBody> subscriber){
|
public static void getHotKeyWords(DisposableObserver<ResponseBody> subscriber){
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getSearchHotKeys();
|
Observable<ResponseBody> observable = HttpMethods.getInstance("/api/page/hot-keywords").getHttpApi().getSearchHotKeys();
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
public static void getNovelsByIds(String ids,DisposableObserver<ResponseBody> subscriber){
|
public static void getNovelsByIds(String ids,DisposableObserver<ResponseBody> subscriber){
|
||||||
|
|
||||||
Observable<ResponseBody> observable = HttpMethods.getInstance().getHttpApi().getNovelsByIds(ids);
|
Observable<ResponseBody> observable = HttpMethods.getInstance("/api/novels").getHttpApi().getNovelsByIds(ids);
|
||||||
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
|
}
|
||||||
|
public static void getVersion(DisposableObserver<ResponseBody> subscriber){
|
||||||
|
Observable<ResponseBody> observable = HttpMethods.getInstance("download/version.xml").getHttpApi().getVersion();
|
||||||
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
HttpMethods.getInstance().toSubscribe(observable, subscriber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,13 @@ import android.util.Log;
|
||||||
|
|
||||||
import com.novelbook.android.MyApp;
|
import com.novelbook.android.MyApp;
|
||||||
import com.novelbook.android.netapi.HttpApi;
|
import com.novelbook.android.netapi.HttpApi;
|
||||||
|
import com.novelbook.android.netapi.RandomHost;
|
||||||
import com.novelbook.android.netapi.URLConstant;
|
import com.novelbook.android.netapi.URLConstant;
|
||||||
import com.novelbook.android.utils.CommonUtil;
|
import com.novelbook.android.utils.CommonUtil;
|
||||||
import com.novelbook.android.utils.FileUtils;
|
import com.novelbook.android.utils.FileUtils;
|
||||||
|
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -42,8 +43,8 @@ import retrofit2.Retrofit;
|
||||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
||||||
import retrofit2.converter.gson.GsonConverterFactory;
|
import retrofit2.converter.gson.GsonConverterFactory;
|
||||||
|
|
||||||
import static com.novelbook.android.netapi.URLConstant.getBaseUrl;
|
import static com.novelbook.android.netapi.URLConstant.getRootUrl;
|
||||||
import static com.novelbook.android.netapi.URLConstant.newBaseUrl;
|
import static com.novelbook.android.netapi.URLConstant.newRootUrl;
|
||||||
|
|
||||||
public class HttpMethods {
|
public class HttpMethods {
|
||||||
public String TAG = "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_CONNECT_TIMEOUT = 5;
|
||||||
private static final int DEFAULT_WRITE_TIMEOUT = 5;
|
private static final int DEFAULT_WRITE_TIMEOUT = 5;
|
||||||
private static final int DEFAULT_READ_TIMEOUT = 5;
|
private static final int DEFAULT_READ_TIMEOUT = 5;
|
||||||
|
public static String USERAGENT="";
|
||||||
private Retrofit retrofit;
|
private Retrofit retrofit;
|
||||||
private HttpApi httpApi;
|
private HttpApi httpApi;
|
||||||
/**
|
/**
|
||||||
|
@ -70,7 +72,7 @@ public class HttpMethods {
|
||||||
.client(okHttpClient)
|
.client(okHttpClient)
|
||||||
.addConverterFactory(GsonConverterFactory.create())//json转换成JavaBean
|
.addConverterFactory(GsonConverterFactory.create())//json转换成JavaBean
|
||||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||||
.baseUrl(getBaseUrl())
|
.baseUrl(getRootUrl())
|
||||||
.build();
|
.build();
|
||||||
httpApi = retrofit.create(HttpApi.class);
|
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() {
|
public static HttpMethods getInstance() {
|
||||||
return SingletonHolder.INSTANCE;
|
return SingletonHolder.INSTANCE;
|
||||||
|
@ -104,6 +112,8 @@ public class HttpMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void changeBaseUrl(String baseUrl) {
|
public void changeBaseUrl(String baseUrl) {
|
||||||
|
okHttpBuilder.addInterceptor(new RetryInterceptor());
|
||||||
|
// okHttpBuilder.retryOnConnectionFailure(false);
|
||||||
retrofit = new Retrofit.Builder()
|
retrofit = new Retrofit.Builder()
|
||||||
.client(okHttpBuilder.build())
|
.client(okHttpBuilder.build())
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
@ -112,9 +122,9 @@ public class HttpMethods {
|
||||||
.build();
|
.build();
|
||||||
httpApi = retrofit.create(HttpApi.class);
|
httpApi = retrofit.create(HttpApi.class);
|
||||||
}
|
}
|
||||||
public void changeBaseUrl() {
|
/* public void changeBaseUrl() {
|
||||||
changeBaseUrl(newBaseUrl());
|
changeBaseUrl(newBaseUrl());
|
||||||
}
|
}*/
|
||||||
/**
|
/**
|
||||||
* 获取httpService
|
* 获取httpService
|
||||||
*
|
*
|
||||||
|
@ -167,7 +177,7 @@ public class HttpMethods {
|
||||||
// .addHeader("Accept", "application/json")
|
// .addHeader("Accept", "application/json")
|
||||||
// .addHeader("Content-Type", "application/json; charset=utf-8")
|
// .addHeader("Content-Type", "application/json; charset=utf-8")
|
||||||
// .addHeader("Device", "Android")
|
// .addHeader("Device", "Android")
|
||||||
.removeHeader("User-Agent").addHeader("User-Agent",NetUtil.getUserAgent()) //加 随机agent
|
.removeHeader("User-Agent").addHeader("User-Agent",USERAGENT) //加 随机agent
|
||||||
.tag(NetUtil.currentRequestTag)
|
.tag(NetUtil.currentRequestTag)
|
||||||
.method(originalRequest.method(), originalRequest.body());
|
.method(originalRequest.method(), originalRequest.body());
|
||||||
|
|
||||||
|
@ -207,6 +217,8 @@ public class HttpMethods {
|
||||||
//错误重连
|
//错误重连
|
||||||
okHttpBuilder.retryOnConnectionFailure(true);
|
okHttpBuilder.retryOnConnectionFailure(true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Install the all-trusting trust manager
|
// Install the all-trusting trust manager
|
||||||
final SSLContext sslContext;
|
final SSLContext sslContext;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -8,6 +8,12 @@ import android.util.Log;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import com.novelbook.android.MyApp;
|
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;
|
import java.util.Random;
|
||||||
|
|
||||||
|
@ -22,10 +28,45 @@ public class NetUtil {
|
||||||
|
|
||||||
private static final String TAG= NetUtil.class.getSimpleName();
|
private static final String TAG= NetUtil.class.getSimpleName();
|
||||||
public static int currentRequestTag =0;
|
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;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 判断是否有网络连接
|
* 判断是否有网络连接
|
||||||
*
|
*
|
||||||
|
|
|
@ -14,8 +14,10 @@ import java.net.UnknownHostException;
|
||||||
import javax.net.ssl.SSLHandshakeException;
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
|
|
||||||
import io.reactivex.observers.DisposableObserver;
|
import io.reactivex.observers.DisposableObserver;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
import okhttp3.ResponseBody;
|
import okhttp3.ResponseBody;
|
||||||
import retrofit2.HttpException;
|
import retrofit2.HttpException;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by 眼神 on 2018/3/27.
|
* Created by 眼神 on 2018/3/27.
|
||||||
|
@ -125,6 +127,16 @@ public class OnSuccessAndFaultSub extends DisposableObserver<ResponseBody>
|
||||||
mOnSuccessAndFaultListener.onFault("安全证书异常");
|
mOnSuccessAndFaultListener.onFault("安全证书异常");
|
||||||
} else if (e instanceof HttpException) {//请求的地址不存在
|
} else if (e instanceof HttpException) {//请求的地址不存在
|
||||||
int code = ((HttpException) e).code();
|
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) {
|
if (code == 504) {
|
||||||
Toast.makeText(context,"网络异常,请检查您的网络状态",Toast.LENGTH_LONG).show();
|
Toast.makeText(context,"网络异常,请检查您的网络状态",Toast.LENGTH_LONG).show();
|
||||||
mOnSuccessAndFaultListener.onFault("网络异常,请检查您的网络状态");
|
mOnSuccessAndFaultListener.onFault("网络异常,请检查您的网络状态");
|
||||||
|
@ -142,7 +154,7 @@ public class OnSuccessAndFaultSub extends DisposableObserver<ResponseBody>
|
||||||
//sleep 200
|
//sleep 200
|
||||||
mOnSuccessAndFaultListener.onFault("服务限制");
|
mOnSuccessAndFaultListener.onFault("服务限制");
|
||||||
}else if(code == 502) {
|
}else if(code == 502) {
|
||||||
HttpMethods.getInstance().changeBaseUrl(); //更新基本信息
|
// HttpMethods.getInstance().changeBaseUrl(); //更新基本信息
|
||||||
try {
|
try {
|
||||||
Toast.makeText(context, "服务器开小差了,请重试", Toast.LENGTH_LONG).show();
|
Toast.makeText(context, "服务器开小差了,请重试", Toast.LENGTH_LONG).show();
|
||||||
}catch (Exception e3){
|
}catch (Exception e3){
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ import com.novelbook.android.db.Chapter;
|
||||||
import com.novelbook.android.db.DownloadTask;
|
import com.novelbook.android.db.DownloadTask;
|
||||||
import com.novelbook.android.db.SiteRule;
|
import com.novelbook.android.db.SiteRule;
|
||||||
import com.novelbook.android.netutils.HttpMethods;
|
import com.novelbook.android.netutils.HttpMethods;
|
||||||
|
import com.novelbook.android.netutils.NetUtil;
|
||||||
import com.novelbook.android.utils.BookUtil;
|
import com.novelbook.android.utils.BookUtil;
|
||||||
|
|
||||||
import com.novelbook.android.utils.NovelParseUtil;
|
import com.novelbook.android.utils.NovelParseUtil;
|
||||||
|
@ -146,7 +147,7 @@ public class ServiceDownload extends Service {
|
||||||
cancelId.add(taskId);
|
cancelId.add(taskId);
|
||||||
for(DownloadTask t : downloadTasks){
|
for(DownloadTask t : downloadTasks){
|
||||||
if( t.getId() == taskId){
|
if( t.getId() == taskId){
|
||||||
t.setDownSatus(DownloadTask.DownStatus.等待下载);
|
t.setDownSatus(DownloadTask.DownStatus.暂停下载);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,6 +248,15 @@ public class ServiceDownload extends Service {
|
||||||
startTask();
|
startTask();
|
||||||
}else*/
|
}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");
|
int tIndex = msg.getData().getInt("tIndex");
|
||||||
|
|
||||||
|
|
||||||
|
@ -282,31 +292,54 @@ public class ServiceDownload extends Service {
|
||||||
sendBroadcast(broadcastIntent);
|
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) {
|
if (tasksMap.get(taskId).size() - 1 > chaptIndex) {
|
||||||
if( downloadTasks.get(tIndex).getDownSatus() == DownloadTask.DownStatus.正在下载) {
|
|
||||||
chaptIndex++;
|
chaptIndex++;
|
||||||
}else{
|
// }
|
||||||
|
|
||||||
|
/* else{
|
||||||
|
startNewTask();
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, String.format("%s task done ---- taskId :%s, chapter count %s,chaptIndex %s", TAG, processingTask.getId(),
|
Log.d(TAG, String.format("%s task done ---- taskId :%s, chapter count %s,chaptIndex %s", TAG, processingTask.getId(),
|
||||||
tasksMap.get(processingTask.getId()).size(), chaptIndex));
|
tasksMap.get(processingTask.getId()).size(), chaptIndex));
|
||||||
//章节全部处理完毕了
|
//章节全部处理完毕了
|
||||||
|
|
||||||
if(taskId == processingTask.getId()) {
|
if (taskId == processingTask.getId()
|
||||||
|
&& tasksMapDone.get(taskId) != null
|
||||||
|
&& tasksMapDone.get(taskId).size() == tasksMap.get(taskId).size()) {
|
||||||
int abc = 1;
|
int abc = 1;
|
||||||
abc++;
|
abc++;
|
||||||
if(tasksMap.get(taskId).size() == tasksMapDone.get(taskId).size()) {
|
processingTask.setFinishedChpats(processingTask.getTotalChapts());
|
||||||
processingTask.setStatus(1);
|
processingTask.setStatus(1);
|
||||||
|
processingTask.setDownSatus(DownloadTask.DownStatus.下载完成);
|
||||||
processingTask.update(processingTask.getId());
|
processingTask.update(processingTask.getId());
|
||||||
// tasksMap.remove(processingTask.getId()); //会不会线程冲突?
|
tasksMap.remove(taskId);
|
||||||
}
|
|
||||||
|
|
||||||
|
broadcastIntent = new Intent();
|
||||||
|
broadcastIntent.setAction("ServiceDownload.ChapterContent.finished");
|
||||||
|
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||||
|
broadcastIntent.putExtra("progress", processingTask.getTotalChapts());
|
||||||
|
broadcastIntent.putExtra("status", processingTask.getStatus());
|
||||||
|
broadcastIntent.putExtra("taskId", processingTask.getId());
|
||||||
|
sendBroadcast(broadcastIntent);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//startTask(); //auto start next task
|
startNewTask();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,6 +350,20 @@ public class ServiceDownload extends Service {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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) {
|
private void stopTask(int taskId) {
|
||||||
|
|
||||||
|
@ -354,7 +401,9 @@ public class ServiceDownload extends Service {
|
||||||
* auto next task
|
* auto next task
|
||||||
*/
|
*/
|
||||||
private void startTask() {
|
private void startTask() {
|
||||||
if ( downloadTasks.size()==0){
|
if ( downloadTasks.size()==0 || downloadTasks.size() <=taskIndex){
|
||||||
|
Log.d(TAG,"ServiceDownload No Task to do, exit.");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(processingTask!=null) {
|
if(processingTask!=null) {
|
||||||
|
@ -363,15 +412,17 @@ public class ServiceDownload extends Service {
|
||||||
|
|
||||||
Log.d(TAG,"ServiceDownload start task to download,index " +taskIndex);
|
Log.d(TAG,"ServiceDownload start task to download,index " +taskIndex);
|
||||||
|
|
||||||
if(downloadTasks.size() <=taskIndex){
|
/* if(downloadTasks.size() <=taskIndex){
|
||||||
taskIndex=0;
|
taskIndex=0;
|
||||||
processingTask =null;
|
processingTask =null;
|
||||||
// Log.d(TAG,"No task to download.");
|
// Log.d(TAG,"No task to download.");
|
||||||
// return;
|
// return;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
processingTask = downloadTasks.get(taskIndex);
|
processingTask = downloadTasks.get(taskIndex);
|
||||||
if(processingTask.getDownSatus()== DownloadTask.DownStatus.等待下载){
|
if(processingTask.getDownSatus()== DownloadTask.DownStatus.暂停下载
|
||||||
|
||processingTask.getDownSatus()== DownloadTask.DownStatus.下载完成
|
||||||
|
){
|
||||||
taskIndex++;
|
taskIndex++;
|
||||||
startTask();
|
startTask();
|
||||||
return;
|
return;
|
||||||
|
@ -397,7 +448,15 @@ public class ServiceDownload extends Service {
|
||||||
if(chps!=null && chps.size()>0 && chps.size() >chaptIndex) {
|
if(chps!=null && chps.size()>0 && chps.size() >chaptIndex) {
|
||||||
Chapter chapter = chps.get(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 {
|
try {
|
||||||
ServiceDownload(taskIndex,chapter);
|
ServiceDownload(taskIndex,chapter);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
|
@ -510,7 +569,8 @@ public class ServiceDownload extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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 title = chapter.getChapterName();
|
||||||
String chapterContent = title+ "\n" + NovelParseUtil.getChapterContent(bodyStr, siteJson);
|
String chapterContent = title+ "\n" + NovelParseUtil.getChapterContent(bodyStr, siteJson);
|
||||||
char[] buf = chapterContent.toCharArray();
|
char[] buf = chapterContent.toCharArray();
|
||||||
|
|
|
@ -155,7 +155,7 @@ public class ServiceDownloadIntent extends IntentService {
|
||||||
private void stopTask(int taskId) {
|
private void stopTask(int taskId) {
|
||||||
for(DownloadTask dt : downloadTasks){
|
for(DownloadTask dt : downloadTasks){
|
||||||
if(dt.getId() == taskId){
|
if(dt.getId() == taskId){
|
||||||
dt.setDownSatus(DownloadTask.DownStatus.等待下载);
|
dt.setDownSatus(DownloadTask.DownStatus.暂停下载);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ public class ServiceDownloadIntent extends IntentService {
|
||||||
startTask();
|
startTask();
|
||||||
}else if(msg.what==2){
|
}else if(msg.what==2){
|
||||||
|
|
||||||
if( downloadTasks.get(taskIndex).getDownSatus() == DownloadTask.DownStatus.等待下载){
|
if( downloadTasks.get(taskIndex).getDownSatus() == DownloadTask.DownStatus.暂停下载){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(tasksMap.get(processingTask.getId())==null){
|
if(tasksMap.get(processingTask.getId())==null){
|
||||||
|
@ -229,7 +229,7 @@ public class ServiceDownloadIntent extends IntentService {
|
||||||
}
|
}
|
||||||
|
|
||||||
processingTask = downloadTasks.get(taskIndex);
|
processingTask = downloadTasks.get(taskIndex);
|
||||||
if(processingTask.getDownSatus()== DownloadTask.DownStatus.等待下载){
|
if(processingTask.getDownSatus()== DownloadTask.DownStatus.暂停下载){
|
||||||
taskIndex++;
|
taskIndex++;
|
||||||
startTask();
|
startTask();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -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<String, String> parseXml(InputStream inStream) throws Exception
|
||||||
|
{
|
||||||
|
HashMap<String, String> hashMap = new HashMap<String, String>();
|
||||||
|
|
||||||
|
// 实例化一个文档构建器工厂
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<String, String> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 濡拷绁存潪顖欐閺囧瓨鏌<EFBFBD>
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 閼惧嘲褰囨潪顖欐閻楀牊婀伴崣锟<EFBFBD> *
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 閼惧嘲褰囨潪顖欐閻楀牊婀伴崣锟<EFBFBD> *
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 閺勫墽銇氭潪顖欐閺囧瓨鏌婄<EFBFBD>纭呯樈濡楋拷
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// 閺嬪嫰锟界<EFBFBD>纭呯樈濡楋拷
|
||||||
|
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();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 閺勫墽銇氭潪顖欐娑撳娴囩<EFBFBD>纭呯樈濡楋拷
|
||||||
|
*/
|
||||||
|
private void showDownloadDialog()
|
||||||
|
{
|
||||||
|
// 閺嬪嫰锟芥潪顖欐娑撳娴囩<EFBFBD>纭呯樈濡楋拷
|
||||||
|
Builder builder = new Builder(mContext);
|
||||||
|
builder.setTitle(R.string.soft_updating);
|
||||||
|
// 缂佹瑤绗呮潪钘夘嚠鐠囨繃顢嬫晶鐐插鏉╂稑瀹抽弶锟<EFBFBD>
|
||||||
|
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();
|
||||||
|
// 鐠佸墽鐤嗛崣鏍ㄧХ閻樿埖锟<EFBFBD>
|
||||||
|
cancelUpdate = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mDownloadDialog = builder.create();
|
||||||
|
mDownloadDialog.setCancelable(false);
|
||||||
|
mDownloadDialog.show();
|
||||||
|
// 閻滄澘婀弬鍥︽
|
||||||
|
downloadApk();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 娑撳娴嘺pk閺傚洣娆<EFBFBD>
|
||||||
|
*/
|
||||||
|
private void downloadApk()
|
||||||
|
{
|
||||||
|
// 閸氼垰濮╅弬鎵殠缁嬪绗呮潪鍊熻拫娴狅拷
|
||||||
|
new downloadApkThread().start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 娑撳娴囬弬鍥︽缁捐法鈻<EFBFBD>
|
||||||
|
*/
|
||||||
|
private class downloadApkThread extends Thread
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 閸掋倖鏌嘢D閸椻剝妲搁崥锕<EFBFBD>摠閸︻煉绱濋獮鏈电瑬閺勵垰鎯侀崗閿嬫箒鐠囪鍟撻弶鍐
|
||||||
|
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
|
||||||
|
{
|
||||||
|
// 閼惧嘲绶辩<EFBFBD>妯哄亶閸楋紕娈戠捄顖氱窞
|
||||||
|
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);
|
||||||
|
// 閸掋倖鏌囬弬鍥︽閻╊喖缍嶉弰顖氭儊鐎涙ê婀<EFBFBD>
|
||||||
|
if (!file.exists())
|
||||||
|
{
|
||||||
|
file.mkdir();
|
||||||
|
}
|
||||||
|
File apkFile = new File(mSavePath, mHashMap.get("name"));
|
||||||
|
FileOutputStream fos = new FileOutputStream(apkFile);
|
||||||
|
int count = 0;
|
||||||
|
// 缂傛挸鐡<EFBFBD>
|
||||||
|
byte buf[] = new byte[1024];
|
||||||
|
// 閸愭瑥鍙嗛崚鐗堟瀮娴犳湹鑵<EFBFBD>
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int numread = is.read(buf);
|
||||||
|
count += numread;
|
||||||
|
// 鐠侊紕鐣绘潻娑樺閺夆<EFBFBD>缍呯純锟<EFBFBD>
|
||||||
|
progress = (int) (((float) count / length) * 100);
|
||||||
|
// 閺囧瓨鏌婃潻娑樺
|
||||||
|
mHandler.sendEmptyMessage(DOWNLOAD);
|
||||||
|
if (numread <= 0)
|
||||||
|
{
|
||||||
|
// 娑撳娴囩<EFBFBD>灞惧灇
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
// 閸欐牗绉锋稉瀣祰鐎电鐦藉鍡樻▔缁<EFBFBD>拷
|
||||||
|
mDownloadDialog.dismiss();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 鐎瑰顥朅PK閺傚洣娆<EFBFBD>
|
||||||
|
*/
|
||||||
|
private void installApk()
|
||||||
|
{
|
||||||
|
File apkfile = new File(mSavePath, mHashMap.get("name"));
|
||||||
|
if (!apkfile.exists())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 闁俺绻僆ntent鐎瑰顥朅PK閺傚洣娆<EFBFBD>
|
||||||
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
|
i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
|
||||||
|
mContext.startActivity(i);
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
@ -749,7 +750,7 @@ int muluRetryCount =0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String url = mSite.getMuluUrl();
|
String url = mSite.getMuluUrl();
|
||||||
Request request = getTagRequest(url,mNovel.getMaxAge());
|
Request request = getTagRequest(url,mSite.getDomain(), mNovel.getMaxAge());
|
||||||
|
|
||||||
mMuluStatus = MuluStatus.isDownloading;
|
mMuluStatus = MuluStatus.isDownloading;
|
||||||
long startTime= new Date().getTime();
|
long startTime= new Date().getTime();
|
||||||
|
@ -1345,7 +1346,7 @@ int muluRetryCount =0;
|
||||||
String targetSiteName = msg.getData().getString("siteName");
|
String targetSiteName = msg.getData().getString("siteName");
|
||||||
Log.d(TAG, String.format("prepare book changing Source:target %s -- %s to open chapter %s"
|
Log.d(TAG, String.format("prepare book changing Source:target %s -- %s to open chapter %s"
|
||||||
,mNovel.getDomain(),targetSiteName,msg.arg1));
|
,mNovel.getDomain(),targetSiteName,msg.arg1));
|
||||||
|
if(pagefactory!=null)
|
||||||
pagefactory.changeSource(targetSiteName, mNovel.getDomain(),msg.arg1,getChapter(msg.arg1).getChapterName());
|
pagefactory.changeSource(targetSiteName, mNovel.getDomain(),msg.arg1,getChapter(msg.arg1).getChapterName());
|
||||||
|
|
||||||
|
|
||||||
|
@ -1436,7 +1437,7 @@ int muluRetryCount =0;
|
||||||
char[] block=null;
|
char[] block=null;
|
||||||
if(chaptCache.containsKey(Integer.valueOf(index))) {
|
if(chaptCache.containsKey(Integer.valueOf(index))) {
|
||||||
block = chaptCache .get(index).getData().get();
|
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));
|
// Log.d(TAG, String.format("prepare book begin to load content for chapter %s", index));
|
||||||
if (block == null) {
|
if (block == null) {
|
||||||
|
@ -1626,6 +1627,10 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte
|
||||||
|
|
||||||
}
|
}
|
||||||
Chapter chapter = mChapters.get(index -1);
|
Chapter chapter = mChapters.get(index -1);
|
||||||
|
String refUrl="";
|
||||||
|
if(index>1){
|
||||||
|
refUrl = mChapters.get(index -2).getChapterUrl();
|
||||||
|
}
|
||||||
String url = chapter.getChapterUrl();
|
String url = chapter.getChapterUrl();
|
||||||
if( TextUtils.isEmpty( url)){
|
if( TextUtils.isEmpty( url)){
|
||||||
handler.sendEmptyMessage(1);
|
handler.sendEmptyMessage(1);
|
||||||
|
@ -1640,7 +1645,7 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte
|
||||||
JSONObject siteJson = new JSONObject();
|
JSONObject siteJson = new JSONObject();
|
||||||
siteJson.put("chapterContentRegex", mSiteRule.getChapterContentRegex());
|
siteJson.put("chapterContentRegex", mSiteRule.getChapterContentRegex());
|
||||||
siteJson.put("chapterContentDumpRegex", mSiteRule.getChapterContentDumpRegex());
|
siteJson.put("chapterContentDumpRegex", mSiteRule.getChapterContentDumpRegex());
|
||||||
Request request = getTagRequest(url, -1);
|
Request request = getTagRequest(url, refUrl,-1);
|
||||||
HttpMethods.getOkClient().newCall(request).enqueue(new Callback() {
|
HttpMethods.getOkClient().newCall(request).enqueue(new Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Call call, IOException e) {
|
public void onFailure(Call call, IOException e) {
|
||||||
|
@ -1742,13 +1747,17 @@ private void loadChaptContent(final int chapterIndex) throws JSONException, Inte
|
||||||
* @param maxAge
|
* @param maxAge
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private Request getTagRequest(String url, int maxAge) {
|
private Request getTagRequest(String url, String refUrl ,int maxAge) {
|
||||||
|
|
||||||
Request.Builder builder = new Request.Builder()
|
Request.Builder builder = new Request.Builder()
|
||||||
.tag(mNovel.getNovelId()) //标记 请求的tag,切换小说或离开小说界面(BookActivity) 时 取消未执行完毕的 此tag的所有请求
|
.tag(mNovel.getNovelId()) //标记 请求的tag,切换小说或离开小说界面(BookActivity) 时 取消未执行完毕的 此tag的所有请求
|
||||||
.url(url)
|
.url(url)
|
||||||
.removeHeader("Pragma");
|
.removeHeader("Pragma");
|
||||||
|
|
||||||
|
if(!TextUtils.isEmpty(refUrl)){
|
||||||
|
builder.header("Referer",refUrl);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < mSiteRule.getHeaders().length; i += 2) {
|
for (int i = 0; i < mSiteRule.getHeaders().length; i += 2) {
|
||||||
builder.header(mSiteRule.getHeaders()[i], mSiteRule.getHeaders()[i + 1]);
|
builder.header(mSiteRule.getHeaders()[i], mSiteRule.getHeaders()[i + 1]);
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ public class Config {
|
||||||
private final static String SYSTEM_LIGHT_KEY = "systemlight";
|
private final static String SYSTEM_LIGHT_KEY = "systemlight";
|
||||||
private final static String PAGE_MODE_KEY = "pagemode";
|
private final static String PAGE_MODE_KEY = "pagemode";
|
||||||
private final static String KEY_BASE_URY = "baseurl";
|
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_DEFAULT = "";
|
||||||
public final static String FONTTYPE_QIHEI = "font/qihei.ttf";
|
public final static String FONTTYPE_QIHEI = "font/qihei.ttf";
|
||||||
public final static String FONTTYPE_WAWA = "font/font1.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){
|
public void setBaseUrl(String baseUrl){
|
||||||
sp.edit().putString(KEY_BASE_URY,baseUrl).commit();
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ public class Constants {
|
||||||
public static final boolean SHOWAD =false ;
|
public static final boolean SHOWAD =false ;
|
||||||
public static final int MAXAGE_MAX =60*60*24*28; //28 天 ;
|
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 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 String[] HOT_KEYS_VALUE = {};
|
||||||
public static int SEX=1; //1 男,2女
|
public static int SEX=1; //1 男,2女
|
||||||
public static String A_Regex = "<a[^>]+href[\\s]*=[\\s]*['\"]?([^'\"]+)['\"\\s]?[^>]*>([^<]+)<"; //TODO: 从服务器更新
|
public static String A_Regex = "<a[^>]+href[\\s]*=[\\s]*['\"]?([^'\"]+)['\"\\s]?[^>]*>([^<]+)<"; //TODO: 从服务器更新
|
||||||
|
@ -24,4 +25,5 @@ public class Constants {
|
||||||
// public static List<String> lstProgress=null;
|
// public static List<String> lstProgress=null;
|
||||||
public static boolean showDialogOnUi =true;
|
public static boolean showDialogOnUi =true;
|
||||||
public static boolean showDialogOnUiPage =false;
|
public static boolean showDialogOnUiPage =false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,16 @@ public class FileUtils {
|
||||||
|
|
||||||
Fileutil.deleteDir(getNovelDir(novelId));
|
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) {
|
public static long getCacheSize(int noveId) {
|
||||||
return Fileutil.getDirSize(getNovelDir(noveId));
|
return Fileutil.getDirSize(getNovelDir(noveId));
|
||||||
}
|
}
|
||||||
|
|
|
@ -332,22 +332,6 @@ public static String enconding(ResponseBody body, String encode) throws Unsupp
|
||||||
}
|
}
|
||||||
return s;
|
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;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -232,7 +232,7 @@ public class PageFactory implements ChangeSource{
|
||||||
chaptId = chaptId > 0 ? chaptId : 1;
|
chaptId = chaptId > 0 ? chaptId : 1;
|
||||||
final File file = new File(getChapterFileName(chaptId));
|
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 > getChapters().size() ? getChapters().size() : chaptId;
|
||||||
|
|
||||||
chaptId = chaptId > 0 ? chaptId : 1;
|
chaptId = chaptId > 0 ? chaptId : 1;
|
||||||
|
@ -290,7 +290,7 @@ public class PageFactory implements ChangeSource{
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Log.d(TAG, String.format("prepare book to download chapter %s ,thread.name %s",chid,Thread.currentThread().getName() ) );
|
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();
|
super.run();
|
||||||
}}.start();
|
}}.start();
|
||||||
|
@ -891,6 +891,7 @@ public static boolean busy(){
|
||||||
m_islastPage = false;
|
m_islastPage = false;
|
||||||
|
|
||||||
if(null == currentPage){
|
if(null == currentPage){
|
||||||
|
changeChapter(mBookUtil.getChapterNo());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(mBookUtil.isBusy()){
|
if(mBookUtil.isBusy()){
|
||||||
|
@ -900,7 +901,7 @@ public static boolean busy(){
|
||||||
if (currentPage.getEnd() >= mBookUtil.getBookLen()) {
|
if (currentPage.getEnd() >= mBookUtil.getBookLen()) {
|
||||||
Log.d(TAG,"已经是本章最后一页了");
|
Log.d(TAG,"已经是本章最后一页了");
|
||||||
|
|
||||||
m_islastPage =currentChapter >= mBookUtil.getChapters().size();
|
m_islastPage =currentChapter == mBookUtil.getChapters().size();
|
||||||
if ( m_islastPage){
|
if ( m_islastPage){
|
||||||
Toast.makeText(mContext, "已经是最后一页了", Toast.LENGTH_SHORT).show();
|
Toast.makeText(mContext, "已经是最后一页了", Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -23,6 +23,14 @@
|
||||||
|
|
||||||
</android.support.design.widget.AppBarLayout>
|
</android.support.design.widget.AppBarLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvMsg"
|
||||||
|
android:textColor="@color/red"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<android.support.v7.widget.RecyclerView
|
||||||
android:id="@+id/recycleView"
|
android:id="@+id/recycleView"
|
||||||
style="@style/llOutside"
|
style="@style/llOutside"
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
android:textColor="@color/grey" />
|
android:textColor="@color/grey" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_marginTop="5dp"
|
android:layout_marginTop="5dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
|
@ -64,10 +65,23 @@
|
||||||
android:layout_height="20dp"
|
android:layout_height="20dp"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
android:gravity="right"
|
android:gravity="right"
|
||||||
android:layout_marginStart="50dp"
|
android:layout_marginStart="0dp"
|
||||||
android:text="未知"
|
android:text="未知"
|
||||||
|
android:layout_weight="0"
|
||||||
android:textColor="@color/grey" />
|
android:textColor="@color/grey" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvSize"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:gravity="right"
|
||||||
|
android:layout_marginStart="0dp"
|
||||||
|
android:text="未知"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:textColor="@color/grey" />
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,9 +101,9 @@
|
||||||
<ImageView
|
<ImageView
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:id="@+id/imgStart"
|
android:id="@+id/imgStart"
|
||||||
android:layout_width="20dp"
|
android:layout_width="25dp"
|
||||||
android:layout_height="20dp"
|
android:layout_height="25dp"
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="15dp"
|
||||||
android:src="@mipmap/play"
|
android:src="@mipmap/play"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -4,22 +4,16 @@
|
||||||
tools:showIn="navigation_view">
|
tools:showIn="navigation_view">
|
||||||
|
|
||||||
<group android:checkableBehavior="single">
|
<group android:checkableBehavior="single">
|
||||||
<item
|
|
||||||
android:id="@+id/nav_camera"
|
|
||||||
android:icon="@drawable/ic_mood_black_24dp"
|
|
||||||
android:title="消息通知" />
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_gallery"
|
android:id="@+id/nav_gallery"
|
||||||
android:icon="@drawable/ic_mood_black_24dp"
|
android:icon="@drawable/ic_mood_black_24dp"
|
||||||
android:title="最近浏览" />
|
android:title="最近浏览" />
|
||||||
<item
|
|
||||||
android:id="@+id/nav_slideshow"
|
|
||||||
android:icon="@drawable/ic_mood_black_24dp"
|
|
||||||
android:title="我的书单" />
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_huancun"
|
android:id="@+id/nav_huancun"
|
||||||
android:icon="@drawable/ic_mood_black_24dp"
|
android:icon="@drawable/ic_mood_black_24dp"
|
||||||
android:title="缓存管理" />
|
android:title="下载管理" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_haoping"
|
android:id="@+id/nav_haoping"
|
||||||
android:icon="@drawable/ic_mood_black_24dp"
|
android:icon="@drawable/ic_mood_black_24dp"
|
||||||
|
@ -32,10 +26,7 @@
|
||||||
android:id="@+id/nav_advice"
|
android:id="@+id/nav_advice"
|
||||||
android:icon="@drawable/ic_mood_black_24dp"
|
android:icon="@drawable/ic_mood_black_24dp"
|
||||||
android:title="意见反馈" />
|
android:title="意见反馈" />
|
||||||
<item
|
|
||||||
android:id="@+id/nav_nightmode"
|
|
||||||
android:icon="@drawable/ic_mood_black_24dp"
|
|
||||||
android:title="夜间模式" />
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_setup"
|
android:id="@+id/nav_setup"
|
||||||
android:icon="@drawable/ic_menu_send"
|
android:icon="@drawable/ic_menu_send"
|
||||||
|
|
|
@ -112,7 +112,7 @@
|
||||||
<string name="title_activity_main5">Main5Activity</string>
|
<string name="title_activity_main5">Main5Activity</string>
|
||||||
<string name="title_on_shelf">加入书架</string>
|
<string name="title_on_shelf">加入书架</string>
|
||||||
<string name="title_read">立即阅读</string>
|
<string name="title_read">立即阅读</string>
|
||||||
<string name="title_download">下载序列</string>
|
<string name="title_download">下载管理</string>
|
||||||
<string name="title_activity_paihangbang">榜</string>
|
<string name="title_activity_paihangbang">榜</string>
|
||||||
<string name="title_activity_main6">Main6Activity</string>
|
<string name="title_activity_main6">Main6Activity</string>
|
||||||
<string name="section_format">Hello World from section: %1$d</string>
|
<string name="section_format">Hello World from section: %1$d</string>
|
||||||
|
@ -191,6 +191,13 @@
|
||||||
<string name="noRecordInshelf">书架空空如也</string>
|
<string name="noRecordInshelf">书架空空如也</string>
|
||||||
<string name="msgLoading">正在加载...</string>
|
<string name="msgLoading">正在加载...</string>
|
||||||
<string name="refresh">重试</string>
|
<string name="refresh">重试</string>
|
||||||
|
<string name="soft_update_no">已是最新版本</string>
|
||||||
|
<string name="soft_update_title">有新版本了</string>
|
||||||
|
<string name="soft_update_info">更新日志</string>
|
||||||
|
<string name="soft_update_updatebtn">更新</string>
|
||||||
|
<string name="soft_update_later">以后再说</string>
|
||||||
|
<string name="soft_updating">正在更新</string>
|
||||||
|
<string name="soft_update_cancel">取消更新</string>
|
||||||
|
|
||||||
<string-array name="voicer_cloud_entries">
|
<string-array name="voicer_cloud_entries">
|
||||||
<item>小燕—女青、中英、普通话</item>
|
<item>小燕—女青、中英、普通话</item>
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
</facet>
|
</facet>
|
||||||
<facet type="android" name="Android">
|
<facet type="android" name="Android">
|
||||||
<configuration>
|
<configuration>
|
||||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
<option name="SELECTED_BUILD_VARIANT" value="huaweiDebug" />
|
||||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
<option name="ASSEMBLE_TASK_NAME" value="assembleHuaweiDebug" />
|
||||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
<option name="COMPILE_JAVA_TASK_NAME" value="compileHuaweiDebugSources" />
|
||||||
<afterSyncTasks>
|
<afterSyncTasks>
|
||||||
<task>generateDebugSources</task>
|
<task>generateHuaweiDebugSources</task>
|
||||||
</afterSyncTasks>
|
</afterSyncTasks>
|
||||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||||
|
@ -23,23 +23,65 @@
|
||||||
</facet>
|
</facet>
|
||||||
</component>
|
</component>
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||||
<output url="file://$MODULE_DIR$/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes" />
|
<output url="file://$MODULE_DIR$/build/intermediates/javac/huaweiDebug/compileHuaweiDebugJavaWithJavac/classes" />
|
||||||
<output-test url="file://$MODULE_DIR$/build/intermediates/javac/debugUnitTest/compileDebugUnitTestJavaWithJavac/classes" />
|
<output-test url="file://$MODULE_DIR$/build/intermediates/javac/huaweiDebugUnitTest/compileHuaweiDebugUnitTestJavaWithJavac/classes" />
|
||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/huawei/debug" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debug/compileDebugAidl/out" isTestSource="false" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/huaweiDebug/compileHuaweiDebugAidl/out" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/huawei/debug" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debug/compileDebugRenderscript/out" isTestSource="false" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/huaweiDebug/compileHuaweiDebugRenderscript/out" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/huawei/debug" type="java-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/huawei/debug" type="java-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/huaweiDebug/res" type="java-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debugAndroidTest/compileDebugAndroidTestAidl/out" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/huaweiDebug/resources" type="java-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/huaweiDebug/assets" type="java-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debugAndroidTest/compileDebugAndroidTestRenderscript/out" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/huaweiDebug/aidl" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/huaweiDebug/java" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/huaweiDebug/rs" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/test/debug" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/huaweiDebug/shaders" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/huawei/debug" isTestSource="true" generated="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/huaweiDebugAndroidTest/compileHuaweiDebugAndroidTestAidl/out" isTestSource="true" generated="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/huawei/debug" isTestSource="true" generated="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/huaweiDebugAndroidTest/compileHuaweiDebugAndroidTestRenderscript/out" isTestSource="true" generated="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/huawei/debug" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/huawei/debug" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuaweiDebug/res" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuaweiDebug/resources" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuaweiDebug/assets" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuaweiDebug/aidl" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuaweiDebug/java" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuaweiDebug/rs" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuaweiDebug/shaders" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/test/huawei/debug" isTestSource="true" generated="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuaweiDebug/res" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuaweiDebug/resources" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuaweiDebug/assets" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuaweiDebug/aidl" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuaweiDebug/java" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuaweiDebug/rs" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuaweiDebug/shaders" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/huawei/res" type="java-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/huawei/resources" type="java-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/huawei/assets" type="java-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/huawei/aidl" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/huawei/java" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/huawei/rs" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/huawei/shaders" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuawei/res" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuawei/resources" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuawei/assets" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuawei/aidl" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuawei/java" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuawei/rs" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTestHuawei/shaders" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuawei/res" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuawei/resources" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuawei/assets" type="java-test-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuawei/aidl" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuawei/java" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuawei/rs" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testHuawei/shaders" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
||||||
|
@ -104,13 +146,17 @@
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javac" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javac" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifest-checker" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifest-checker" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged-not-compiled-resources" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_assets" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_assets" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_manifests" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_manifests" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/metadata_feature_manifest" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/metadata_feature_manifest" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/prebuild" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/prebuild" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/processed_res" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/processed_res" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard-files" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard-rules" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res_stripped" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/resources" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/resources" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shader_assets" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shader_assets" />
|
||||||
|
@ -120,6 +166,8 @@
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/reports" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/test-results" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Android API 28 Platform" jdkType="Android SDK" />
|
<orderEntry type="jdk" jdkName="Android API 28 Platform" jdkType="Android SDK" />
|
||||||
|
@ -173,6 +221,7 @@
|
||||||
<orderEntry type="library" name="Gradle: com.android.support.constraint:constraint-layout-solver:1.1.3@jar" level="project" />
|
<orderEntry type="library" name="Gradle: com.android.support.constraint:constraint-layout-solver:1.1.3@jar" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="Gradle: net.sf.kxml:kxml2:2.3.0@jar" level="project" />
|
<orderEntry type="library" scope="TEST" name="Gradle: net.sf.kxml:kxml2:2.3.0@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: io.reactivex.rxjava2:rxandroid:2.1.0@aar" level="project" />
|
<orderEntry type="library" name="Gradle: io.reactivex.rxjava2:rxandroid:2.1.0@aar" level="project" />
|
||||||
|
<orderEntry type="library" name="Gradle: com.umeng.umsdk:analytics:8.0.2@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.jakewharton:butterknife-annotations:9.0.0@jar" level="project" />
|
<orderEntry type="library" name="Gradle: com.jakewharton:butterknife-annotations:9.0.0@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.android.support:documentfile:28.0.0@aar" level="project" />
|
<orderEntry type="library" name="Gradle: com.android.support:documentfile:28.0.0@aar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.jakewharton:butterknife:9.0.0@aar" level="project" />
|
<orderEntry type="library" name="Gradle: com.jakewharton:butterknife:9.0.0@aar" level="project" />
|
||||||
|
@ -189,6 +238,7 @@
|
||||||
<orderEntry type="library" name="Gradle: com.timqi.collapsibletextview:library:1.1.2@aar" level="project" />
|
<orderEntry type="library" name="Gradle: com.timqi.collapsibletextview:library:1.1.2@aar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.squareup.retrofit2:converter-gson:2.5.0@jar" level="project" />
|
<orderEntry type="library" name="Gradle: com.squareup.retrofit2:converter-gson:2.5.0@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.android.support:support-core-ui:28.0.0@aar" level="project" />
|
<orderEntry type="library" name="Gradle: com.android.support:support-core-ui:28.0.0@aar" level="project" />
|
||||||
|
<orderEntry type="library" name="Gradle: com.umeng.umsdk:common:2.0.2@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:logging-interceptor:3.14.0@jar" level="project" />
|
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:logging-interceptor:3.14.0@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.android.support:asynclayoutinflater:28.0.0@aar" level="project" />
|
<orderEntry type="library" name="Gradle: com.android.support:asynclayoutinflater:28.0.0@aar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.android.support.constraint:constraint-layout:1.1.3@aar" level="project" />
|
<orderEntry type="library" name="Gradle: com.android.support.constraint:constraint-layout:1.1.3@aar" level="project" />
|
||||||
|
|
Loading…
Reference in New Issue