| @@ -0,0 +1 @@ | |||||
| WebEBook | |||||
| @@ -1,6 +1,6 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project version="4"> | <project version="4"> | ||||
| <component name="CompilerConfiguration"> | <component name="CompilerConfiguration"> | ||||
| <bytecodeTargetLevel target="1.8" /> | |||||
| <bytecodeTargetLevel target="11" /> | |||||
| </component> | </component> | ||||
| </project> | </project> | ||||
| @@ -0,0 +1,17 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <project version="4"> | |||||
| <component name="deploymentTargetDropDown"> | |||||
| <targetSelectedWithDropDown> | |||||
| <Target> | |||||
| <type value="QUICK_BOOT_TARGET" /> | |||||
| <deviceKey> | |||||
| <Key> | |||||
| <type value="VIRTUAL_DEVICE_PATH" /> | |||||
| <value value="C:\Users\Administrator\.android\avd\EScreen_API_27.avd" /> | |||||
| </Key> | |||||
| </deviceKey> | |||||
| </Target> | |||||
| </targetSelectedWithDropDown> | |||||
| <timeTargetWasSelectedWithDropDown value="2022-04-20T04:41:22.102557200Z" /> | |||||
| </component> | |||||
| </project> | |||||
| @@ -5,7 +5,7 @@ | |||||
| <option name="linkedExternalProjectsSettings"> | <option name="linkedExternalProjectsSettings"> | ||||
| <GradleProjectSettings> | <GradleProjectSettings> | ||||
| <option name="delegatedBuild" value="true" /> | <option name="delegatedBuild" value="true" /> | ||||
| <option name="testRunner" value="PLATFORM" /> | |||||
| <option name="testRunner" value="GRADLE" /> | |||||
| <option name="disableWrapperSourceDistributionNotification" value="true" /> | <option name="disableWrapperSourceDistributionNotification" value="true" /> | ||||
| <option name="distributionType" value="DEFAULT_WRAPPED" /> | <option name="distributionType" value="DEFAULT_WRAPPED" /> | ||||
| <option name="externalProjectPath" value="$PROJECT_DIR$" /> | <option name="externalProjectPath" value="$PROJECT_DIR$" /> | ||||
| @@ -16,7 +16,6 @@ | |||||
| </set> | </set> | ||||
| </option> | </option> | ||||
| <option name="resolveModulePerSourceSet" value="false" /> | <option name="resolveModulePerSourceSet" value="false" /> | ||||
| <option name="useQualifiedModuleNames" value="true" /> | |||||
| </GradleProjectSettings> | </GradleProjectSettings> | ||||
| </option> | </option> | ||||
| </component> | </component> | ||||
| @@ -1,6 +1,16 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project version="4"> | <project version="4"> | ||||
| <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> | |||||
| <component name="DesignSurface"> | |||||
| <option name="filePathToZoomLevelMap"> | |||||
| <map> | |||||
| <entry key="..\:/work/escreen/app/src/main/res/layout/activity_book.xml" value="0.37135416666666665" /> | |||||
| <entry key="..\:/work/escreen/app/src/main/res/layout/activity_main.xml" value="0.37135416666666665" /> | |||||
| <entry key="..\:/work/escreen/app/src/main/res/layout/activity_main1.xml" value="0.37135416666666665" /> | |||||
| <entry key="..\:/work/escreen/app/src/main/res/layout/activity_note.xml" value="0.37135416666666665" /> | |||||
| </map> | |||||
| </option> | |||||
| </component> | |||||
| <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK"> | |||||
| <output url="file://$PROJECT_DIR$/build/classes" /> | <output url="file://$PROJECT_DIR$/build/classes" /> | ||||
| </component> | </component> | ||||
| <component name="ProjectType"> | <component name="ProjectType"> | ||||
| @@ -1,12 +0,0 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <project version="4"> | |||||
| <component name="RunConfigurationProducerService"> | |||||
| <option name="ignoredProducers"> | |||||
| <set> | |||||
| <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" /> | |||||
| <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" /> | |||||
| <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" /> | |||||
| </set> | |||||
| </option> | |||||
| </component> | |||||
| </project> | |||||
| @@ -6,13 +6,13 @@ apply plugin: 'kotlin-android-extensions' | |||||
| //apply from: 'https://raw.githubusercontent.com/apache/incubator-weex/release/0.28/android/sdk/buildSrc/download_jsc.gradle' | //apply from: 'https://raw.githubusercontent.com/apache/incubator-weex/release/0.28/android/sdk/buildSrc/download_jsc.gradle' | ||||
| apply plugin: 'org.greenrobot.greendao' | |||||
| //apply plugin: 'org.greenrobot.greendao' | |||||
| android { | android { | ||||
| compileSdkVersion 30 | compileSdkVersion 30 | ||||
| buildToolsVersion "30.0.3" | buildToolsVersion "30.0.3" | ||||
| defaultConfig { | defaultConfig { | ||||
| applicationId "com.yzx.webebook" | |||||
| applicationId "com.yzx.escreen" | |||||
| // minSdkVersion 26 | // minSdkVersion 26 | ||||
| minSdkVersion 21 | minSdkVersion 21 | ||||
| targetSdkVersion 25 | targetSdkVersion 25 | ||||
| @@ -20,9 +20,9 @@ android { | |||||
| versionName "2.0.1" | versionName "2.0.1" | ||||
| testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | ||||
| ndk { | |||||
| abiFilters "armeabi-v7a", "arm64-v8a", "x86" | |||||
| } | |||||
| // ndk { | |||||
| // abiFilters "armeabi-v7a", "arm64-v8a", "x86" | |||||
| // } | |||||
| } | } | ||||
| signingConfigs { | signingConfigs { | ||||
| yzx { | yzx { | ||||
| @@ -115,11 +115,11 @@ android { | |||||
| } | } | ||||
| greendao{ | |||||
| schemaVersion 4 | |||||
| daoPackage 'com.yzx.webebook.model.gen' | |||||
| targetGenDir 'src/main/java' | |||||
| } | |||||
| //greendao{ | |||||
| // schemaVersion 4 | |||||
| // daoPackage 'com.yzx.webebook.model.gen' | |||||
| // targetGenDir 'src/main/java' | |||||
| //} | |||||
| repositories { | repositories { | ||||
| maven { | maven { | ||||
| @@ -144,7 +144,6 @@ dependencies { | |||||
| testImplementation 'junit:junit:4.12' | testImplementation 'junit:junit:4.12' | ||||
| androidTestImplementation 'androidx.test.ext:junit:1.1.0' | androidTestImplementation 'androidx.test.ext:junit:1.1.0' | ||||
| androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' | ||||
| implementation files('libs/wenote.jar') | |||||
| implementation 'com.github.bumptech.glide:glide:4.11.0' | implementation 'com.github.bumptech.glide:glide:4.11.0' | ||||
| implementation 'com.lzy.net:okgo:3.0.4' | implementation 'com.lzy.net:okgo:3.0.4' | ||||
| implementation 'com.blankj:utilcodex:1.30.5' | implementation 'com.blankj:utilcodex:1.30.5' | ||||
| @@ -157,17 +156,19 @@ dependencies { | |||||
| implementation 'com.github.thomhurst:RoundImageView:1.0.2' | implementation 'com.github.thomhurst:RoundImageView:1.0.2' | ||||
| implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4' | implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4' | ||||
| implementation 'org.apache.weex:sdk:0.28.0' | |||||
| implementation 'com.alibaba:fastjson:1.1.46.android' | |||||
| // implementation 'org.apache.weex:sdk:0.28.0' | |||||
| // implementation 'com.alibaba:fastjson:1.1.46.android' | |||||
| //ORM Database | //ORM Database | ||||
| implementation deps.greendao.runtime | |||||
| testImplementation deps.testing.junit | |||||
| // implementation deps.greendao.runtime | |||||
| // testImplementation deps.testing.junit | |||||
| //RxJava | //RxJava | ||||
| implementation deps.reactivex.rxandroid | |||||
| implementation deps.reactivex.rxjava2 | |||||
| // implementation deps.reactivex.rxandroid | |||||
| // implementation deps.reactivex.rxjava2 | |||||
| implementation 'es.voghdev.pdfviewpager:library:1.1.2' | implementation 'es.voghdev.pdfviewpager:library:1.1.2' | ||||
| implementation 'io.github.h07000223:flycoTabLayout:3.0.0' | |||||
| } | } | ||||
| @@ -65,10 +65,10 @@ | |||||
| } | } | ||||
| #bean | #bean | ||||
| -keep class com.yzx.webebook.model.** { *; } | |||||
| -keep class com.yzx.webebook.model.Note { *; } | |||||
| -keep class com.yzx.webebook.model.UploadBean { *; } | |||||
| -keep class com.yzx.webebook.model.UploadContent { *; } | |||||
| -keep class com.yzx.escreen.model.** { *; } | |||||
| -keep class com.yzx.escreen.model.Note { *; } | |||||
| -keep class com.yzx.escreen.model.UploadBean { *; } | |||||
| -keep class com.yzx.escreen.model.UploadContent { *; } | |||||
| -keep class **$Properties {*;} | -keep class **$Properties {*;} | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook | |||||
| package com.yzx.escreen | |||||
| import androidx.test.platform.app.InstrumentationRegistry | import androidx.test.platform.app.InstrumentationRegistry | ||||
| import androidx.test.ext.junit.runners.AndroidJUnit4 | import androidx.test.ext.junit.runners.AndroidJUnit4 | ||||
| @@ -1,7 +1,7 @@ | |||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||||
| xmlns:tools="http://schemas.android.com/tools" | xmlns:tools="http://schemas.android.com/tools" | ||||
| package="com.yzx.webebook"> | |||||
| package="com.yzx.escreen"> | |||||
| <uses-permission android:name="android.permission.INTERNET" /> | <uses-permission android:name="android.permission.INTERNET" /> | ||||
| <uses-permission android:name="android.permission.READ_PHONE_STATE" /> | <uses-permission android:name="android.permission.READ_PHONE_STATE" /> | ||||
| @@ -17,7 +17,7 @@ | |||||
| <uses-permission android:name="android.permission.WAKE_LOCK" /> | <uses-permission android:name="android.permission.WAKE_LOCK" /> | ||||
| <application | <application | ||||
| android:name=".App" | |||||
| android:name="com.yzx.escreen.App" | |||||
| android:allowBackup="true" | android:allowBackup="true" | ||||
| android:icon="@mipmap/ic_launcher" | android:icon="@mipmap/ic_launcher" | ||||
| android:label="@string/app_name" | android:label="@string/app_name" | ||||
| @@ -27,42 +27,32 @@ | |||||
| android:supportsRtl="true" | android:supportsRtl="true" | ||||
| android:theme="@style/AppTheme" | android:theme="@style/AppTheme" | ||||
| android:usesCleartextTraffic="true"> | android:usesCleartextTraffic="true"> | ||||
| <activity android:name=".activity.PDFViewActivity"></activity> | |||||
| <activity android:name=".activity.ReadActivity" /> | |||||
| <activity android:name=".activity.WeexTestActivity" /> | |||||
| <activity android:name="com.yzx.escreen.activity.WeexTestActivity" /> | |||||
| <activity | <activity | ||||
| android:name=".activity.HomeActivity" | |||||
| android:name="com.yzx.escreen.MainActivity" | |||||
| android:configChanges="orientation|keyboard" | android:configChanges="orientation|keyboard" | ||||
| android:launchMode="singleTask" | android:launchMode="singleTask" | ||||
| android:screenOrientation="portrait"> | |||||
| android:screenOrientation="landscape"> | |||||
| <intent-filter> | <intent-filter> | ||||
| <action android:name="android.intent.action.MAIN" /> | <action android:name="android.intent.action.MAIN" /> | ||||
| <category android:name="android.intent.category.HOME" /> | |||||
| <category android:name="android.intent.category.DEFAULT" /> | |||||
| <!-- <category android:name="android.intent.category.HOME" />--> | |||||
| <!-- <category android:name="android.intent.category.DEFAULT" />--> | |||||
| <category android:name="android.intent.category.LAUNCHER" /> | <category android:name="android.intent.category.LAUNCHER" /> | ||||
| </intent-filter> | </intent-filter> | ||||
| </activity> | </activity> | ||||
| <activity | <activity | ||||
| android:name=".activity.NoteActivity" | |||||
| android:configChanges="orientation|keyboard" | |||||
| android:screenOrientation="portrait" /> | |||||
| <activity | |||||
| android:name=".activity.WebActivity" | |||||
| android:configChanges="orientation|keyboard" | |||||
| android:screenOrientation="portrait" /> | |||||
| <activity | |||||
| android:name=".MainActivity" | |||||
| android:configChanges="orientation|keyboard" | |||||
| android:launchMode="singleTask" | |||||
| android:screenOrientation="portrait" /> | |||||
| <activity | |||||
| android:name=".activity.BookActivity" | |||||
| android:name="com.yzx.escreen.activity.WebActivity" | |||||
| android:configChanges="orientation|keyboard" | android:configChanges="orientation|keyboard" | ||||
| android:screenOrientation="portrait" /> | android:screenOrientation="portrait" /> | ||||
| <!-- <activity--> | |||||
| <!-- android:name="com.yzx.escreen.MainActivity"--> | |||||
| <!-- android:configChanges="orientation|keyboard"--> | |||||
| <!-- android:launchMode="singleTask"--> | |||||
| <!-- android:screenOrientation="portrait" />--> | |||||
| <provider | <provider | ||||
| android:name=".utils.YzxFileProvider" | |||||
| android:name="com.yzx.escreen.utils.YzxFileProvider" | |||||
| android:authorities="${applicationId}.fileProvider" | android:authorities="${applicationId}.fileProvider" | ||||
| android:exported="false" | android:exported="false" | ||||
| android:grantUriPermissions="true" | android:grantUriPermissions="true" | ||||
| @@ -0,0 +1,48 @@ | |||||
| package com.yzx.escreen | |||||
| import android.app.Application | |||||
| import com.blankj.utilcode.util.Utils | |||||
| import com.lzy.okgo.OkGo | |||||
| import com.lzy.okgo.model.HttpHeaders | |||||
| import com.umeng.analytics.MobclickAgent | |||||
| import com.umeng.commonsdk.UMConfigure | |||||
| import com.yzx.escreen.model.User | |||||
| class App : Application() { | |||||
| companion object { | |||||
| var app: App? = null | |||||
| fun getContext(): App { | |||||
| return app ?: App() | |||||
| } | |||||
| } | |||||
| override fun onCreate() { | |||||
| super.onCreate() | |||||
| app = this | |||||
| val headers = HttpHeaders() | |||||
| val user = User.getUser() | |||||
| headers.put("phone",user.phone) | |||||
| headers.put("token",user.token) | |||||
| OkGo.getInstance() | |||||
| .addCommonHeaders(headers) | |||||
| .init(this) | |||||
| Utils.init(this) | |||||
| UMConfigure.init( | |||||
| this, | |||||
| "60334d01425ec25f10fbd5b4", | |||||
| "ebook", | |||||
| UMConfigure.DEVICE_TYPE_PHONE, | |||||
| "" | |||||
| ) | |||||
| MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO) | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,45 @@ | |||||
| package com.yzx.escreen | |||||
| import android.annotation.SuppressLint | |||||
| import android.content.Intent | |||||
| import com.flyco.tablayout.listener.CustomTabEntity | |||||
| import com.yzx.escreen.activity.base.BaseActivity | |||||
| import com.yzx.escreen.model.TabEntity | |||||
| import com.yzx.escreen.presenter.base.BasePresenter | |||||
| import kotlinx.android.synthetic.main.activity_main.* | |||||
| /** | |||||
| * Yun.Lei | |||||
| * 2020年5月6日14:49:10 | |||||
| */ | |||||
| class MainActivity : BaseActivity<BasePresenter<*>>() { | |||||
| override val inflateId: Int | |||||
| get() = R.layout.activity_main | |||||
| override fun initView() { | |||||
| val tabData = arrayListOf<CustomTabEntity>() | |||||
| tabData.add(TabEntity("首页",R.mipmap.home_select,R.mipmap.home_unselect)) | |||||
| tabData.add(TabEntity("我的",R.mipmap.my_select,R.mipmap.my_unselect)) | |||||
| tabLayout.setTabData(tabData) | |||||
| } | |||||
| override fun initData() { | |||||
| } | |||||
| override fun initPresenter(): BasePresenter<*>? { | |||||
| return null | |||||
| } | |||||
| @SuppressLint("SetTextI18n") | |||||
| override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { | |||||
| super.onActivityResult(requestCode, resultCode, data) | |||||
| } | |||||
| } | |||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.activity | |||||
| package com.yzx.escreen.activity | |||||
| import android.Manifest | import android.Manifest | ||||
| import android.annotation.SuppressLint | import android.annotation.SuppressLint | ||||
| @@ -6,12 +6,9 @@ import android.app.AlertDialog | |||||
| import android.app.Dialog | import android.app.Dialog | ||||
| import android.content.Context | import android.content.Context | ||||
| import android.content.DialogInterface | import android.content.DialogInterface | ||||
| import android.content.IntentFilter | |||||
| import android.net.ConnectivityManager | |||||
| import android.util.Log | import android.util.Log | ||||
| import android.view.View | import android.view.View | ||||
| import android.widget.TextView | import android.widget.TextView | ||||
| import androidx.core.app.ActivityCompat | |||||
| import androidx.core.widget.ContentLoadingProgressBar | import androidx.core.widget.ContentLoadingProgressBar | ||||
| import androidx.recyclerview.widget.GridLayoutManager | import androidx.recyclerview.widget.GridLayoutManager | ||||
| import com.allenliu.versionchecklib.v2.AllenVersionChecker | import com.allenliu.versionchecklib.v2.AllenVersionChecker | ||||
| @@ -24,17 +21,17 @@ import com.google.gson.reflect.TypeToken | |||||
| import com.lzy.okgo.OkGo | import com.lzy.okgo.OkGo | ||||
| import com.lzy.okgo.callback.StringCallback | import com.lzy.okgo.callback.StringCallback | ||||
| import com.lzy.okgo.model.Response | import com.lzy.okgo.model.Response | ||||
| import com.yzx.webebook.MainActivity | |||||
| import com.yzx.webebook.R | |||||
| import com.yzx.webebook.activity.base.BaseActivity | |||||
| import com.yzx.webebook.adapter.HomeAdapter | |||||
| import com.yzx.webebook.config.Config | |||||
| import com.yzx.webebook.model.BaseBean | |||||
| import com.yzx.webebook.model.HomeItem | |||||
| import com.yzx.webebook.model.User | |||||
| import com.yzx.webebook.model.Version | |||||
| import com.yzx.webebook.presenter.base.BasePresenter | |||||
| import com.yzx.webebook.widget.BaseDialog | |||||
| import com.yzx.escreen.MainActivity | |||||
| import com.yzx.escreen.R | |||||
| import com.yzx.escreen.activity.base.BaseActivity | |||||
| import com.yzx.escreen.adapter.HomeAdapter | |||||
| import com.yzx.escreen.config.Config | |||||
| import com.yzx.escreen.model.BaseBean | |||||
| import com.yzx.escreen.model.HomeItem | |||||
| import com.yzx.escreen.model.User | |||||
| import com.yzx.escreen.model.Version | |||||
| import com.yzx.escreen.presenter.base.BasePresenter | |||||
| import com.yzx.escreen.widget.BaseDialog | |||||
| import kotlinx.android.synthetic.main.activity_home.* | import kotlinx.android.synthetic.main.activity_home.* | ||||
| import org.jetbrains.anko.find | import org.jetbrains.anko.find | ||||
| import org.jetbrains.anko.startActivity | import org.jetbrains.anko.startActivity | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.activity | |||||
| package com.yzx.escreen.activity | |||||
| import android.annotation.SuppressLint | import android.annotation.SuppressLint | ||||
| import android.app.Activity | import android.app.Activity | ||||
| @@ -22,29 +22,24 @@ import com.allenliu.versionchecklib.v2.builder.UIData | |||||
| import com.allenliu.versionchecklib.v2.callback.CustomDownloadingDialogListener | import com.allenliu.versionchecklib.v2.callback.CustomDownloadingDialogListener | ||||
| import com.blankj.utilcode.util.AppUtils | import com.blankj.utilcode.util.AppUtils | ||||
| import com.blankj.utilcode.util.SPUtils | import com.blankj.utilcode.util.SPUtils | ||||
| import com.blankj.utilcode.util.ToastUtils | |||||
| import com.google.gson.Gson | import com.google.gson.Gson | ||||
| import com.google.gson.reflect.TypeToken | import com.google.gson.reflect.TypeToken | ||||
| import com.lzy.okgo.OkGo | import com.lzy.okgo.OkGo | ||||
| import com.lzy.okgo.callback.StringCallback | import com.lzy.okgo.callback.StringCallback | ||||
| import com.lzy.okgo.model.Response | import com.lzy.okgo.model.Response | ||||
| import com.yzx.webebook.R | |||||
| import com.yzx.webebook.activity.base.BaseActivity | |||||
| import com.yzx.webebook.config.Config | |||||
| import com.yzx.webebook.model.BaseBean | |||||
| import com.yzx.webebook.model.User | |||||
| import com.yzx.webebook.model.Version | |||||
| import com.yzx.webebook.model.local.BookRepository | |||||
| import com.yzx.webebook.presenter.ReadPresenter | |||||
| import com.yzx.webebook.presenter.ReadView | |||||
| import com.yzx.webebook.presenter.base.BasePresenter | |||||
| import com.yzx.webebook.widget.BaseDialog | |||||
| import com.yzx.escreen.R | |||||
| import com.yzx.escreen.activity.base.BaseActivity | |||||
| import com.yzx.escreen.config.Config | |||||
| import com.yzx.escreen.model.BaseBean | |||||
| import com.yzx.escreen.model.User | |||||
| import com.yzx.escreen.model.Version | |||||
| import com.yzx.escreen.presenter.base.BasePresenter | |||||
| import com.yzx.escreen.widget.BaseDialog | |||||
| import kotlinx.android.synthetic.main.activity_web.* | import kotlinx.android.synthetic.main.activity_web.* | ||||
| import org.jetbrains.anko.ctx | import org.jetbrains.anko.ctx | ||||
| import org.jetbrains.anko.find | import org.jetbrains.anko.find | ||||
| import org.jetbrains.anko.startActivity | import org.jetbrains.anko.startActivity | ||||
| import org.jetbrains.anko.toast | import org.jetbrains.anko.toast | ||||
| import org.json.JSONObject | |||||
| import java.util.* | import java.util.* | ||||
| /** | /** | ||||
| @@ -346,22 +341,7 @@ class WebActivity : BaseActivity<BasePresenter<*>>() { | |||||
| @SuppressLint("SetTextI18n") | @SuppressLint("SetTextI18n") | ||||
| override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { | ||||
| super.onActivityResult(requestCode, resultCode, data) | super.onActivityResult(requestCode, resultCode, data) | ||||
| if (requestCode == BookActivity.REQ_CODE && resultCode == Activity.RESULT_OK) { | |||||
| val mKey = data?.getStringExtra("key") ?: "" | |||||
| val mIdentity = data?.getStringExtra("identity") ?: "" | |||||
| val obj = JSONObject() | |||||
| obj.put("key", mKey) | |||||
| obj.put("identity", mIdentity) | |||||
| obj.put("name", data?.getStringExtra("name") ?: "") | |||||
| obj.put("index", data?.getIntExtra("index", 0)) | |||||
| obj.put("type", data?.getIntExtra("type", 1)) | |||||
| evaluateJavascript("onImageUploadSuccess", obj.toString()) | |||||
| } | |||||
| if (requestCode == NoteActivity.REQ_CODE && resultCode == Activity.RESULT_OK) { | |||||
| val json = data?.getStringExtra("note_info") ?: "" | |||||
| evaluateJavascript("onImageUploadSuccess", json) | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -387,7 +367,7 @@ class YzxJavascriptInterface(var ctx: Activity) { | |||||
| index: Int, | index: Int, | ||||
| type: Int | type: Int | ||||
| ) { | ) { | ||||
| BookActivity.active(ctx, title, key, identity, name, index, type) | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -402,7 +382,7 @@ class YzxJavascriptInterface(var ctx: Activity) { | |||||
| note_info: String, | note_info: String, | ||||
| can_add_page: Int = 1 | can_add_page: Int = 1 | ||||
| ) { | ) { | ||||
| NoteActivity.active(ctx, title, note_info, can_add_page) | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -415,7 +395,7 @@ class YzxJavascriptInterface(var ctx: Activity) { | |||||
| title: String, | title: String, | ||||
| note_info: String | note_info: String | ||||
| ) { | ) { | ||||
| NoteActivity.active(ctx, title, note_info, 1) | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -479,68 +459,12 @@ class YzxJavascriptInterface(var ctx: Activity) { | |||||
| @JavascriptInterface | @JavascriptInterface | ||||
| fun readPage(bookTaskId: String) { | fun readPage(bookTaskId: String) { | ||||
| val presenter = ReadPresenter(object : ReadView { | |||||
| override fun finishChapter() { | |||||
| } | |||||
| override fun onProgressSuccess(progress: Float) { | |||||
| } | |||||
| override fun errorChapter() { | |||||
| } | |||||
| override fun showCategory(localId: String?) { | |||||
| val collBook = BookRepository.getInstance().getCollBook(localId) | |||||
| if (collBook.cover.endsWith(".txt")) { | |||||
| ctx.startActivity<ReadActivity>("book_id" to localId) | |||||
| } else { | |||||
| ToastUtils.showLong("暂不支持该格式预览!") | |||||
| } | |||||
| } | |||||
| }) | |||||
| presenter.loadCategory(bookTaskId) | |||||
| } | } | ||||
| @JavascriptInterface | @JavascriptInterface | ||||
| fun readPage(bookTaskId: String, readTaskId: String) { | fun readPage(bookTaskId: String, readTaskId: String) { | ||||
| val presenter = ReadPresenter(object : ReadView { | |||||
| override fun finishChapter() { | |||||
| } | |||||
| override fun errorChapter() { | |||||
| } | |||||
| override fun showCategory(localId: String?) { | |||||
| val collBook = BookRepository.getInstance().getCollBook(localId) | |||||
| if (collBook.cover.endsWith(".txt")) { | |||||
| ctx.startActivity<ReadActivity>( | |||||
| "book_id" to localId, | |||||
| "read_task_id" to readTaskId, | |||||
| "real_book_id" to bookTaskId | |||||
| ) | |||||
| } else if (collBook.cover.endsWith(".pdf")) { | |||||
| ctx.startActivity<PDFViewActivity>( | |||||
| "book_id" to localId, | |||||
| "read_task_id" to readTaskId, | |||||
| "real_book_id" to bookTaskId | |||||
| ) | |||||
| } else { | |||||
| ToastUtils.showLong("暂不支持该格式预览!") | |||||
| } | |||||
| } | |||||
| override fun onProgressSuccess(progress: Float) { | |||||
| } | |||||
| }) | |||||
| presenter.loadCategory(bookTaskId) | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,12 +1,10 @@ | |||||
| package com.yzx.webebook.activity.base | |||||
| package com.yzx.escreen.activity.base | |||||
| import android.os.Bundle | import android.os.Bundle | ||||
| import androidx.appcompat.app.AppCompatActivity | import androidx.appcompat.app.AppCompatActivity | ||||
| import com.gyf.immersionbar.ktx.immersionBar | import com.gyf.immersionbar.ktx.immersionBar | ||||
| import com.yzx.webebook.R | |||||
| import com.yzx.webebook.presenter.base.BasePresenter | |||||
| import io.reactivex.disposables.CompositeDisposable | |||||
| import io.reactivex.disposables.Disposable | |||||
| import com.yzx.escreen.R | |||||
| import com.yzx.escreen.presenter.base.BasePresenter | |||||
| /** | /** | ||||
| * 类名:BaseActivity | * 类名:BaseActivity | ||||
| @@ -40,7 +38,6 @@ abstract class BaseActivity<out P : BasePresenter<*>> : AppCompatActivity() { | |||||
| abstract fun initPresenter(): P? | abstract fun initPresenter(): P? | ||||
| protected var mDisposable: CompositeDisposable? = null | |||||
| override fun onCreate(savedInstanceState: Bundle?) { | override fun onCreate(savedInstanceState: Bundle?) { | ||||
| super.onCreate(savedInstanceState) | super.onCreate(savedInstanceState) | ||||
| @@ -61,12 +58,7 @@ abstract class BaseActivity<out P : BasePresenter<*>> : AppCompatActivity() { | |||||
| } | } | ||||
| protected open fun addDisposable(d: Disposable?) { | |||||
| if (mDisposable == null) { | |||||
| mDisposable = CompositeDisposable() | |||||
| } | |||||
| mDisposable!!.add(d!!) | |||||
| } | |||||
| override fun onBackPressed() { | override fun onBackPressed() { | ||||
| @@ -75,9 +67,7 @@ abstract class BaseActivity<out P : BasePresenter<*>> : AppCompatActivity() { | |||||
| override fun onDestroy() { | override fun onDestroy() { | ||||
| super.onDestroy() | super.onDestroy() | ||||
| if (mDisposable != null) { | |||||
| mDisposable!!.dispose() | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,9 +1,9 @@ | |||||
| package com.yzx.webebook.adapter | |||||
| package com.yzx.escreen.adapter | |||||
| import com.chad.library.adapter.base.BaseQuickAdapter | import com.chad.library.adapter.base.BaseQuickAdapter | ||||
| import com.chad.library.adapter.base.viewholder.BaseViewHolder | import com.chad.library.adapter.base.viewholder.BaseViewHolder | ||||
| import com.yzx.webebook.R | |||||
| import com.yzx.webebook.model.HomeItem | |||||
| import com.yzx.escreen.R | |||||
| import com.yzx.escreen.model.HomeItem | |||||
| import kotlinx.android.synthetic.main.item_home.view.* | import kotlinx.android.synthetic.main.item_home.view.* | ||||
| class HomeAdapter(list: MutableList<HomeItem>) : BaseQuickAdapter<HomeItem, BaseViewHolder>(R.layout.item_home,list) { | class HomeAdapter(list: MutableList<HomeItem>) : BaseQuickAdapter<HomeItem, BaseViewHolder>(R.layout.item_home,list) { | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.adapter.base; | |||||
| package com.yzx.escreen.adapter.base; | |||||
| import android.os.Handler; | import android.os.Handler; | ||||
| import android.view.View; | import android.view.View; | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.adapter.base; | |||||
| package com.yzx.escreen.adapter.base; | |||||
| import android.view.View; | import android.view.View; | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.adapter.base; | |||||
| package com.yzx.escreen.adapter.base; | |||||
| import android.view.View; | import android.view.View; | ||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.adapter.base; | |||||
| package com.yzx.escreen.adapter.base; | |||||
| import android.view.View; | import android.view.View; | ||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.adapter.base; | |||||
| package com.yzx.escreen.adapter.base; | |||||
| import android.view.View; | import android.view.View; | ||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.adapter.base; | |||||
| package com.yzx.escreen.adapter.base; | |||||
| import android.content.Context; | import android.content.Context; | ||||
| import android.view.LayoutInflater; | import android.view.LayoutInflater; | ||||
| @@ -1,6 +1,6 @@ | |||||
| package com.yzx.webebook.config | |||||
| package com.yzx.escreen.config | |||||
| import com.yzx.webebook.BuildConfig | |||||
| import com.yzx.escreen.BuildConfig | |||||
| object Config { | object Config { | ||||
| var BASE_URL = BuildConfig.BASE_URL | var BASE_URL = BuildConfig.BASE_URL | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.model | |||||
| package com.yzx.escreen.model | |||||
| data class BaseBean<T>( | data class BaseBean<T>( | ||||
| var code: Int, | var code: Int, | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.model | |||||
| package com.yzx.escreen.model | |||||
| class Book { | class Book { | ||||
| var book_name:String = "" | var book_name:String = "" | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.model | |||||
| package com.yzx.escreen.model | |||||
| class HomeItem ( | class HomeItem ( | ||||
| var title:String, | var title:String, | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.model | |||||
| package com.yzx.escreen.model | |||||
| class Note { | class Note { | ||||
| var key:String = "" | var key:String = "" | ||||
| @@ -0,0 +1,21 @@ | |||||
| package com.yzx.escreen.model | |||||
| import com.flyco.tablayout.listener.CustomTabEntity | |||||
| data class TabEntity(var title: String, | |||||
| var selectedIcon: Int, | |||||
| var unSelectedIcon: Int) : | |||||
| CustomTabEntity { | |||||
| override fun getTabTitle(): String { | |||||
| return title | |||||
| } | |||||
| override fun getTabSelectedIcon(): Int { | |||||
| return selectedIcon | |||||
| } | |||||
| override fun getTabUnselectedIcon(): Int { | |||||
| return unSelectedIcon | |||||
| } | |||||
| } | |||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.model | |||||
| package com.yzx.escreen.model | |||||
| class UploadBean { | class UploadBean { | ||||
| var code:Int = 0 | var code:Int = 0 | ||||
| @@ -1,6 +1,5 @@ | |||||
| package com.yzx.webebook.model | |||||
| package com.yzx.escreen.model | |||||
| import android.content.Context | |||||
| import com.blankj.utilcode.util.SPUtils | import com.blankj.utilcode.util.SPUtils | ||||
| class User( | class User( | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.model | |||||
| package com.yzx.escreen.model | |||||
| class Version { | class Version { | ||||
| var version: String = "" | var version: String = "" | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.presenter.base | |||||
| package com.yzx.escreen.presenter.base | |||||
| /** | /** | ||||
| * 类名:BasePresenter | * 类名:BasePresenter | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.presenter.base | |||||
| package com.yzx.escreen.presenter.base | |||||
| /** | /** | ||||
| * 类名:IView | * 类名:IView | ||||
| @@ -1,10 +1,10 @@ | |||||
| package com.yzx.webebook.presenter.base | |||||
| package com.yzx.escreen.presenter.base | |||||
| import com.google.gson.Gson | import com.google.gson.Gson | ||||
| import com.google.gson.reflect.TypeToken | import com.google.gson.reflect.TypeToken | ||||
| import com.lzy.okgo.callback.AbsCallback | import com.lzy.okgo.callback.AbsCallback | ||||
| import com.lzy.okgo.convert.StringConvert | import com.lzy.okgo.convert.StringConvert | ||||
| import com.yzx.webebook.model.BaseBean | |||||
| import com.yzx.escreen.model.BaseBean | |||||
| import okhttp3.Response | import okhttp3.Response | ||||
| abstract class JsonCallBack<T> : AbsCallback<BaseBean<T>>() { | abstract class JsonCallBack<T> : AbsCallback<BaseBean<T>>() { | ||||
| @@ -0,0 +1,2 @@ | |||||
| package com.yzx.escreen.utils | |||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.utils | |||||
| package com.yzx.escreen.utils | |||||
| import androidx.core.content.FileProvider | import androidx.core.content.FileProvider | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.widget | |||||
| package com.yzx.escreen.widget | |||||
| import android.app.Dialog | import android.app.Dialog | ||||
| import android.content.Context | import android.content.Context | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.yzx.webebook.widget | |||||
| package com.yzx.escreen.widget | |||||
| import android.content.Context | import android.content.Context | ||||
| import android.view.MotionEvent | import android.view.MotionEvent | ||||
| @@ -1,73 +0,0 @@ | |||||
| package com.yzx.webebook | |||||
| import android.app.Application | |||||
| import android.content.Context | |||||
| import android.util.Log | |||||
| import com.blankj.utilcode.util.Utils | |||||
| import com.lzy.okgo.OkGo | |||||
| import com.lzy.okgo.model.HttpHeaders | |||||
| import com.umeng.analytics.MobclickAgent | |||||
| import com.umeng.commonsdk.UMConfigure | |||||
| import com.yzx.webebook.adapter.ImageAdapter | |||||
| import com.yzx.webebook.model.User | |||||
| import com.yzx.webebook.modules.ActivityWXModule | |||||
| import org.apache.weex.InitConfig | |||||
| import org.apache.weex.WXEnvironment | |||||
| import org.apache.weex.WXSDKEngine | |||||
| import org.apache.weex.adapter.DefaultWXHttpAdapter | |||||
| import org.apache.weex.bridge.WXBridgeManager | |||||
| class App : Application() { | |||||
| companion object { | |||||
| var app: App? = null | |||||
| fun getContext(): App { | |||||
| return app ?: App() | |||||
| } | |||||
| } | |||||
| override fun onCreate() { | |||||
| super.onCreate() | |||||
| app = this | |||||
| val config = InitConfig.Builder() //图片库接口 | |||||
| .setImgAdapter(ImageAdapter()) //网络库接口 | |||||
| .setHttpAdapter(DefaultWXHttpAdapter()) | |||||
| .build() | |||||
| WXSDKEngine.initialize(this, config) | |||||
| WXBridgeManager.updateGlobalConfig("wson_on") | |||||
| WXEnvironment.setOpenDebugLog(true) | |||||
| WXEnvironment.setApkDebugable(true) | |||||
| WXSDKEngine.addCustomOptions("appName", "WXSample") | |||||
| WXSDKEngine.addCustomOptions("appGroup", "WXApp") | |||||
| val registerSuccess = WXSDKEngine.registerModule("navevent", ActivityWXModule::class.java) | |||||
| Log.i("welog", "WXSDKEngine.isInitializedApplication: " + WXSDKEngine.isInitialized()) | |||||
| Log.i("welog", "WXSDKEngine.registerModule: $registerSuccess") | |||||
| val headers = HttpHeaders() | |||||
| val user = User.getUser() | |||||
| headers.put("phone",user.phone) | |||||
| headers.put("token",user.token) | |||||
| OkGo.getInstance() | |||||
| .addCommonHeaders(headers) | |||||
| .init(this) | |||||
| Utils.init(this) | |||||
| UMConfigure.init( | |||||
| this, | |||||
| "60334d01425ec25f10fbd5b4", | |||||
| "ebook", | |||||
| UMConfigure.DEVICE_TYPE_PHONE, | |||||
| "" | |||||
| ) | |||||
| MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO) | |||||
| } | |||||
| } | |||||
| @@ -1,211 +0,0 @@ | |||||
| package com.yzx.webebook | |||||
| import android.annotation.SuppressLint | |||||
| import android.app.Activity | |||||
| import android.content.Intent | |||||
| import android.text.TextUtils | |||||
| import android.util.Log | |||||
| import com.blankj.utilcode.util.StringUtils | |||||
| import com.bumptech.glide.Glide | |||||
| import com.yzx.webebook.activity.* | |||||
| import com.yzx.webebook.activity.base.BaseActivity | |||||
| import com.yzx.webebook.config.Config | |||||
| import com.yzx.webebook.model.User | |||||
| import com.yzx.webebook.model.bean.CollBookBean | |||||
| import com.yzx.webebook.model.local.BookRepository | |||||
| import com.yzx.webebook.presenter.ReadPresenter | |||||
| import com.yzx.webebook.presenter.ReadView | |||||
| import kotlinx.android.synthetic.main.activity_main.* | |||||
| import org.jetbrains.anko.startActivity | |||||
| import org.jetbrains.anko.toast | |||||
| /** | |||||
| * Yun.Lei | |||||
| * 2020年5月6日14:49:10 | |||||
| */ | |||||
| class MainActivity : BaseActivity<ReadPresenter>(),ReadView { | |||||
| override val inflateId: Int | |||||
| get() = R.layout.activity_main | |||||
| override fun initView() { | |||||
| btn1.setOnClickListener { | |||||
| Config.APP_NAME = "家校互通" | |||||
| Config.BASE_URL = "https://oa.qbjjyyun.net/api" | |||||
| Config.M_URL = "https://m.qbjjyyun.net" | |||||
| User.clearUserInfo() | |||||
| startActivity<HomeActivity>() | |||||
| } | |||||
| btn2.setOnClickListener { | |||||
| Config.APP_NAME = "家校互通(LIVE)" | |||||
| Config.BASE_URL = "https://oa.live.educlouddata.com/api" | |||||
| Config.M_URL = "https://m.live.educlouddata.com" | |||||
| User.clearUserInfo() | |||||
| startActivity<HomeActivity>() | |||||
| } | |||||
| btn6.setOnClickListener { | |||||
| Config.APP_NAME = "家校互通(测试)" | |||||
| Config.BASE_URL = "http://192.168.69.99:9009" | |||||
| Config.M_URL = "http://192.168.69.99:8098" | |||||
| if (BuildConfig.BUILD_TYPE != "debug") { | |||||
| User.clearUserInfo() | |||||
| } | |||||
| startActivity<HomeActivity>() | |||||
| } | |||||
| btn3.setOnClickListener { | |||||
| val mBaseUrl = mBaseUrlTv.text.toString() | |||||
| if(StringUtils.isTrimEmpty(mBaseUrl)){ | |||||
| toast("请输入BASE_URL") | |||||
| return@setOnClickListener | |||||
| } | |||||
| val mUrl = mUrlTv.text.toString() | |||||
| if(StringUtils.isTrimEmpty(mUrl)){ | |||||
| toast("请输入M_URL") | |||||
| return@setOnClickListener | |||||
| } | |||||
| Config.APP_NAME = "家校互通(本地)" | |||||
| Config.BASE_URL = mBaseUrl | |||||
| Config.M_URL = mUrl | |||||
| if (BuildConfig.BUILD_TYPE != "debug") { | |||||
| User.clearUserInfo() | |||||
| } | |||||
| startActivity<HomeActivity>() | |||||
| } | |||||
| btn4.setOnClickListener { | |||||
| BookActivity.active( | |||||
| this, | |||||
| "教育云空间", | |||||
| "f04be754f6cb3f6168f582403a514c39", | |||||
| "filec", | |||||
| "", | |||||
| 1, | |||||
| 1 | |||||
| ) | |||||
| } | |||||
| btn5.setOnClickListener { | |||||
| // BookActivity.active(this,"教育云空间(无图)","","","",2,2) | |||||
| val json ="" | |||||
| NoteActivity.active(this, "测试笔记写字", json,1) | |||||
| } | |||||
| btn7.setOnClickListener { | |||||
| startActivity<PDFViewActivity>() | |||||
| // mPresenter?.loadCategory("17") | |||||
| } | |||||
| /*OkGo.post<String>("https://fileupload.oa.qbjjyyun.net/edufile/fileUpload") | |||||
| .tag(this) | |||||
| .params("token","0fc58a8df03c46d3f85b1047c4693cf6") | |||||
| .params("user","97244") | |||||
| .params("file",file) | |||||
| .execute(object : StringCallback(){ | |||||
| override fun onError(response: Response<String>?) { | |||||
| super.onError(response) | |||||
| Log.d("onError",response?.body()) | |||||
| } | |||||
| override fun onSuccess(response: Response<String>?) { | |||||
| val json = response?.body() | |||||
| Log.d("onSuccess",response?.body()) | |||||
| val jsonObject = JSONObject(json) | |||||
| val content = jsonObject.optString("content") | |||||
| Log.d("onSuccess,content",content) | |||||
| val contentObject = JSONObject(content) | |||||
| val key = contentObject.optString("key") | |||||
| val identity = contentObject.optString("identity") | |||||
| Log.d("onSuccess,identity",identity) | |||||
| Log.d("onSuccess,key",key) | |||||
| } | |||||
| })*/ | |||||
| // val apps = AppUtils.getAppInfo("com.tencent.weread.eink") | |||||
| // appInfos.text = apps.toString(); | |||||
| appInfos.setOnClickListener { | |||||
| val intent = packageManager.getLaunchIntentForPackage("com.tencent.weread.eink") | |||||
| intent?.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | |||||
| startActivity(intent) | |||||
| Log.d("AppUtils", "initView: ${intent.toString()}") | |||||
| } | |||||
| btn8.setOnClickListener { | |||||
| startActivity<WeexTestActivity>("url" to "weex/index.js","params" to "我是android传递的消息") | |||||
| } | |||||
| btn9.setOnClickListener { | |||||
| val intent = packageManager.getLaunchIntentForPackage("com.example.weexdemo") | |||||
| intent?.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | |||||
| startActivity(intent) | |||||
| Log.d("AppUtils", "initView: ${intent.toString()}") | |||||
| } | |||||
| } | |||||
| override fun initData() { | |||||
| saveDb() | |||||
| } | |||||
| fun saveDb(){ | |||||
| val path = "/storage/emulated/0/xxjs.pdf"; | |||||
| val collBook = CollBookBean() | |||||
| collBook._id = "xxjs" | |||||
| collBook.title = "三国演义sgyy" | |||||
| collBook.author = "yzx" | |||||
| collBook.shortIntro = "" | |||||
| collBook.cover = path | |||||
| collBook.lastChapter = "开始阅读" | |||||
| collBook.updated = "2021年5月7日18:20:25" | |||||
| collBook.lastRead = "2021年5月7日18:20:34" | |||||
| collBook.setIsLocal(true) | |||||
| BookRepository.getInstance() | |||||
| .saveCollBooks(mutableListOf(collBook)) | |||||
| } | |||||
| override fun initPresenter(): ReadPresenter = ReadPresenter(this) | |||||
| @SuppressLint("SetTextI18n") | |||||
| override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { | |||||
| super.onActivityResult(requestCode, resultCode, data) | |||||
| if (requestCode == BookActivity.REQ_CODE && resultCode == Activity.RESULT_OK) { | |||||
| val mKey = data?.getStringExtra("key") | |||||
| val mIdentity = data?.getStringExtra("identity") | |||||
| if(!TextUtils.isEmpty(mKey)&&!TextUtils.isEmpty(mIdentity)){ | |||||
| val url = "https://$mIdentity.oa.qbjjyyun.net/edufile/imageView?uniqueKey=$mKey" | |||||
| Glide.with(this) | |||||
| .load(url) | |||||
| .into(testImageView) | |||||
| } | |||||
| val json = data?.getStringExtra("note_info")?:"" | |||||
| backInfo.text = json | |||||
| } | |||||
| if (requestCode == NoteActivity.REQ_CODE && resultCode == Activity.RESULT_OK) { | |||||
| val json = data?.getStringExtra("note_info")?:"" | |||||
| backInfo.text = json | |||||
| } | |||||
| } | |||||
| override fun finishChapter() { | |||||
| } | |||||
| override fun errorChapter() { | |||||
| } | |||||
| override fun showCategory(localId: String?) { | |||||
| // startActivity<ReadActivity>("book_id" to "xxjs") | |||||
| } | |||||
| override fun onProgressSuccess(progress: Float) { | |||||
| } | |||||
| } | |||||
| @@ -1,687 +0,0 @@ | |||||
| package com.yzx.webebook.activity | |||||
| import android.Manifest | |||||
| import android.annotation.SuppressLint | |||||
| import android.app.Activity | |||||
| import android.content.BroadcastReceiver | |||||
| import android.content.Context | |||||
| import android.content.Intent | |||||
| import android.content.IntentFilter | |||||
| import android.content.pm.ActivityInfo | |||||
| import android.content.pm.PackageManager | |||||
| import android.graphics.Bitmap | |||||
| import android.graphics.Rect | |||||
| import android.graphics.drawable.Drawable | |||||
| import android.os.Handler | |||||
| import android.os.Message | |||||
| import android.text.TextUtils | |||||
| import android.util.Log | |||||
| import android.view.KeyEvent | |||||
| import android.view.View | |||||
| import android.widget.Toast | |||||
| import com.blankj.utilcode.util.FileUtils | |||||
| import com.blankj.utilcode.util.GsonUtils | |||||
| import com.blankj.utilcode.util.ImageUtils | |||||
| import com.bumptech.glide.Glide | |||||
| import com.bumptech.glide.load.engine.DiskCacheStrategy | |||||
| import com.bumptech.glide.request.target.CustomTarget | |||||
| import com.bumptech.glide.request.target.Target | |||||
| import com.bumptech.glide.request.transition.Transition | |||||
| import com.google.gson.Gson | |||||
| import com.lzy.okgo.OkGo | |||||
| import com.lzy.okgo.callback.StringCallback | |||||
| import com.lzy.okgo.model.Response | |||||
| import com.wetao.note.NotePageInfo | |||||
| import com.wetao.note.OnInitedListener | |||||
| import com.wetao.note.WeNoteView | |||||
| import com.wetao.note.WePoint | |||||
| import com.yzx.webebook.R | |||||
| import com.yzx.webebook.activity.base.BaseActivity | |||||
| import com.yzx.webebook.model.Note | |||||
| import com.yzx.webebook.presenter.base.BasePresenter | |||||
| import kotlinx.android.synthetic.main.activity_note.* | |||||
| import org.jetbrains.anko.startActivityForResult | |||||
| import org.jetbrains.anko.toast | |||||
| import org.json.JSONArray | |||||
| import org.json.JSONObject | |||||
| import java.io.File | |||||
| import java.util.* | |||||
| import kotlin.system.exitProcess | |||||
| /** | |||||
| * 笔记页面 | |||||
| */ | |||||
| class NoteActivity : BaseActivity<BasePresenter<*>>() { | |||||
| private val mBGDrawableList = intArrayOf( | |||||
| R.drawable.background0, | |||||
| R.drawable.background1, | |||||
| R.drawable.background2, | |||||
| R.drawable.background3, | |||||
| R.drawable.background4, | |||||
| R.drawable.background5, | |||||
| R.drawable.background6, | |||||
| R.drawable.background7, | |||||
| R.drawable.background8, | |||||
| R.drawable.background9, | |||||
| R.drawable.background10 | |||||
| ) | |||||
| private var mBgId = 0 | |||||
| private var mWePointList = mutableListOf<WePoint>() | |||||
| private var mHandler = Handler() | |||||
| private var mScreenH = 0 | |||||
| private var mScreenW = 0 | |||||
| private val MSG_SAVE_END = 2001 | |||||
| private var mNotePageInfo: NotePageInfo? = null | |||||
| private var notList = mutableListOf<Note>() | |||||
| private var currKey = "" | |||||
| private var currIndex = 0 | |||||
| val TAG = "NoteActivity" | |||||
| companion object { | |||||
| const val NOTE_FOLDER_DIR = "/mnt/sdcard/ebook/" | |||||
| const val REQ_CODE = 0x98 | |||||
| fun active(act: Activity, title: String, noteInfo: String, can_add_page: Int = 1) { | |||||
| act.startActivityForResult<NoteActivity>( | |||||
| REQ_CODE, | |||||
| "note_info" to noteInfo, | |||||
| "title" to title, | |||||
| "can_add_page" to can_add_page | |||||
| ) | |||||
| } | |||||
| } | |||||
| override val inflateId: Int | |||||
| get() = R.layout.activity_note | |||||
| override fun initView() { | |||||
| checkPermission() | |||||
| requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT | |||||
| mScreenH = resources.displayMetrics.heightPixels | |||||
| mScreenW = resources.displayMetrics.widthPixels | |||||
| //背景 | |||||
| new_init.setOnClickListener { | |||||
| mBgId++ | |||||
| if (mBgId >= mBGDrawableList.size) { | |||||
| mBgId = 0 | |||||
| } | |||||
| note_view.setBackgroundResource(mBGDrawableList[mBgId]) | |||||
| val note = notList[currIndex] | |||||
| note.BGid = mBgId | |||||
| } | |||||
| //清除 | |||||
| new_clear.setOnClickListener { | |||||
| note_view.clear(); | |||||
| } | |||||
| //笔 | |||||
| pen.setOnClickListener { | |||||
| if (note_view.penType == WeNoteView.TYPE_DRAW_ERASER) { | |||||
| note_view.penType = WeNoteView.TYPE_DRAW_CURVE | |||||
| note_view.updateEnableStatus() | |||||
| Log.d(TAG, "initNoteView: ${note_view.penType}") | |||||
| pen.setCompoundDrawablesWithIntrinsicBounds( | |||||
| 0, | |||||
| R.mipmap.ic_book_pen_select, | |||||
| 0, | |||||
| 0 | |||||
| ) | |||||
| new_eraser.setCompoundDrawablesWithIntrinsicBounds( | |||||
| 0, | |||||
| R.mipmap.ic_book_rubber, | |||||
| 0, | |||||
| 0 | |||||
| ) | |||||
| } | |||||
| } | |||||
| //橡皮 | |||||
| new_eraser.setOnClickListener { | |||||
| if (note_view.penType != WeNoteView.TYPE_DRAW_ERASER) { | |||||
| note_view.penType = WeNoteView.TYPE_DRAW_ERASER | |||||
| note_view.updateEnableStatus() | |||||
| Log.d(TAG, "initNoteView: ${note_view.penType}") | |||||
| pen.setCompoundDrawablesWithIntrinsicBounds(0, R.mipmap.ic_book_pen, 0, 0) | |||||
| new_eraser.setCompoundDrawablesWithIntrinsicBounds( | |||||
| 0, | |||||
| R.mipmap.ic_book_rubber_select, | |||||
| 0, | |||||
| 0 | |||||
| ) | |||||
| } | |||||
| } | |||||
| //加纸 | |||||
| new_add.setOnClickListener { | |||||
| val lastBGid = notList[notList.size - 1].BGid | |||||
| val note = Note() | |||||
| note.BGid = lastBGid | |||||
| notList.add(note) | |||||
| tv_page_index.text = "${currIndex + 1}/${notList.size}" | |||||
| indexBox.visibility = if (notList.size > 1) { | |||||
| View.VISIBLE | |||||
| } else { | |||||
| View.GONE | |||||
| } | |||||
| } | |||||
| //title | |||||
| btnBack.setOnClickListener { onBackPressed() } | |||||
| titleTv.text = intent.getStringExtra("title") | |||||
| //初始化笔记 | |||||
| mWePointList.clear() | |||||
| //屏幕初始化 | |||||
| val filter = IntentFilter() | |||||
| filter.addAction(SCREEN_ON) | |||||
| filter.addAction(SCREEN_OFF) | |||||
| if (mReceiver != null) { | |||||
| registerReceiver(mReceiver, filter) | |||||
| } | |||||
| btnPre.setOnClickListener { | |||||
| if (currIndex - 1 >= 0) { | |||||
| ImageUtils.save( | |||||
| note_view.currentNoteBitmap, | |||||
| "${NOTE_FOLDER_DIR}/${currKey}.png", | |||||
| Bitmap.CompressFormat.PNG | |||||
| ) | |||||
| loadImage(currIndex - 1) | |||||
| } | |||||
| } | |||||
| btnNext.setOnClickListener { | |||||
| if (currIndex + 1 < notList.size) { | |||||
| ImageUtils.save( | |||||
| note_view.currentNoteBitmap, | |||||
| "${NOTE_FOLDER_DIR}/${currKey}.png", | |||||
| Bitmap.CompressFormat.PNG | |||||
| ) | |||||
| loadImage(currIndex + 1) | |||||
| } | |||||
| } | |||||
| saveBtn.setOnClickListener { | |||||
| saveTip.visibility = View.VISIBLE | |||||
| saveTip.text = "保存中..." | |||||
| ImageUtils.save( | |||||
| note_view.currentNoteBitmap, | |||||
| "${NOTE_FOLDER_DIR}/${currKey}.png", | |||||
| Bitmap.CompressFormat.PNG | |||||
| ) | |||||
| save(0) | |||||
| } | |||||
| } | |||||
| override fun onWindowFocusChanged(hasFocus: Boolean) { | |||||
| super.onWindowFocusChanged(hasFocus) | |||||
| if (hasFocus) { | |||||
| note_view.onResume() | |||||
| } else { | |||||
| note_view.onPause() | |||||
| } | |||||
| } | |||||
| @SuppressLint("SetTextI18n") | |||||
| override fun initData() { | |||||
| val json = intent.getStringExtra("note_info") | |||||
| notList.clear() | |||||
| if (!TextUtils.isEmpty(json)) { | |||||
| val jsonArray = JSONArray(json) | |||||
| if (jsonArray.length() > 0) { | |||||
| for (index in 0 until jsonArray.length()) { | |||||
| val jsonObj: JSONObject? = jsonArray?.opt(index) as JSONObject | |||||
| val identity = jsonObj?.getString("identity"); | |||||
| val key = jsonObj?.getString("key") | |||||
| val bgId = jsonObj?.getInt("BGid") | |||||
| val note = Note() | |||||
| note.BGid = bgId ?: 0 | |||||
| note.identity = identity ?: "" | |||||
| note.key = key ?: "" | |||||
| notList.add(note) | |||||
| } | |||||
| } else { | |||||
| notList.add(Note()) | |||||
| } | |||||
| } else { | |||||
| notList.add(Note()) | |||||
| } | |||||
| // Log.d(TAG, "初始化开始note_view") | |||||
| // note_view.post { | |||||
| // Log.d(TAG, "初始化开始note_view.post") | |||||
| // mHandler.post(mRunnable) | |||||
| // } | |||||
| Log.d(TAG, "初始化开始note_view") | |||||
| note_view.setOnFinishListener(object : OnInitedListener { | |||||
| override fun onSizeChanged() { | |||||
| } | |||||
| override fun onInited() { | |||||
| // note_view.post { | |||||
| // Log.d(TAG, "初始化开始note_view.post") | |||||
| // mHandler.post(mRunnable) | |||||
| // } | |||||
| if (mNotePageInfo == null) { | |||||
| mNotePageInfo = getNotePageInfo(NOTE_FOLDER_DIR) | |||||
| } | |||||
| if (mNotePageInfo == null) { | |||||
| Log.d(TAG, "Flash test : +++++ no note, so init a page"); | |||||
| initPage() | |||||
| } | |||||
| loadImage(0) | |||||
| initNoteView() | |||||
| } | |||||
| }) | |||||
| tv_page_index.text = "1/${notList.size}" | |||||
| indexBox.visibility = if (notList.size > 1) { | |||||
| View.VISIBLE | |||||
| } else { | |||||
| View.GONE | |||||
| } | |||||
| val canAddPage = intent.getIntExtra("can_add_page", 1) | |||||
| if (canAddPage == 1) { | |||||
| new_add.visibility = View.VISIBLE | |||||
| } else { | |||||
| new_add.visibility = View.GONE | |||||
| } | |||||
| } | |||||
| private fun loadImage(index: Int = 0) { | |||||
| val note = notList[index] | |||||
| val identity = note.identity | |||||
| val key = note.key | |||||
| val bgId = note.BGid | |||||
| if (TextUtils.isEmpty(key)) { | |||||
| note.key = Date().time.toString() | |||||
| note_view.showExistPage("") | |||||
| note_view.setBackgroundResource(mBGDrawableList[bgId]) | |||||
| currKey = note.key | |||||
| currIndex = index | |||||
| mBgId = bgId | |||||
| tv_page_index.text = "${index + 1}/${notList.size}" | |||||
| return | |||||
| } | |||||
| val path = "${NOTE_FOLDER_DIR}/${key}.png" | |||||
| if (FileUtils.isFileExists(path)) { | |||||
| if (mNotePageInfo == null) { | |||||
| return | |||||
| } | |||||
| mBgId = bgId ?: 0 | |||||
| note_view.showExistPage(path) | |||||
| note_view.setBackgroundResource(mBGDrawableList[bgId]) | |||||
| currKey = key | |||||
| currIndex = index | |||||
| tv_page_index.text = "${index + 1}/${notList.size}" | |||||
| } else { | |||||
| if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(identity)) { | |||||
| saveTip.visibility = View.VISIBLE | |||||
| saveTip.text = "加载中..." | |||||
| val url = "https://${identity}.oa.qbjjyyun.net/edufile/imageView?uniqueKey=${key}" | |||||
| val customTarget: CustomTarget<Drawable> = object : CustomTarget<Drawable>() { | |||||
| override fun onLoadCleared(placeholder: Drawable?) {} | |||||
| override fun onLoadFailed(errorDrawable: Drawable?) { | |||||
| toast("文档加载失败!") | |||||
| saveTip.visibility = View.GONE | |||||
| } | |||||
| override fun onResourceReady( | |||||
| resource: Drawable, | |||||
| transition: Transition<in Drawable>? | |||||
| ) { | |||||
| val bmp = ImageUtils.drawable2Bitmap(resource) | |||||
| ImageUtils.save(bmp, path, Bitmap.CompressFormat.PNG) | |||||
| if (FileUtils.isFileExists(path)) { | |||||
| if (mNotePageInfo == null) { | |||||
| return | |||||
| } | |||||
| mBgId = bgId ?: 0 | |||||
| note_view.showExistPage(path) | |||||
| note_view.setBackgroundResource(mBGDrawableList[bgId]) | |||||
| currKey = key | |||||
| currIndex = index | |||||
| tv_page_index.text = "${index + 1}/${notList.size}" | |||||
| } | |||||
| saveTip.visibility = View.GONE | |||||
| } | |||||
| } | |||||
| Glide.with(this) | |||||
| .load(url) | |||||
| .diskCacheStrategy(DiskCacheStrategy.ALL) | |||||
| .override( | |||||
| Target.SIZE_ORIGINAL, | |||||
| Target.SIZE_ORIGINAL | |||||
| ) | |||||
| .into(customTarget) | |||||
| } else { | |||||
| note.key = Date().time.toString() | |||||
| note_view.showExistPage("") | |||||
| note_view.setBackgroundResource(mBGDrawableList[bgId]) | |||||
| currKey = note.key | |||||
| currIndex = index | |||||
| mBgId = bgId ?: 0 | |||||
| tv_page_index.text = "${index + 1}/${notList.size}" | |||||
| } | |||||
| } | |||||
| } | |||||
| private fun save(index: Int) { | |||||
| val item = notList[index] | |||||
| val path = "${NOTE_FOLDER_DIR}/${item.key}.png" | |||||
| if (!TextUtils.isEmpty(item.key)) { | |||||
| if (FileUtils.isFileExists(path)) { //存在就上传 | |||||
| OkGo.post<String>("https://fileupload.oa.qbjjyyun.net/edufile/fileUpload") | |||||
| .tag(this) | |||||
| .params("token", "0fc58a8df03c46d3f85b1047c4693cf6") | |||||
| .params("user", Date().time) | |||||
| .params("file", File(path)) | |||||
| .execute(object : StringCallback() { | |||||
| override fun onSuccess(response: Response<String>) { | |||||
| try { | |||||
| val json = response.body() | |||||
| Log.d("onSuccess", response.body()) | |||||
| val jsonObject = JSONObject(json) | |||||
| val content = jsonObject.optString("content") | |||||
| Log.d("onSuccess,content", content) | |||||
| val contentObject = JSONObject(content) | |||||
| val key = contentObject.optString("key") | |||||
| val identity = contentObject.optString("identity") | |||||
| Log.d("onSuccess,identity", identity) | |||||
| Log.d("onSuccess,key", key) | |||||
| item.key = key | |||||
| item.identity = identity | |||||
| FileUtils.copy(path, "${NOTE_FOLDER_DIR}/${key}.png") | |||||
| if (index == notList.size - 1) { | |||||
| saveTip.visibility = View.GONE | |||||
| toast("保存成功!") | |||||
| backToH5() | |||||
| } else { | |||||
| save(index + 1) | |||||
| } | |||||
| } catch (e: Exception) { | |||||
| } | |||||
| } | |||||
| override fun onError(response: Response<String>) { | |||||
| super.onError(response) | |||||
| toast("保存失败!") | |||||
| } | |||||
| override fun onFinish() { | |||||
| super.onFinish() | |||||
| saveTip.visibility = View.GONE | |||||
| } | |||||
| }) | |||||
| } else { | |||||
| if (index == notList.size - 1) { | |||||
| saveTip.visibility = View.GONE | |||||
| toast("保存成功!") | |||||
| backToH5() | |||||
| } else { | |||||
| save(index + 1) | |||||
| } | |||||
| } | |||||
| } else { | |||||
| if (index == notList.size - 1) { | |||||
| saveTip.visibility = View.GONE | |||||
| toast("保存成功!") | |||||
| backToH5() | |||||
| } else { | |||||
| save(index + 1) | |||||
| } | |||||
| } | |||||
| } | |||||
| private fun backToH5() { | |||||
| val intent = Intent() | |||||
| Log.d(TAG + "--------1------->", copyList().toString()) | |||||
| Log.d(TAG + "---------2------>", Gson().toJson(copyList())) | |||||
| Log.d(TAG + "---------3------>", GsonUtils.toJson(notList)) | |||||
| intent.putExtra("note_info", GsonUtils.toJson(copyList())) | |||||
| setResult(Activity.RESULT_OK, intent) | |||||
| onBackPressed() | |||||
| } | |||||
| private fun copyList(): MutableList<Note> { | |||||
| val list = mutableListOf<Note>() | |||||
| notList.forEach { | |||||
| if (!TextUtils.isEmpty(it.key) && !TextUtils.isEmpty(it.identity)) { | |||||
| val item = Note() | |||||
| item.key = it.key | |||||
| item.identity = it.identity | |||||
| item.BGid = it.BGid | |||||
| list.add(item) | |||||
| } | |||||
| } | |||||
| return list | |||||
| } | |||||
| data class CopyNote(val key: String, val identity: String, val BGid: Int) | |||||
| override fun initPresenter(): BasePresenter<*>? = null | |||||
| private fun checkPermission() { | |||||
| var isGranted = true | |||||
| if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { | |||||
| //如果没有写sd卡权限 | |||||
| isGranted = false | |||||
| } | |||||
| if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { | |||||
| isGranted = false | |||||
| } | |||||
| Log.i("cbs", "isGranted == $isGranted") | |||||
| if (!isGranted) { | |||||
| requestPermissions( | |||||
| arrayOf( | |||||
| Manifest.permission.ACCESS_COARSE_LOCATION, | |||||
| Manifest.permission.ACCESS_FINE_LOCATION, | |||||
| Manifest.permission.READ_EXTERNAL_STORAGE, | |||||
| Manifest.permission.WRITE_EXTERNAL_STORAGE | |||||
| ), | |||||
| 102 | |||||
| ) | |||||
| } | |||||
| } | |||||
| override fun onResume() { | |||||
| note_view.onResume() | |||||
| super.onResume() | |||||
| } | |||||
| override fun onPause() { | |||||
| note_view.onPause() | |||||
| super.onPause() | |||||
| } | |||||
| override fun onDestroy() { | |||||
| //mView.exitView(); | |||||
| mHandler.removeCallbacks(mRunnable) | |||||
| note_view.exitView() | |||||
| if (mReceiver != null) { | |||||
| unregisterReceiver(mReceiver) | |||||
| mReceiver = null | |||||
| } | |||||
| super.onDestroy() | |||||
| } | |||||
| override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { | |||||
| if (keyCode == KeyEvent.KEYCODE_BACK) { | |||||
| note_view.exitView() | |||||
| if (mReceiver != null) { | |||||
| unregisterReceiver(mReceiver) | |||||
| mReceiver = null | |||||
| } | |||||
| finish() | |||||
| return true | |||||
| } | |||||
| return super.onKeyDown(keyCode, event) | |||||
| } | |||||
| val SCREEN_ON = "android.intent.action.SCREEN_ON" | |||||
| val SCREEN_OFF = "android.intent.action.SCREEN_OFF" | |||||
| private var mReceiver: BroadcastReceiver? = object : BroadcastReceiver() { | |||||
| override fun onReceive(context: Context, intent: Intent) { | |||||
| // 屏幕唤醒 | |||||
| // if (SCREEN_ON == intent.action) { | |||||
| // note_view.setSleepMode(true) | |||||
| // } else if (SCREEN_OFF == intent.action) { | |||||
| // note_view.setSleepMode(true) | |||||
| // } | |||||
| } | |||||
| } | |||||
| private val mRunnable: Runnable = object : Runnable { | |||||
| override fun run() { | |||||
| Log.d(TAG, "初始化开始-------------》"); | |||||
| var count = 0 | |||||
| while (note_view.height <= 0) { | |||||
| try { | |||||
| Thread.sleep(50) | |||||
| } catch (e: InterruptedException) { | |||||
| e.printStackTrace() | |||||
| } | |||||
| if (count++ > 40) { | |||||
| Log.d(TAG, "Flash test : ++++++++ removeCallbacks"); | |||||
| mHandler.removeCallbacks(this) | |||||
| exitProcess(0) | |||||
| } | |||||
| } | |||||
| //note_view.initNative(new Rect(mScreenW, mScreenH - note_view.getHeight(), 0, mScreenH), SAVE_PIC_PATH); | |||||
| Log.d( | |||||
| TAG, | |||||
| "Flash test : ++++++++ mView.getHeight() = " + note_view.height + ", count = " + count | |||||
| ); | |||||
| // note_view.initNative( | |||||
| // Rect( | |||||
| // mScreenW, | |||||
| // mScreenH - note_view.height, | |||||
| // 0, | |||||
| // mScreenH | |||||
| // ) | |||||
| // ) | |||||
| note_view.setTouchEventHander(mPointHandler) | |||||
| Log.d(TAG, "Flash test : ++++++ mRunnable() start loader notepageinfo"); | |||||
| if (mNotePageInfo == null) { | |||||
| mNotePageInfo = getNotePageInfo(NOTE_FOLDER_DIR) | |||||
| } | |||||
| if (mNotePageInfo == null) { | |||||
| Log.d(TAG, "Flash test : +++++ no note, so init a page"); | |||||
| initPage() | |||||
| } | |||||
| loadImage(0) | |||||
| initNoteView() | |||||
| Log.d(TAG, "初始化结束-------------》"); | |||||
| } | |||||
| } | |||||
| private fun initNoteView() { | |||||
| //写字板初始化 | |||||
| // note_view.setEnable(true) | |||||
| note_view.penWidth = 3 | |||||
| note_view.eraserWidth = 20 | |||||
| note_view.penType = WeNoteView.TYPE_DRAW_CURVE | |||||
| note_view.updateEnableStatus() | |||||
| Log.d(TAG, "initNoteView: ${note_view.penType}") | |||||
| } | |||||
| override fun finish() { | |||||
| note_view.exitView() | |||||
| if (mReceiver != null) { | |||||
| unregisterReceiver(mReceiver) | |||||
| mReceiver = null | |||||
| } | |||||
| super.finish() | |||||
| } | |||||
| override fun onBackPressed() { | |||||
| note_view.exitView() | |||||
| if (mReceiver != null) { | |||||
| unregisterReceiver(mReceiver) | |||||
| mReceiver = null | |||||
| } | |||||
| super.onBackPressed() | |||||
| } | |||||
| private fun initPage(): Boolean { | |||||
| var file = File(NOTE_FOLDER_DIR) | |||||
| if (!file.exists()) { | |||||
| if (!FileUtils.createOrExistsDir(file)) { | |||||
| return false | |||||
| } | |||||
| } | |||||
| var notePath: String? = null | |||||
| file = File("$NOTE_FOLDER_DIR/${currKey}.png") | |||||
| if (file.exists()) { | |||||
| notePath = "$NOTE_FOLDER_DIR/${currKey}.png" | |||||
| } | |||||
| mNotePageInfo = NotePageInfo(notePath, mBgId) | |||||
| return true | |||||
| } | |||||
| private fun loadOldPage() { | |||||
| if (mNotePageInfo == null) { | |||||
| return | |||||
| } | |||||
| mBgId = mNotePageInfo?.drwId ?: 0 | |||||
| note_view.showExistPage(mNotePageInfo?.notePath) | |||||
| note_view.setBackgroundResource(mBGDrawableList[mBgId]) | |||||
| } | |||||
| //从笔记文件夹中读取当前笔记的页面信息 | |||||
| private fun getNotePageInfo(path: String): NotePageInfo? { | |||||
| var file = File(path) | |||||
| if (!file.exists()) { | |||||
| return null | |||||
| } | |||||
| file.listFiles() ?: return null | |||||
| val info = NotePageInfo(null, 0) | |||||
| val notePath = "$path/${currKey}.png" | |||||
| file = File(notePath) | |||||
| if (file.exists()) { | |||||
| info.notePath = notePath | |||||
| } | |||||
| info.drwId = 0 //Integer.parseInt(drwId); | |||||
| return info | |||||
| } | |||||
| private val mPointHandler: Handler = @SuppressLint("HandlerLeak") | |||||
| object : Handler() { | |||||
| override fun handleMessage(msg: Message) { | |||||
| val what = msg.what | |||||
| //同步获取的笔记点坐标信息msg | |||||
| if (what == WeNoteView.TOUCH_EVENT) { | |||||
| val point = msg.obj as WePoint | |||||
| mWePointList.add(point) | |||||
| } | |||||
| //保存笔记结束msg | |||||
| if (what == MSG_SAVE_END) { | |||||
| val status = msg.arg1 | |||||
| if (status > 0) { //保存成功 | |||||
| Toast.makeText(applicationContext, "保存成功!", Toast.LENGTH_SHORT).show(); | |||||
| } else { //保存失败 | |||||
| Toast.makeText(applicationContext, "保存失败!", Toast.LENGTH_SHORT) | |||||
| .show(); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,171 +0,0 @@ | |||||
| package com.yzx.webebook.activity | |||||
| import android.content.Context | |||||
| import android.os.PowerManager | |||||
| import android.os.PowerManager.WakeLock | |||||
| import androidx.viewpager.widget.ViewPager | |||||
| import com.blankj.utilcode.util.NumberUtils | |||||
| import com.yzx.webebook.R | |||||
| import com.yzx.webebook.activity.base.BaseActivity | |||||
| import com.yzx.webebook.model.bean.BookRecordBean | |||||
| import com.yzx.webebook.model.bean.CollBookBean | |||||
| import com.yzx.webebook.model.local.BookRepository | |||||
| import com.yzx.webebook.presenter.ReadPresenter | |||||
| import com.yzx.webebook.presenter.ReadView | |||||
| import com.yzx.webebook.widget.YzxPDFViewPager | |||||
| import kotlinx.android.synthetic.main.activity_pdf_view.* | |||||
| /** | |||||
| * pdf 预览页面 | |||||
| */ | |||||
| class PDFViewActivity : BaseActivity<ReadPresenter>(), ReadView { | |||||
| private var mBookRecord: BookRecordBean? = null | |||||
| private var mCollBook: CollBookBean? = null | |||||
| private var mRealBookId: String = "" | |||||
| private var mReadTaskId: String = "" | |||||
| private var mBookId: String = "" | |||||
| var currPage = 0 | |||||
| var total = 0 | |||||
| var oldPosition = 0 | |||||
| var lastProgress = 0f | |||||
| //控制屏幕常亮 | |||||
| private var mWakeLock: WakeLock? = null | |||||
| override val inflateId: Int | |||||
| get() = R.layout.activity_pdf_view | |||||
| override fun initView() { | |||||
| mBookId = intent.getStringExtra("book_id") ?: "" | |||||
| mReadTaskId = intent.getStringExtra("read_task_id") ?: "" | |||||
| mRealBookId = intent.getStringExtra("real_book_id") ?: "" | |||||
| mCollBook = BookRepository.getInstance().getCollBook(mBookId) | |||||
| mCollBook.apply { | |||||
| loadPdf() | |||||
| } | |||||
| mPresenter?.getReadProgress(mRealBookId, mReadTaskId) | |||||
| } | |||||
| private fun loadPdf() { | |||||
| val pdf = YzxPDFViewPager(this, mCollBook?.cover ?: "") | |||||
| pdfView.addView(pdf) | |||||
| total = pdf.adapter?.count ?: 0 | |||||
| btnLeft.setOnClickListener { | |||||
| if (currPage > 0) { | |||||
| pdf.currentItem = --currPage | |||||
| } | |||||
| } | |||||
| btnRight.setOnClickListener { | |||||
| if (currPage < total - 1) { | |||||
| pdf.currentItem = ++currPage | |||||
| } | |||||
| } | |||||
| prepareBook() | |||||
| pdf.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { | |||||
| override fun onPageScrollStateChanged(state: Int) { | |||||
| } | |||||
| override fun onPageScrolled( | |||||
| position: Int, | |||||
| positionOffset: Float, | |||||
| positionOffsetPixels: Int | |||||
| ) { | |||||
| } | |||||
| override fun onPageSelected(position: Int) { | |||||
| currPageTv.text = "${position + 1}" | |||||
| percentTv.text = "${getPercent(position.toFloat(), total.toFloat())}%" | |||||
| mBookRecord?.pagePos = position | |||||
| } | |||||
| }) | |||||
| val pos = mBookRecord?.pagePos ?: 0; | |||||
| pdf.currentItem = pos | |||||
| currPage = pos | |||||
| } | |||||
| /** | |||||
| * 初始化书籍 | |||||
| */ | |||||
| private fun prepareBook() { | |||||
| mBookRecord = BookRepository.getInstance() | |||||
| .getBookRecord(mCollBook!!._id) | |||||
| if (mBookRecord == null) { | |||||
| mBookRecord = BookRecordBean() | |||||
| mBookRecord?.bookId = mBookId | |||||
| totalPageTv.text = "$total" | |||||
| currPageTv.text = "${currPage + 1}" | |||||
| percentTv.text = "${getPercent(1f, total.toFloat())}%" | |||||
| oldPosition = 0 | |||||
| } else { | |||||
| oldPosition = mBookRecord!!.pagePos | |||||
| totalPageTv.text = "$total" | |||||
| currPageTv.text = "${mBookRecord!!.pagePos + 1}" | |||||
| percentTv.text = | |||||
| "${getPercent((mBookRecord!!.pagePos + 1).toFloat(), total.toFloat())}%" | |||||
| } | |||||
| } | |||||
| override fun initData() { | |||||
| //初始化屏幕常亮类 | |||||
| //初始化屏幕常亮类 | |||||
| val pm = | |||||
| getSystemService(Context.POWER_SERVICE) as PowerManager | |||||
| mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "ireader:keep bright") | |||||
| } | |||||
| private fun getPercent(curr: Float, total: Float): String { | |||||
| val percent = NumberUtils.format(curr * 100f / total, 2) | |||||
| return "$percent" | |||||
| } | |||||
| override fun initPresenter(): ReadPresenter = ReadPresenter(this) | |||||
| override fun onResume() { | |||||
| super.onResume() | |||||
| mWakeLock?.acquire() | |||||
| } | |||||
| override fun onPause() { | |||||
| super.onPause() | |||||
| mWakeLock?.release() | |||||
| //存储到数据库 | |||||
| if (mBookRecord != null) { | |||||
| BookRepository.getInstance() | |||||
| .saveBookRecord(mBookRecord) | |||||
| val currProgress = getPercent( | |||||
| (mBookRecord!!.pagePos + 1).toFloat(), | |||||
| total.toFloat() | |||||
| ).toFloat() | |||||
| if (mBookRecord!!.pagePos > oldPosition && currProgress > lastProgress) { | |||||
| mPresenter?.updateReadProgress( | |||||
| mRealBookId, mReadTaskId, currProgress.toString() | |||||
| ) | |||||
| } | |||||
| } | |||||
| } | |||||
| override fun finishChapter() { | |||||
| } | |||||
| override fun errorChapter() { | |||||
| } | |||||
| override fun showCategory(localId: String?) { | |||||
| } | |||||
| override fun onProgressSuccess(progress: Float) { | |||||
| lastProgress = progress | |||||
| } | |||||
| } | |||||
| @@ -1,730 +0,0 @@ | |||||
| package com.yzx.webebook.activity; | |||||
| import android.app.Activity; | |||||
| import android.app.AlertDialog; | |||||
| import android.content.BroadcastReceiver; | |||||
| import android.content.ContentResolver; | |||||
| import android.content.Context; | |||||
| import android.content.Intent; | |||||
| import android.content.IntentFilter; | |||||
| import android.database.ContentObserver; | |||||
| import android.graphics.drawable.Drawable; | |||||
| import android.net.Uri; | |||||
| import android.os.Build; | |||||
| import android.os.Bundle; | |||||
| import android.os.Handler; | |||||
| import android.os.Message; | |||||
| import android.os.PowerManager; | |||||
| import android.provider.Settings; | |||||
| import android.util.Log; | |||||
| import android.view.Gravity; | |||||
| import android.view.KeyEvent; | |||||
| import android.view.View; | |||||
| import android.view.ViewGroup; | |||||
| import android.view.animation.Animation; | |||||
| import android.view.animation.AnimationUtils; | |||||
| import android.widget.LinearLayout; | |||||
| import android.widget.ListView; | |||||
| import android.widget.SeekBar; | |||||
| import android.widget.TextView; | |||||
| import androidx.core.content.ContextCompat; | |||||
| import androidx.core.view.GravityCompat; | |||||
| import androidx.drawerlayout.widget.DrawerLayout; | |||||
| import com.blankj.utilcode.util.NumberUtils; | |||||
| import com.google.android.material.appbar.AppBarLayout; | |||||
| import com.yzx.webebook.R; | |||||
| import com.yzx.webebook.activity.base.BaseActivity; | |||||
| import com.yzx.webebook.adapter.CategoryAdapter; | |||||
| import com.yzx.webebook.model.bean.BookChapterBean; | |||||
| import com.yzx.webebook.model.bean.CollBookBean; | |||||
| import com.yzx.webebook.model.local.BookRepository; | |||||
| import com.yzx.webebook.model.local.ReadSettingManager; | |||||
| import com.yzx.webebook.presenter.ReadPresenter; | |||||
| import com.yzx.webebook.presenter.ReadView; | |||||
| import com.yzx.webebook.utils.BrightnessUtils; | |||||
| import com.yzx.webebook.utils.Constant; | |||||
| import com.yzx.webebook.utils.LogUtils; | |||||
| import com.yzx.webebook.utils.RxUtils; | |||||
| import com.yzx.webebook.utils.ScreenUtils; | |||||
| import com.yzx.webebook.utils.StringUtils; | |||||
| import com.yzx.webebook.utils.SystemBarUtils; | |||||
| import com.yzx.webebook.widget.ReadSettingDialog; | |||||
| import com.yzx.webebook.widget.page.PageLoader; | |||||
| import com.yzx.webebook.widget.page.PageView; | |||||
| import com.yzx.webebook.widget.page.TxtChapter; | |||||
| import org.jetbrains.annotations.Nullable; | |||||
| import java.util.List; | |||||
| import io.reactivex.disposables.Disposable; | |||||
| import static android.view.View.GONE; | |||||
| import static android.view.View.VISIBLE; | |||||
| public class ReadActivity extends BaseActivity<ReadPresenter> implements ReadView { | |||||
| private static final String TAG = "ReadActivity"; | |||||
| public static final int REQUEST_MORE_SETTING = 1; | |||||
| public static final String EXTRA_COLL_BOOK = "extra_coll_book"; | |||||
| public static final String EXTRA_IS_COLLECTED = "extra_is_collected"; | |||||
| // 注册 Brightness 的 uri | |||||
| private final Uri BRIGHTNESS_MODE_URI = | |||||
| Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE); | |||||
| private final Uri BRIGHTNESS_URI = | |||||
| Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS); | |||||
| private final Uri BRIGHTNESS_ADJ_URI = | |||||
| Settings.System.getUriFor("screen_auto_brightness_adj"); | |||||
| private static final int WHAT_CATEGORY = 1; | |||||
| private static final int WHAT_CHAPTER = 2; | |||||
| DrawerLayout mDlSlide; | |||||
| /*************top_menu_view*******************/ | |||||
| // AppBarLayout mAblTopMenu; | |||||
| // TextView mTvCommunity; | |||||
| // TextView mTvBrief; | |||||
| /***************content_view******************/ | |||||
| PageView mPvPage; | |||||
| /***************bottom_menu_view***************************/ | |||||
| TextView mTvPageTip; | |||||
| LinearLayout mLlBottomMenu; | |||||
| TextView mTvPreChapter; | |||||
| SeekBar mSbChapterProgress; | |||||
| TextView mTvNextChapter; | |||||
| TextView mTvCategory; | |||||
| TextView mTvNightMode; | |||||
| TextView mTvSetting; | |||||
| /***************left slide*******************************/ | |||||
| ListView mLvCategory; | |||||
| /*****************view******************/ | |||||
| private ReadSettingDialog mSettingDialog; | |||||
| private PageLoader mPageLoader; | |||||
| private Animation mTopInAnim; | |||||
| private Animation mTopOutAnim; | |||||
| private Animation mBottomInAnim; | |||||
| private Animation mBottomOutAnim; | |||||
| private CategoryAdapter mCategoryAdapter; | |||||
| private CollBookBean mCollBook; | |||||
| //控制屏幕常亮 | |||||
| private PowerManager.WakeLock mWakeLock; | |||||
| /***************params*****************/ | |||||
| private boolean isCollected = false; // isFromSDCard | |||||
| private boolean isNightMode = false; | |||||
| private boolean isFullScreen = false; | |||||
| private boolean isRegistered = false; | |||||
| private String mBookId; | |||||
| private String mRealBookId; | |||||
| private String mReadTaskId; | |||||
| private float lastProgress = 0f; | |||||
| private Handler mHandler = new Handler() { | |||||
| @Override | |||||
| public void handleMessage(Message msg) { | |||||
| super.handleMessage(msg); | |||||
| switch (msg.what) { | |||||
| case WHAT_CATEGORY: | |||||
| mLvCategory.setSelection(mPageLoader.getChapterPos()); | |||||
| break; | |||||
| case WHAT_CHAPTER: | |||||
| mPageLoader.openChapter(); | |||||
| break; | |||||
| } | |||||
| } | |||||
| }; | |||||
| // 接收电池信息和时间更新的广播 | |||||
| private BroadcastReceiver mReceiver = new BroadcastReceiver() { | |||||
| @Override | |||||
| public void onReceive(Context context, Intent intent) { | |||||
| if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) { | |||||
| int level = intent.getIntExtra("level", 0); | |||||
| if (mPageLoader != null) { | |||||
| mPageLoader.updateBattery(level); | |||||
| } | |||||
| } | |||||
| // 监听分钟的变化 | |||||
| else if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) { | |||||
| if (mPageLoader != null) { | |||||
| mPageLoader.updateTime(); | |||||
| } | |||||
| } | |||||
| } | |||||
| }; | |||||
| // 亮度调节监听 | |||||
| // 由于亮度调节没有 Broadcast 而是直接修改 ContentProvider 的。所以需要创建一个 Observer 来监听 ContentProvider 的变化情况。 | |||||
| private ContentObserver mBrightObserver = new ContentObserver(new Handler()) { | |||||
| @Override | |||||
| public void onChange(boolean selfChange) { | |||||
| onChange(selfChange, null); | |||||
| } | |||||
| @Override | |||||
| public void onChange(boolean selfChange, Uri uri) { | |||||
| super.onChange(selfChange); | |||||
| // 判断当前是否跟随屏幕亮度,如果不是则返回 | |||||
| if (selfChange || !mSettingDialog.isBrightFollowSystem()) return; | |||||
| // 如果系统亮度改变,则修改当前 Activity 亮度 | |||||
| if (BRIGHTNESS_MODE_URI.equals(uri)) { | |||||
| Log.d(TAG, "亮度模式改变"); | |||||
| } else if (BRIGHTNESS_URI.equals(uri) && !BrightnessUtils.isAutoBrightness(ReadActivity.this)) { | |||||
| Log.d(TAG, "亮度模式为手动模式 值改变"); | |||||
| BrightnessUtils.setBrightness(ReadActivity.this, BrightnessUtils.getScreenBrightness(ReadActivity.this)); | |||||
| } else if (BRIGHTNESS_ADJ_URI.equals(uri) && BrightnessUtils.isAutoBrightness(ReadActivity.this)) { | |||||
| Log.d(TAG, "亮度模式为自动模式 值改变"); | |||||
| BrightnessUtils.setDefaultBrightness(ReadActivity.this); | |||||
| } else { | |||||
| Log.d(TAG, "亮度调整 其他"); | |||||
| } | |||||
| } | |||||
| }; | |||||
| @Override | |||||
| protected void onCreate(Bundle savedInstanceState) { | |||||
| super.onCreate(savedInstanceState); | |||||
| } | |||||
| @Override | |||||
| public int getInflateId() { | |||||
| return R.layout.activity_read; | |||||
| } | |||||
| @Override | |||||
| public void initView() { | |||||
| mDlSlide = findViewById(R.id.read_dl_slide); | |||||
| // mTvCommunity = findViewById(R.id.read_tv_community); | |||||
| // mTvBrief = findViewById(R.id.read_tv_brief); | |||||
| mPvPage = findViewById(R.id.read_pv_page); | |||||
| mTvPageTip = findViewById(R.id.read_tv_page_tip); | |||||
| mLlBottomMenu = findViewById(R.id.read_ll_bottom_menu); | |||||
| mTvPreChapter = findViewById(R.id.read_tv_pre_chapter); | |||||
| mSbChapterProgress = findViewById(R.id.read_sb_chapter_progress); | |||||
| mTvNextChapter = findViewById(R.id.read_tv_next_chapter); | |||||
| mTvCategory = findViewById(R.id.read_tv_category); | |||||
| mTvNightMode = findViewById(R.id.read_tv_night_mode); | |||||
| mTvSetting = findViewById(R.id.read_tv_setting); | |||||
| mLvCategory = findViewById(R.id.read_iv_category); | |||||
| } | |||||
| @Override | |||||
| public void initData() { | |||||
| String id = getIntent().getStringExtra("book_id"); | |||||
| mReadTaskId = getIntent().getStringExtra("read_task_id"); | |||||
| mRealBookId = getIntent().getStringExtra("real_book_id"); | |||||
| loadBookData(id); | |||||
| getMPresenter().getReadProgress(mRealBookId, mReadTaskId); | |||||
| } | |||||
| private void loadBookData(String id) { | |||||
| mCollBook = BookRepository.getInstance().getCollBook(id); | |||||
| isNightMode = ReadSettingManager.getInstance().isNightMode(); | |||||
| isFullScreen = ReadSettingManager.getInstance().isFullScreen(); | |||||
| mBookId = mCollBook.get_id(); | |||||
| Log.d(TAG, "initData: " + mCollBook.toString()); | |||||
| //获取页面加载器 | |||||
| mPageLoader = mPvPage.getPageLoader(mCollBook); | |||||
| //禁止滑动展示DrawerLayout | |||||
| mDlSlide.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); | |||||
| //侧边打开后,返回键能够起作用 | |||||
| mDlSlide.setFocusableInTouchMode(false); | |||||
| mSettingDialog = new ReadSettingDialog(this, mPageLoader); | |||||
| setUpAdapter(); | |||||
| //夜间模式按钮的状态 | |||||
| toggleNightMode(); | |||||
| //注册广播 | |||||
| IntentFilter intentFilter = new IntentFilter(); | |||||
| intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); | |||||
| intentFilter.addAction(Intent.ACTION_TIME_TICK); | |||||
| registerReceiver(mReceiver, intentFilter); | |||||
| //设置当前Activity的Brightness | |||||
| if (ReadSettingManager.getInstance().isBrightnessAuto()) { | |||||
| BrightnessUtils.setDefaultBrightness(this); | |||||
| } else { | |||||
| BrightnessUtils.setBrightness(this, ReadSettingManager.getInstance().getBrightness()); | |||||
| } | |||||
| //初始化屏幕常亮类 | |||||
| PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); | |||||
| mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "ireader:keep bright"); | |||||
| //初始化BottomMenu | |||||
| initBottomMenu(); | |||||
| Disposable disposable = BookRepository.getInstance() | |||||
| .getBookChaptersInRx(mBookId) | |||||
| .compose(RxUtils::toSimpleSingle) | |||||
| .subscribe( | |||||
| (bookChapterBeen, throwable) -> { | |||||
| // 设置 CollBook | |||||
| mPageLoader.getCollBook().setBookChapters(bookChapterBeen); | |||||
| // 刷新章节列表 | |||||
| mPageLoader.refreshChapterList(); | |||||
| LogUtils.e(throwable); | |||||
| } | |||||
| ); | |||||
| addDisposable(disposable); | |||||
| initClick(); | |||||
| } | |||||
| private void saveBookInfo() { | |||||
| if (mCollBook != null) { | |||||
| mCollBook.setLastRead(StringUtils. | |||||
| dateConvert(System.currentTimeMillis(), Constant.FORMAT_BOOK_DATE)); | |||||
| BookRepository.getInstance() | |||||
| .saveCollBookWithAsync(mCollBook); | |||||
| } | |||||
| } | |||||
| private void initClick() { | |||||
| mPageLoader.setOnPageChangeListener( | |||||
| new PageLoader.OnPageChangeListener() { | |||||
| @Override | |||||
| public void onChapterChange(int pos) { | |||||
| mCategoryAdapter.setChapter(pos); | |||||
| } | |||||
| @Override | |||||
| public void requestChapters(List<TxtChapter> requestChapters) { | |||||
| getMPresenter().loadChapter(mBookId, requestChapters); | |||||
| mHandler.sendEmptyMessage(WHAT_CATEGORY); | |||||
| //隐藏提示 | |||||
| mTvPageTip.setVisibility(GONE); | |||||
| } | |||||
| @Override | |||||
| public void onCategoryFinish(List<TxtChapter> chapters) { | |||||
| for (TxtChapter chapter : chapters) { | |||||
| chapter.setTitle(StringUtils.convertCC(chapter.getTitle(), mPvPage.getContext())); | |||||
| } | |||||
| mCategoryAdapter.refreshItems(chapters); | |||||
| } | |||||
| @Override | |||||
| public void onPageCountChange(int count) { | |||||
| mSbChapterProgress.setMax(Math.max(0, count - 1)); | |||||
| mSbChapterProgress.setProgress(0); | |||||
| // 如果处于错误状态,那么就冻结使用 | |||||
| if (mPageLoader.getPageStatus() == PageLoader.STATUS_LOADING | |||||
| || mPageLoader.getPageStatus() == PageLoader.STATUS_ERROR) { | |||||
| mSbChapterProgress.setEnabled(false); | |||||
| } else { | |||||
| mSbChapterProgress.setEnabled(true); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public void onPageChange(int pos) { | |||||
| mSbChapterProgress.post( | |||||
| () -> { | |||||
| mSbChapterProgress.setProgress(pos); | |||||
| } | |||||
| ); | |||||
| } | |||||
| } | |||||
| ); | |||||
| mSbChapterProgress.setOnSeekBarChangeListener( | |||||
| new SeekBar.OnSeekBarChangeListener() { | |||||
| @Override | |||||
| public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { | |||||
| if (mLlBottomMenu.getVisibility() == VISIBLE) { | |||||
| //显示标题 | |||||
| mTvPageTip.setText((progress + 1) + "/" + (mSbChapterProgress.getMax() + 1)); | |||||
| mTvPageTip.setVisibility(VISIBLE); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public void onStartTrackingTouch(SeekBar seekBar) { | |||||
| } | |||||
| @Override | |||||
| public void onStopTrackingTouch(SeekBar seekBar) { | |||||
| //进行切换 | |||||
| int pagePos = mSbChapterProgress.getProgress(); | |||||
| if (pagePos != mPageLoader.getPagePos()) { | |||||
| mPageLoader.skipToPage(pagePos); | |||||
| } | |||||
| //隐藏提示 | |||||
| mTvPageTip.setVisibility(GONE); | |||||
| } | |||||
| } | |||||
| ); | |||||
| mPvPage.setTouchListener(new PageView.TouchListener() { | |||||
| @Override | |||||
| public boolean onTouch() { | |||||
| return !hideReadMenu(); | |||||
| } | |||||
| @Override | |||||
| public void center() { | |||||
| toggleMenu(true); | |||||
| } | |||||
| @Override | |||||
| public void prePage() { | |||||
| } | |||||
| @Override | |||||
| public void nextPage() { | |||||
| } | |||||
| @Override | |||||
| public void cancel() { | |||||
| } | |||||
| }); | |||||
| mLvCategory.setOnItemClickListener( | |||||
| (parent, view, position, id) -> { | |||||
| mDlSlide.closeDrawer(GravityCompat.START); | |||||
| mPageLoader.skipToChapter(position); | |||||
| } | |||||
| ); | |||||
| mTvCategory.setOnClickListener( | |||||
| (v) -> { | |||||
| //移动到指定位置 | |||||
| if (mCategoryAdapter.getCount() > 0) { | |||||
| mLvCategory.setSelection(mPageLoader.getChapterPos()); | |||||
| } | |||||
| //切换菜单 | |||||
| toggleMenu(true); | |||||
| //打开侧滑动栏 | |||||
| mDlSlide.openDrawer(GravityCompat.START); | |||||
| } | |||||
| ); | |||||
| mTvSetting.setOnClickListener( | |||||
| (v) -> { | |||||
| toggleMenu(false); | |||||
| mSettingDialog.show(); | |||||
| } | |||||
| ); | |||||
| mTvPreChapter.setOnClickListener( | |||||
| (v) -> { | |||||
| if (mPageLoader.skipPreChapter()) { | |||||
| mCategoryAdapter.setChapter(mPageLoader.getChapterPos()); | |||||
| } | |||||
| } | |||||
| ); | |||||
| mTvNextChapter.setOnClickListener( | |||||
| (v) -> { | |||||
| if (mPageLoader.skipNextChapter()) { | |||||
| mCategoryAdapter.setChapter(mPageLoader.getChapterPos()); | |||||
| } | |||||
| } | |||||
| ); | |||||
| mTvNightMode.setOnClickListener( | |||||
| (v) -> { | |||||
| if (isNightMode) { | |||||
| isNightMode = false; | |||||
| } else { | |||||
| isNightMode = true; | |||||
| } | |||||
| mPageLoader.setNightMode(isNightMode); | |||||
| toggleNightMode(); | |||||
| } | |||||
| ); | |||||
| } | |||||
| @Nullable | |||||
| @Override | |||||
| public ReadPresenter initPresenter() { | |||||
| return new ReadPresenter(this); | |||||
| } | |||||
| @Override | |||||
| public void showCategory(String localId) { | |||||
| loadBookData(localId); | |||||
| } | |||||
| @Override | |||||
| public void finishChapter() { | |||||
| } | |||||
| @Override | |||||
| public void errorChapter() { | |||||
| } | |||||
| private void initBottomMenu() { | |||||
| //判断是否全屏 | |||||
| if (ReadSettingManager.getInstance().isFullScreen()) { | |||||
| //还需要设置mBottomMenu的底部高度 | |||||
| ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mLlBottomMenu.getLayoutParams(); | |||||
| params.bottomMargin = ScreenUtils.getNavigationBarHeight(); | |||||
| mLlBottomMenu.setLayoutParams(params); | |||||
| } else { | |||||
| //设置mBottomMenu的底部距离 | |||||
| ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mLlBottomMenu.getLayoutParams(); | |||||
| params.bottomMargin = 0; | |||||
| mLlBottomMenu.setLayoutParams(params); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public void onWindowFocusChanged(boolean hasFocus) { | |||||
| super.onWindowFocusChanged(hasFocus); | |||||
| } | |||||
| private void toggleNightMode() { | |||||
| if (isNightMode) { | |||||
| mTvNightMode.setText("日间"); | |||||
| Drawable drawable = ContextCompat.getDrawable(this, R.mipmap.ic_read_menu_morning); | |||||
| mTvNightMode.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null); | |||||
| } else { | |||||
| mTvNightMode.setText("夜间"); | |||||
| Drawable drawable = ContextCompat.getDrawable(this, R.mipmap.ic_read_menu_night); | |||||
| mTvNightMode.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null); | |||||
| } | |||||
| } | |||||
| private void setUpAdapter() { | |||||
| mCategoryAdapter = new CategoryAdapter(); | |||||
| mLvCategory.setAdapter(mCategoryAdapter); | |||||
| mLvCategory.setFastScrollEnabled(true); | |||||
| } | |||||
| // 注册亮度观察者 | |||||
| private void registerBrightObserver() { | |||||
| try { | |||||
| if (mBrightObserver != null) { | |||||
| if (!isRegistered) { | |||||
| final ContentResolver cr = getContentResolver(); | |||||
| cr.unregisterContentObserver(mBrightObserver); | |||||
| cr.registerContentObserver(BRIGHTNESS_MODE_URI, false, mBrightObserver); | |||||
| cr.registerContentObserver(BRIGHTNESS_URI, false, mBrightObserver); | |||||
| cr.registerContentObserver(BRIGHTNESS_ADJ_URI, false, mBrightObserver); | |||||
| isRegistered = true; | |||||
| } | |||||
| } | |||||
| } catch (Throwable throwable) { | |||||
| LogUtils.e(TAG, "register mBrightObserver error! " + throwable); | |||||
| } | |||||
| } | |||||
| //解注册 | |||||
| private void unregisterBrightObserver() { | |||||
| try { | |||||
| if (mBrightObserver != null) { | |||||
| if (isRegistered) { | |||||
| getContentResolver().unregisterContentObserver(mBrightObserver); | |||||
| isRegistered = false; | |||||
| } | |||||
| } | |||||
| } catch (Throwable throwable) { | |||||
| LogUtils.e(TAG, "unregister BrightnessObserver error! " + throwable); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 隐藏阅读界面的菜单显示 | |||||
| * | |||||
| * @return 是否隐藏成功 | |||||
| */ | |||||
| private boolean hideReadMenu() { | |||||
| if (mLlBottomMenu.getVisibility() == VISIBLE) { | |||||
| toggleMenu(true); | |||||
| return true; | |||||
| } else if (mSettingDialog.isShowing()) { | |||||
| mSettingDialog.dismiss(); | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /** | |||||
| * 切换菜单栏的可视状态 | |||||
| * 默认是隐藏的 | |||||
| */ | |||||
| private void toggleMenu(boolean hideStatusBar) { | |||||
| initMenuAnim(); | |||||
| if (mLlBottomMenu.getVisibility() == View.VISIBLE) { | |||||
| //关闭 | |||||
| mLlBottomMenu.setVisibility(GONE); | |||||
| mTvPageTip.setVisibility(GONE); | |||||
| } else { | |||||
| mLlBottomMenu.setVisibility(View.VISIBLE); | |||||
| } | |||||
| } | |||||
| //初始化菜单动画 | |||||
| private void initMenuAnim() { | |||||
| if (mTopInAnim != null) return; | |||||
| mTopInAnim = AnimationUtils.loadAnimation(this, R.anim.slide_top_in); | |||||
| mTopOutAnim = AnimationUtils.loadAnimation(this, R.anim.slide_top_out); | |||||
| mBottomInAnim = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_in); | |||||
| mBottomOutAnim = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_out); | |||||
| //退出的速度要快 | |||||
| mTopOutAnim.setDuration(200); | |||||
| mBottomOutAnim.setDuration(200); | |||||
| } | |||||
| @Override | |||||
| public void onBackPressed() { | |||||
| if (mLlBottomMenu.getVisibility() == View.VISIBLE) { | |||||
| // 非全屏下才收缩,全屏下直接退出 | |||||
| if (!ReadSettingManager.getInstance().isFullScreen()) { | |||||
| toggleMenu(true); | |||||
| return; | |||||
| } | |||||
| } else if (mSettingDialog.isShowing()) { | |||||
| mSettingDialog.dismiss(); | |||||
| return; | |||||
| } else if (mDlSlide.isDrawerOpen(GravityCompat.START)) { | |||||
| mDlSlide.closeDrawer(GravityCompat.START); | |||||
| return; | |||||
| } | |||||
| if (!mCollBook.isLocal() && !isCollected | |||||
| && !mCollBook.getBookChapters().isEmpty() && false) { | |||||
| AlertDialog alertDialog = new AlertDialog.Builder(this) | |||||
| .setTitle("加入书架") | |||||
| .setMessage("喜欢本书就加入书架吧") | |||||
| .setPositiveButton("确定", (dialog, which) -> { | |||||
| //设置为已收藏 | |||||
| isCollected = true; | |||||
| //设置阅读时间 | |||||
| mCollBook.setLastRead(StringUtils. | |||||
| dateConvert(System.currentTimeMillis(), Constant.FORMAT_BOOK_DATE)); | |||||
| BookRepository.getInstance() | |||||
| .saveCollBookWithAsync(mCollBook); | |||||
| exit(); | |||||
| }) | |||||
| .setNegativeButton("取消", (dialog, which) -> { | |||||
| exit(); | |||||
| }).create(); | |||||
| alertDialog.show(); | |||||
| } else { | |||||
| exit(); | |||||
| } | |||||
| } | |||||
| // 退出 | |||||
| private void exit() { | |||||
| // 退出 | |||||
| super.onBackPressed(); | |||||
| } | |||||
| @Override | |||||
| protected void onStart() { | |||||
| super.onStart(); | |||||
| registerBrightObserver(); | |||||
| } | |||||
| @Override | |||||
| protected void onResume() { | |||||
| super.onResume(); | |||||
| if (mWakeLock != null) { | |||||
| mWakeLock.acquire(); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| protected void onPause() { | |||||
| super.onPause(); | |||||
| if (mWakeLock != null) { | |||||
| mWakeLock.release(); | |||||
| } | |||||
| if (mPageLoader != null) { | |||||
| saveBookInfo(); | |||||
| mPageLoader.saveRecord(); | |||||
| } | |||||
| if (getMPresenter() != null && mPageLoader != null) { | |||||
| float currProgress = Float.parseFloat(mPageLoader.getPercent()); | |||||
| if (currProgress > lastProgress) { | |||||
| getMPresenter().updateReadProgress(mRealBookId, mReadTaskId, String.valueOf(mPageLoader.getPercent())); | |||||
| } | |||||
| } | |||||
| } | |||||
| @Override | |||||
| protected void onStop() { | |||||
| super.onStop(); | |||||
| unregisterBrightObserver(); | |||||
| } | |||||
| @Override | |||||
| protected void onDestroy() { | |||||
| super.onDestroy(); | |||||
| unregisterReceiver(mReceiver); | |||||
| mHandler.removeMessages(WHAT_CATEGORY); | |||||
| mHandler.removeMessages(WHAT_CHAPTER); | |||||
| mPageLoader.closeBook(); | |||||
| mPageLoader = null; | |||||
| } | |||||
| @Override | |||||
| public boolean onKeyDown(int keyCode, KeyEvent event) { | |||||
| boolean isVolumeTurnPage = ReadSettingManager | |||||
| .getInstance().isVolumeTurnPage(); | |||||
| switch (keyCode) { | |||||
| case KeyEvent.KEYCODE_VOLUME_UP: | |||||
| if (isVolumeTurnPage) { | |||||
| return mPageLoader.skipToPrePage(); | |||||
| } | |||||
| break; | |||||
| case KeyEvent.KEYCODE_VOLUME_DOWN: | |||||
| if (isVolumeTurnPage) { | |||||
| return mPageLoader.skipToNextPage(); | |||||
| } | |||||
| break; | |||||
| } | |||||
| return super.onKeyDown(keyCode, event); | |||||
| } | |||||
| @Override | |||||
| protected void onActivityResult(int requestCode, int resultCode, Intent data) { | |||||
| super.onActivityResult(requestCode, resultCode, data); | |||||
| if (requestCode == REQUEST_MORE_SETTING) { | |||||
| boolean fullScreen = ReadSettingManager.getInstance().isFullScreen(); | |||||
| if (isFullScreen != fullScreen) { | |||||
| isFullScreen = fullScreen; | |||||
| // 刷新BottomMenu | |||||
| initBottomMenu(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public void onProgressSuccess(float progress) { | |||||
| lastProgress = progress; | |||||
| } | |||||
| } | |||||
| @@ -1,19 +0,0 @@ | |||||
| package com.yzx.webebook.activity | |||||
| import androidx.appcompat.app.AppCompatActivity | |||||
| import android.os.Bundle | |||||
| import com.yzx.webebook.activity.base.BaseWeexActivity | |||||
| class WeexTestActivity : BaseWeexActivity() { | |||||
| override fun initView() { | |||||
| } | |||||
| override fun initData() { | |||||
| val url = intent.getStringExtra("url") ?: "" | |||||
| val params = intent.getStringExtra("params") ?: "" | |||||
| setUrlInfo(url, "RaderPage", params) | |||||
| } | |||||
| } | |||||
| @@ -1,201 +0,0 @@ | |||||
| package com.yzx.webebook.activity.base | |||||
| import android.annotation.SuppressLint | |||||
| import android.os.Bundle | |||||
| import android.os.Handler | |||||
| import android.os.Message | |||||
| import android.util.Log | |||||
| import android.view.View | |||||
| import androidx.appcompat.app.AppCompatActivity | |||||
| import com.gyf.immersionbar.ktx.immersionBar | |||||
| import com.yzx.webebook.R | |||||
| import com.yzx.webebook.modules.ActivityWXModule | |||||
| import com.yzx.webebook.utils.StringUtils | |||||
| import kotlinx.android.synthetic.main.activity_base_weex.* | |||||
| import org.apache.weex.IWXRenderListener | |||||
| import org.apache.weex.WXSDKEngine | |||||
| import org.apache.weex.WXSDKInstance | |||||
| import org.apache.weex.common.WXRenderStrategy | |||||
| import org.apache.weex.utils.WXFileUtils | |||||
| /** | |||||
| * 类名:BaseActivity | |||||
| * 作者:Yun.Lei | |||||
| * 功能: | |||||
| * 创建日期:2020年5月6日14:27:04 | |||||
| * 修改人: | |||||
| * 修改时间: | |||||
| * 修改备注: | |||||
| */ | |||||
| abstract class BaseWeexActivity : AppCompatActivity(), IWXRenderListener { | |||||
| /** | |||||
| * 初始化视图操作在这里执行,执行时机为onCreate之后 | |||||
| */ | |||||
| abstract fun initView(): Unit | |||||
| /** | |||||
| * 数据初始化在这里执行,执行时机为initView之后 | |||||
| */ | |||||
| abstract fun initData(): Unit | |||||
| var mWXSDKInstance: WXSDKInstance? = null | |||||
| var pageName: String = "WeexPage" | |||||
| var bundleUrl: String = "" | |||||
| var params: String = "" | |||||
| private val handler: Handler = @SuppressLint("HandlerLeak") | |||||
| object : Handler() { | |||||
| override fun handleMessage(msg: Message) { | |||||
| super.handleMessage(msg) | |||||
| /** | |||||
| * 轮询访问 WXSDKEngine 初始化状态 防止异步造成的初始化失败问题 | |||||
| */ | |||||
| if (msg.what == 1) { | |||||
| Log.i( | |||||
| "welog", | |||||
| "WXSDKEngine.isInitializedActivity: " + WXSDKEngine.isInitialized() | |||||
| ) | |||||
| //&& !StringUtils.isEmpty(pageName) && !StringUtils.isEmpty( bundleUrl) | |||||
| if (WXSDKEngine.isInitialized()) { | |||||
| startRender() | |||||
| } else { | |||||
| sendEmptyMessageDelayed(1, 300) | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| override fun onCreate(savedInstanceState: Bundle?) { | |||||
| super.onCreate(savedInstanceState) | |||||
| setContentView(R.layout.activity_base_weex) | |||||
| initView() | |||||
| initData() | |||||
| setStatusBar() | |||||
| mWXSDKInstance = WXSDKInstance(this) | |||||
| mWXSDKInstance!!.registerRenderListener(this) | |||||
| startRender() | |||||
| if (WXSDKEngine.isInitialized()) { | |||||
| } else { | |||||
| handler.sendEmptyMessageDelayed(1, 300) | |||||
| } | |||||
| } | |||||
| /** | |||||
| * WXSDKEngine 初始化成功后 开始渲染 | |||||
| */ | |||||
| private fun startRender() { | |||||
| /** | |||||
| * 防止空指针 | |||||
| */ | |||||
| if (mWXSDKInstance == null) { | |||||
| mWXSDKInstance = WXSDKInstance(this) | |||||
| mWXSDKInstance!!.registerRenderListener(this) | |||||
| } | |||||
| /** | |||||
| * 渲染远程js | |||||
| */ | |||||
| // bundleUrl = "http://dotwe.org/raw/dist/38e202c16bdfefbdb88a8754f975454c.bundle.wx"; | |||||
| try { | |||||
| Log.d("welog", "开始加载") | |||||
| bundleUrl = "https://oa.live.educlouddata.com/index.js"; | |||||
| mWXSDKInstance?.renderByUrl("https://oa.live.educlouddata.com", bundleUrl, null, null, WXRenderStrategy.APPEND_ASYNC) | |||||
| Log.d("welog", "加载中") | |||||
| }catch (e:Exception){ | |||||
| Log.d("welog", "加载失败,$e") | |||||
| } | |||||
| /** | |||||
| * 渲染本地js | |||||
| */ | |||||
| // val options = mapOf("params" to this.params) | |||||
| // Log.d("welog", "startRender: $options") | |||||
| // mWXSDKInstance!!.render( | |||||
| // pageName, | |||||
| // WXFileUtils.loadAsset(bundleUrl, this), | |||||
| // options, | |||||
| // null, | |||||
| // WXRenderStrategy.APPEND_ASYNC | |||||
| // ) | |||||
| } | |||||
| fun setUrlInfo(url: String, pageName: String, params: String = "") { | |||||
| this.pageName = pageName | |||||
| this.bundleUrl = url | |||||
| this.params = params | |||||
| } | |||||
| open fun setStatusBar() { | |||||
| immersionBar { | |||||
| statusBarColor(R.color.white) | |||||
| fitsSystemWindows(true) | |||||
| statusBarDarkFont(true, 0.2f) | |||||
| keyboardEnable(true) | |||||
| init() | |||||
| } | |||||
| btnBack.setOnClickListener { onBackPressed() } | |||||
| btnClose.setOnClickListener { | |||||
| finish() | |||||
| } | |||||
| } | |||||
| override fun onViewCreated(instance: WXSDKInstance?, view: View) { | |||||
| Log.d("welog", "onViewCreated:") | |||||
| if (view.parent == null) { | |||||
| webLayout.addView(view); | |||||
| } | |||||
| webLayout.requestLayout(); | |||||
| } | |||||
| override fun onRenderSuccess(instance: WXSDKInstance?, width: Int, height: Int) { | |||||
| Log.d("welog", "onRenderSuccess:") | |||||
| } | |||||
| override fun onRefreshSuccess(instance: WXSDKInstance?, width: Int, height: Int) { | |||||
| Log.d("welog", "onRefreshSuccess:") | |||||
| } | |||||
| override fun onException(instance: WXSDKInstance?, errCode: String?, msg: String?) { | |||||
| Log.d("welog", "onException: $errCode//$msg") | |||||
| handler.sendEmptyMessageDelayed(1, 300) | |||||
| } | |||||
| override fun onResume() { | |||||
| super.onResume() | |||||
| if (mWXSDKInstance != null) { | |||||
| mWXSDKInstance!!.onActivityResume() | |||||
| } | |||||
| } | |||||
| override fun onPause() { | |||||
| super.onPause() | |||||
| if (mWXSDKInstance != null) { | |||||
| mWXSDKInstance!!.onActivityPause() | |||||
| } | |||||
| } | |||||
| override fun onStop() { | |||||
| super.onStop() | |||||
| if (mWXSDKInstance != null) { | |||||
| mWXSDKInstance!!.onActivityStop() | |||||
| } | |||||
| } | |||||
| override fun onBackPressed() { | |||||
| super.onBackPressed() | |||||
| } | |||||
| override fun onDestroy() { | |||||
| super.onDestroy() | |||||
| if (mWXSDKInstance != null) { | |||||
| mWXSDKInstance!!.onActivityDestroy() | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,38 +0,0 @@ | |||||
| package com.yzx.webebook.adapter; | |||||
| import android.view.View; | |||||
| import android.view.ViewGroup; | |||||
| import com.yzx.webebook.adapter.base.EasyAdapter; | |||||
| import com.yzx.webebook.adapter.base.IViewHolder; | |||||
| import com.yzx.webebook.widget.page.TxtChapter; | |||||
| /** | |||||
| * Created by newbiechen on 17-6-5. | |||||
| */ | |||||
| public class CategoryAdapter extends EasyAdapter<TxtChapter> { | |||||
| private int currentSelected = 0; | |||||
| @Override | |||||
| protected IViewHolder<TxtChapter> onCreateViewHolder(int viewType) { | |||||
| return new CategoryHolder(); | |||||
| } | |||||
| @Override | |||||
| public View getView(int position, View convertView, ViewGroup parent) { | |||||
| View view = super.getView(position, convertView, parent); | |||||
| CategoryHolder holder = (CategoryHolder) view.getTag(); | |||||
| if (position == currentSelected){ | |||||
| holder.setSelectedChapter(); | |||||
| } | |||||
| return view; | |||||
| } | |||||
| public void setChapter(int pos){ | |||||
| currentSelected = pos; | |||||
| notifyDataSetChanged(); | |||||
| } | |||||
| } | |||||
| @@ -1,63 +0,0 @@ | |||||
| package com.yzx.webebook.adapter; | |||||
| import android.graphics.drawable.Drawable; | |||||
| import android.widget.TextView; | |||||
| import androidx.core.content.ContextCompat; | |||||
| import com.yzx.webebook.R; | |||||
| import com.yzx.webebook.adapter.base.ViewHolderImpl; | |||||
| import com.yzx.webebook.utils.BookManager; | |||||
| import com.yzx.webebook.widget.page.TxtChapter; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-16. | |||||
| */ | |||||
| public class CategoryHolder extends ViewHolderImpl<TxtChapter> { | |||||
| private TextView mTvChapter; | |||||
| @Override | |||||
| public void initView() { | |||||
| mTvChapter = findById(R.id.category_tv_chapter); | |||||
| } | |||||
| @Override | |||||
| public void onBind(TxtChapter value, int pos){ | |||||
| //首先判断是否该章已下载 | |||||
| Drawable drawable = null; | |||||
| //TODO:目录显示设计的有点不好,需要靠成员变量是否为null来判断。 | |||||
| //如果没有链接地址表示是本地文件 | |||||
| if (value.getLink() == null){ | |||||
| drawable = ContextCompat.getDrawable(getContext(),R.drawable.selector_category_load); | |||||
| } | |||||
| else { | |||||
| if (value.getBookId() != null | |||||
| && BookManager | |||||
| .isChapterCached(value.getBookId(),value.getTitle())){ | |||||
| drawable = ContextCompat.getDrawable(getContext(),R.drawable.selector_category_load); | |||||
| } | |||||
| else { | |||||
| drawable = ContextCompat.getDrawable(getContext(), R.drawable.selector_category_unload); | |||||
| } | |||||
| } | |||||
| mTvChapter.setSelected(false); | |||||
| mTvChapter.setTextColor(ContextCompat.getColor(getContext(),R.color.nb_text_default)); | |||||
| mTvChapter.setCompoundDrawablesWithIntrinsicBounds(drawable,null,null,null); | |||||
| mTvChapter.setText(value.getTitle()); | |||||
| } | |||||
| @Override | |||||
| protected int getItemLayoutId() { | |||||
| return R.layout.item_category; | |||||
| } | |||||
| public void setSelectedChapter(){ | |||||
| mTvChapter.setTextColor(ContextCompat.getColor(getContext(),R.color.light_red)); | |||||
| mTvChapter.setSelected(true); | |||||
| } | |||||
| } | |||||
| @@ -1,21 +0,0 @@ | |||||
| package com.yzx.webebook.adapter | |||||
| import android.widget.ImageView | |||||
| import com.bumptech.glide.Glide | |||||
| import org.apache.weex.WXEnvironment | |||||
| import org.apache.weex.adapter.IWXImgLoaderAdapter | |||||
| import org.apache.weex.common.WXImageStrategy | |||||
| import org.apache.weex.dom.WXImageQuality | |||||
| class ImageAdapter:IWXImgLoaderAdapter { | |||||
| override fun setImage( | |||||
| url: String?, | |||||
| view: ImageView?, | |||||
| quality: WXImageQuality?, | |||||
| strategy: WXImageStrategy? | |||||
| ) { | |||||
| Glide.with(WXEnvironment.sApplication) | |||||
| .load(url) | |||||
| .into(view!!) | |||||
| } | |||||
| } | |||||
| @@ -1,46 +0,0 @@ | |||||
| package com.yzx.webebook.adapter; | |||||
| import android.graphics.drawable.Drawable; | |||||
| import android.view.View; | |||||
| import androidx.recyclerview.widget.RecyclerView; | |||||
| import com.yzx.webebook.adapter.base.BaseListAdapter; | |||||
| import com.yzx.webebook.adapter.base.BaseViewHolder; | |||||
| import com.yzx.webebook.adapter.base.IViewHolder; | |||||
| import com.yzx.webebook.widget.page.PageStyle; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-19. | |||||
| */ | |||||
| public class PageStyleAdapter extends BaseListAdapter<Drawable> { | |||||
| private int currentChecked; | |||||
| @Override | |||||
| protected IViewHolder<Drawable> createViewHolder(int viewType) { | |||||
| return new PageStyleHolder(); | |||||
| } | |||||
| @Override | |||||
| public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { | |||||
| super.onBindViewHolder(holder, position); | |||||
| IViewHolder iHolder = ((BaseViewHolder) holder).holder; | |||||
| PageStyleHolder pageStyleHolder = (PageStyleHolder) iHolder; | |||||
| if (currentChecked == position){ | |||||
| pageStyleHolder.setChecked(); | |||||
| } | |||||
| } | |||||
| public void setPageStyleChecked(PageStyle pageStyle){ | |||||
| currentChecked = pageStyle.ordinal(); | |||||
| } | |||||
| @Override | |||||
| protected void onItemClick(View v, int pos) { | |||||
| super.onItemClick(v, pos); | |||||
| currentChecked = pos; | |||||
| notifyDataSetChanged(); | |||||
| } | |||||
| } | |||||
| @@ -1,40 +0,0 @@ | |||||
| package com.yzx.webebook.adapter; | |||||
| import android.graphics.drawable.Drawable; | |||||
| import android.view.View; | |||||
| import android.widget.ImageView; | |||||
| import com.yzx.webebook.R; | |||||
| import com.yzx.webebook.adapter.base.ViewHolderImpl; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-19. | |||||
| */ | |||||
| public class PageStyleHolder extends ViewHolderImpl<Drawable> { | |||||
| private View mReadBg; | |||||
| private ImageView mIvChecked; | |||||
| @Override | |||||
| public void initView() { | |||||
| mReadBg = findById(R.id.read_bg_view); | |||||
| mIvChecked = findById(R.id.read_bg_iv_checked); | |||||
| } | |||||
| @Override | |||||
| public void onBind(Drawable data, int pos) { | |||||
| mReadBg.setBackground(data); | |||||
| mIvChecked.setVisibility(View.GONE); | |||||
| } | |||||
| @Override | |||||
| protected int getItemLayoutId() { | |||||
| return R.layout.item_read_bg; | |||||
| } | |||||
| public void setChecked(){ | |||||
| mIvChecked.setVisibility(View.VISIBLE); | |||||
| } | |||||
| } | |||||
| @@ -1,116 +0,0 @@ | |||||
| package com.yzx.webebook.model.bean; | |||||
| import org.greenrobot.greendao.annotation.Entity; | |||||
| import org.greenrobot.greendao.annotation.Generated; | |||||
| import org.greenrobot.greendao.annotation.Id; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-20. | |||||
| * 作者 | |||||
| */ | |||||
| @Entity | |||||
| public class AuthorBean { | |||||
| /** | |||||
| * _id : 553136ba70feaa764a096f6f | |||||
| * avatar : /avatar/26/eb/26ebf8ede76d7f52cd377960bd66383b | |||||
| * nickname : 九歌 | |||||
| * activityAvatar : | |||||
| * type : normal | |||||
| * lv : 8 | |||||
| * gender : female | |||||
| */ | |||||
| @Id | |||||
| private String _id; | |||||
| private String avatar; | |||||
| private String nickname; | |||||
| private String activityAvatar; | |||||
| private String type; | |||||
| private int lv; | |||||
| private String gender; | |||||
| @Generated(hash = 1152582024) | |||||
| public AuthorBean(String _id, String avatar, String nickname, | |||||
| String activityAvatar, String type, int lv, String gender) { | |||||
| this._id = _id; | |||||
| this.avatar = avatar; | |||||
| this.nickname = nickname; | |||||
| this.activityAvatar = activityAvatar; | |||||
| this.type = type; | |||||
| this.lv = lv; | |||||
| this.gender = gender; | |||||
| } | |||||
| @Generated(hash = 1694633584) | |||||
| public AuthorBean() { | |||||
| } | |||||
| public String get_id() { | |||||
| return _id; | |||||
| } | |||||
| public void set_id(String _id) { | |||||
| this._id = _id; | |||||
| } | |||||
| public String getAvatar() { | |||||
| return avatar; | |||||
| } | |||||
| public void setAvatar(String avatar) { | |||||
| this.avatar = avatar; | |||||
| } | |||||
| public String getNickname() { | |||||
| return nickname; | |||||
| } | |||||
| public void setNickname(String nickname) { | |||||
| this.nickname = nickname; | |||||
| } | |||||
| public String getActivityAvatar() { | |||||
| return activityAvatar; | |||||
| } | |||||
| public void setActivityAvatar(String activityAvatar) { | |||||
| this.activityAvatar = activityAvatar; | |||||
| } | |||||
| public String getType() { | |||||
| return type; | |||||
| } | |||||
| public void setType(String type) { | |||||
| this.type = type; | |||||
| } | |||||
| public int getLv() { | |||||
| return lv; | |||||
| } | |||||
| public void setLv(int lv) { | |||||
| this.lv = lv; | |||||
| } | |||||
| public String getGender() { | |||||
| return gender; | |||||
| } | |||||
| public void setGender(String gender) { | |||||
| this.gender = gender; | |||||
| } | |||||
| @Override | |||||
| public String toString() { | |||||
| return "AuthorBean{" + | |||||
| "_id='" + _id + '\'' + | |||||
| ", avatar='" + avatar + '\'' + | |||||
| ", nickname='" + nickname + '\'' + | |||||
| ", activityAvatar='" + activityAvatar + '\'' + | |||||
| ", type='" + type + '\'' + | |||||
| ", lv=" + lv + | |||||
| ", gender='" + gender + '\'' + | |||||
| '}'; | |||||
| } | |||||
| } | |||||
| @@ -1,146 +0,0 @@ | |||||
| package com.yzx.webebook.model.bean; | |||||
| import org.greenrobot.greendao.annotation.Entity; | |||||
| import org.greenrobot.greendao.annotation.Generated; | |||||
| import org.greenrobot.greendao.annotation.Id; | |||||
| import org.greenrobot.greendao.annotation.Index; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-10. | |||||
| * 书的章节链接(作为下载的进度数据) | |||||
| * 同时作为网络章节和本地章节 (没有找到更好分离两者的办法) | |||||
| */ | |||||
| @Entity | |||||
| public class BookChapterBean implements Serializable{ | |||||
| private static final long serialVersionUID = 56423411313L; | |||||
| /** | |||||
| * title : 第一章 他叫白小纯 | |||||
| * link : http://read.qidian.com/chapter/rJgN8tJ_cVdRGoWu-UQg7Q2/6jr-buLIUJSaGfXRMrUjdw2 | |||||
| * unreadble : false | |||||
| */ | |||||
| @Id | |||||
| private String id; | |||||
| private String link; | |||||
| private String title; | |||||
| //所属的下载任务 | |||||
| private String taskName; | |||||
| private boolean unreadble; | |||||
| //所属的书籍 | |||||
| @Index | |||||
| private String bookId; | |||||
| //本地书籍参数 | |||||
| //在书籍文件中的起始位置 | |||||
| private long start; | |||||
| //在书籍文件中的终止位置 | |||||
| private long end; | |||||
| @Generated(hash = 1508543635) | |||||
| public BookChapterBean(String id, String link, String title, String taskName, | |||||
| boolean unreadble, String bookId, long start, long end) { | |||||
| this.id = id; | |||||
| this.link = link; | |||||
| this.title = title; | |||||
| this.taskName = taskName; | |||||
| this.unreadble = unreadble; | |||||
| this.bookId = bookId; | |||||
| this.start = start; | |||||
| this.end = end; | |||||
| } | |||||
| @Generated(hash = 853839616) | |||||
| public BookChapterBean() { | |||||
| } | |||||
| public String getTitle() { | |||||
| return title; | |||||
| } | |||||
| public void setTitle(String title) { | |||||
| this.title = title; | |||||
| } | |||||
| public String getLink() { | |||||
| return link; | |||||
| } | |||||
| public void setLink(String link) { | |||||
| this.link = link; | |||||
| } | |||||
| public boolean isUnreadble() { | |||||
| return unreadble; | |||||
| } | |||||
| public void setUnreadble(boolean unreadble) { | |||||
| this.unreadble = unreadble; | |||||
| } | |||||
| public String getTaskName() { | |||||
| return taskName; | |||||
| } | |||||
| public void setTaskName(String taskName) { | |||||
| this.taskName = taskName; | |||||
| } | |||||
| public boolean getUnreadble() { | |||||
| return this.unreadble; | |||||
| } | |||||
| public String getBookId() { | |||||
| return bookId; | |||||
| } | |||||
| public void setBookId(String bookId) { | |||||
| this.bookId = bookId; | |||||
| } | |||||
| public String getId() { | |||||
| return id; | |||||
| } | |||||
| public void setId(String id) { | |||||
| this.id = id; | |||||
| } | |||||
| public long getStart() { | |||||
| return start; | |||||
| } | |||||
| public void setStart(long start) { | |||||
| this.start = start; | |||||
| } | |||||
| public long getEnd() { | |||||
| return end; | |||||
| } | |||||
| public void setEnd(long end) { | |||||
| this.end = end; | |||||
| } | |||||
| @Override | |||||
| public String toString() { | |||||
| return "BookChapterBean{" + | |||||
| "id='" + id + '\'' + | |||||
| ", link='" + link + '\'' + | |||||
| ", title='" + title + '\'' + | |||||
| ", taskName='" + taskName + '\'' + | |||||
| ", unreadble=" + unreadble + | |||||
| ", bookId='" + bookId + '\'' + | |||||
| ", start=" + start + | |||||
| ", end=" + end + | |||||
| '}'; | |||||
| } | |||||
| } | |||||
| @@ -1,38 +0,0 @@ | |||||
| package com.yzx.webebook.model.bean; | |||||
| import org.greenrobot.greendao.annotation.Entity; | |||||
| import org.greenrobot.greendao.annotation.Id; | |||||
| import org.greenrobot.greendao.annotation.Generated; | |||||
| @Entity | |||||
| public class BookCount { | |||||
| @Id | |||||
| private String _id; // 本地书籍中,path 的 md5 值作为本地书籍的 id | |||||
| private int total; | |||||
| @Generated(hash = 433479827) | |||||
| public BookCount(String _id, int total) { | |||||
| this._id = _id; | |||||
| this.total = total; | |||||
| } | |||||
| @Generated(hash = 2056164259) | |||||
| public BookCount() { | |||||
| } | |||||
| public int getTotal() { | |||||
| return total; | |||||
| } | |||||
| public String get_id() { | |||||
| return _id; | |||||
| } | |||||
| public void set_id(String _id) { | |||||
| this._id = _id; | |||||
| } | |||||
| public void setTotal(int total) { | |||||
| this.total = total; | |||||
| } | |||||
| } | |||||
| @@ -1,54 +0,0 @@ | |||||
| package com.yzx.webebook.model.bean; | |||||
| import org.greenrobot.greendao.annotation.Entity; | |||||
| import org.greenrobot.greendao.annotation.Generated; | |||||
| import org.greenrobot.greendao.annotation.Id; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-20. | |||||
| */ | |||||
| @Entity | |||||
| public class BookRecordBean { | |||||
| //所属的书的id | |||||
| @Id | |||||
| private String bookId; | |||||
| //阅读到了第几章 | |||||
| private int chapter; | |||||
| //当前的页码 | |||||
| private int pagePos; | |||||
| @Generated(hash = 340380968) | |||||
| public BookRecordBean(String bookId, int chapter, int pagePos) { | |||||
| this.bookId = bookId; | |||||
| this.chapter = chapter; | |||||
| this.pagePos = pagePos; | |||||
| } | |||||
| @Generated(hash = 398068002) | |||||
| public BookRecordBean() { | |||||
| } | |||||
| public String getBookId() { | |||||
| return bookId; | |||||
| } | |||||
| public void setBookId(String bookId) { | |||||
| this.bookId = bookId; | |||||
| } | |||||
| public int getChapter() { | |||||
| return chapter; | |||||
| } | |||||
| public void setChapter(int chapter) { | |||||
| this.chapter = chapter; | |||||
| } | |||||
| public int getPagePos() { | |||||
| return pagePos; | |||||
| } | |||||
| public void setPagePos(int pagePos) { | |||||
| this.pagePos = pagePos; | |||||
| } | |||||
| } | |||||
| @@ -1,89 +0,0 @@ | |||||
| package com.yzx.webebook.model.bean; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-10. | |||||
| */ | |||||
| public class ChapterInfoBean { | |||||
| /** | |||||
| * title : 第一章 他叫白小纯 | |||||
| * body : 帽儿山,位于东林山脉中,山下有一个村子,民风淳朴,以耕田为生,与世隔绝。 | |||||
| 清晨,村庄的大门前,整个村子里的乡亲,正为一个十五六岁少年送别,这少年瘦弱,但却白白净净,看起来很是乖巧,衣着尽管是寻常的青衫,可却洗的泛白,穿在这少年的身上,与他目中的纯净搭配在一起,透出一股子灵动。 | |||||
| 他叫白小纯。 | |||||
| “父老乡亲们,我要去修仙了,可我舍不得你们啊。”少年满脸不舍,原本就乖巧的样子,此刻看起来更为纯朴。 | |||||
| 四周的乡亲,面面相觑,顿时摆出难舍之色。 | |||||
| “小纯,你爹娘走的早,你是个……好孩子!!难道你不想长生了么,成为仙人就可以长生,能活的很久很久,走吧,雏鹰长大,总有飞出去的那一天。”人群内走出一个头发花白的老者,说道好孩子三个字时,他顿了一下。 | |||||
| “在外面遇到任何事情,都要坚持下去,走出村子,就不要回来,因为你的路在前方!”老人神色慈祥,拍了拍少年的肩膀。 | |||||
| “长生……”白小纯身体一震,目中慢慢坚定起来,在老者以及四周乡亲鼓励的目光下,他重重的点了点头,深深的看了一眼四周的乡亲,转身迈着大步,渐渐走出了村子。 | |||||
| 眼看少年的身影远去,村中的众人,一个个都激动起来,目中的难舍刹那就被喜悦代替,那之前满脸慈祥的老者,此刻也在颤抖,眼中流下泪水。 | |||||
| “苍天有眼,这白鼠狼,他终于……终于走了,是谁告诉他在附近看到仙人的,你为村子立下了大功!” | |||||
| “这白鼠狼终于肯离开了,可怜我家的几只鸡,就因为这白鼠狼怕鸡打鸣,不知用了什么方法,唆使一群孩子吃鸡肉,把全村的鸡都给吃的干干净净……” | |||||
| “今天过年了!”欢呼之声,立刻在这不大的村子里,沸腾而起,甚至有人拿出了锣鼓,高兴的敲打起来。 | |||||
| 村子外,白小纯还没等走远,他就听到了身后村子内,传出了敲锣打鼓的声音,还夹着欢呼。 | |||||
| 白小纯脚步一顿,神色有些古怪,干咳一声,伴随着耳边传来的锣鼓,白小纯顺着山路,走上了帽儿山。 | |||||
| 这帽儿山虽不高,却灌木杂多,虽是清晨,可看起来也是黑压压一片,很是安静。 | |||||
| “听二狗说,他前几天在这里被一头野猪追赶时,看到天上有仙人飞过……”白小纯走在山路上,心脏怦怦跳动时,忽然一旁的灌林中传来阵阵哗哗声,似野猪一样,这声音来的突然,让本就紧张的白小纯,顿时背后发凉。 | |||||
| “谁,谁在那里!”白小纯右手快速从行囊中拿出四把斧头,六把柴刀,还觉得不放心,又从怀里取出了一小根黑色的香,死死的抓住。 | |||||
| “别出来,千万别出来,我有斧头,有柴刀,手里的香还可以召唤天雷,能引仙人降临,你敢出来,就劈死你!”白小纯哆嗦的大喊,连滚带爬的夹着那些武器,赶紧顺着山路跑去,沿途叮当乱响,斧头柴刀掉了一地。 | |||||
| 或许是真的被他给吓住了,很快的哗哗声就消失,没有什么野兽跑出来,白小纯面色苍白,擦了擦冷汗,有心放弃继续上山,可一想到手中这根香是他爹娘去世前留给他的,据说是祖上曾偶然的救下一个落魄的仙人,那仙人离去时留下这根香作为报答,曾言会收下白家血脉一人为弟子,只要点燃,仙人就会到来。 | |||||
| 可至今为止,这根香他点过十多次,始终不见仙人到来,让白小纯开始怀疑仙人是不是真的会来,这一次之所以下定决心,一方面是香所剩不多,另一方面是他听村子里人说,头几天在这看到有仙人从天上飞过。 | |||||
| 所以他这才到来,想着距离仙人近一些,或许仙人就察觉到了也说不定。 | |||||
| 踌躇一番,白小纯咬牙继续,好在此山不高,不久他气喘吁吁的到了山顶,站在那里,他遥望山下的村庄,神色颇为感慨,又低头看着手中的只有指甲盖大小的黑香,此香似乎被燃烧了好多次,所剩不多。 | |||||
| “三年了,爹娘保佑我,这次一定要成功!”白小纯深吸口气,小心的将香点燃,立刻四周狂风顿起,天空更是眨眼间乌云密布,一道道闪电划过,还有震耳欲聋的雷鸣在白小纯耳边直接炸开。 | |||||
| 声音之大,气势之强,让白小纯身体哆嗦,有种随时会被雷劈死的感觉,下意识的就想要吐口唾沫将那根香灭掉,但却挣扎忍住。 | |||||
| “三年了,我点这根香点了十二次,这是第十三次,这次一定要忍住,小纯不怕,应该不会被劈死……”白小纯想起了这三年的经历,不算这次,点了十二次,每次都是这样的雷鸣闪电,仙人也没有到来,吓的本就怕死的他每次都吐口唾沫将其熄灭,说来也怪,这根香看似不凡,可实际上一样是浇水就灭。 | |||||
| 在白小纯这里心惊肉跳,艰难的于那雷声中等待时,距离这里不远处的天空上,有一道长虹正急速的呼啸而来。 | |||||
| 长虹内是一个中年男子,这男子衣着华丽,仙风道骨,可偏偏风尘仆仆,甚至仔细去看,可以看到他神色内深深的疲惫。 | |||||
| “我倒要看看,到底是个什么样的人,竟然点根香点了三年!” | |||||
| 一想到自己这三年的经历,中年男子就气恼,三年前他察觉有人点燃自己还是凝气时送出的香药,想起了当年在凡俗中的一段人情。 | |||||
| 这才飞出寻来,原本按照他的打算,很快就会回来,可没成想,刚寻着香气过去,还没等多远,那气息就瞬间消失,断了联系。若是一次也就罢了,这三年,气息出现了十多次。 | |||||
| 使得他这里,多次在寻找时中断,就这样来来回回,折腾了三年…… | |||||
| 此刻他遥遥的看到了帽儿山,看到了山顶上白小纯,气不打一处来,一瞬飞出,直接就站在了山顶,大手一挥,那根所剩不多的香,直接熄灭。 | |||||
| 雷声刹那消失,白小纯愣了一下,抬头一看,看到了自己的身边多了一个中年男子。 | |||||
| “仙人?”白小纯小心翼翼的开口,有些拿不准,背后偷偷捡起一把斧头。 | |||||
| “本座李青候,你是白家后人?”中年修士目光如电,无视白小纯身后的斧子,打量了白小纯一番,觉得眼前此子眉清目秀,依稀与当年的故人相似,资质也不错,心底的恼意,也不由缓了一些。 | |||||
| “晚辈正是白家后人,白小纯。”白小纯眨了眨眼,小声说道,虽然心中有些畏惧,但还是挺了挺腰板。 | |||||
| “我问你,点一根香,为什么点了三年!”中年修士淡淡开口,问出了他这三年里,最想要知道的问题。 | |||||
| 白小纯听到这个问题,脑筋飞速转动,然后脸上摆出惆怅,遥望山下的村庄。 | |||||
| “晚辈是一个重情重义的人,舍不得那些乡亲们,每一次我点燃香,他们也都不舍得我离去,如今山下的他们,还在因为我的离去而悲伤呢。” | |||||
| 中年修士一愣,这个缘由,是他之前没想到的,目中的恼色又少了一些,单单从话语上看,此子的本性还是不错的。 | |||||
| 可当他的目光落在山下的村子时,他的神识随之扫过,听到了村子里的敲锣打鼓以及那一句句欢呼白鼠狼离去的话语,面色立刻难看起来,有些头疼,看着眼前这个外表乖巧纯朴,人畜无害的白小纯,已心底明朗对方实际上一肚子坏水。 | |||||
| “说实话!”中年修士一瞪眼,声音如同雷声一样,白小纯吓得一个哆嗦。 | |||||
| “这不怨我啊,你那什么破香啊,每次点燃都会打雷,好几次都差点劈死我,我躲过了十三次,已经很不容易了。”白小纯可怜兮兮的说道。 | |||||
| 中年修士看着白小纯,半晌无语。 | |||||
| “既然你这么害怕,为什么还要强行去点香十多次?”中年修士缓缓开口。 | |||||
| “我怕死啊,修仙不是能长生么,我想长生啊。”白小纯委屈的说道。 | |||||
| 中年修士再次无语,不过觉得此子总算执念可嘉,扔到门派里磨炼一番,或可在性子上改变一二。 | |||||
| 于是略一思索,大袖一甩卷着白小纯化作一道长虹,直奔天边而去。 | |||||
| “跟我走吧。” | |||||
| “去哪?这也太高了吧……”白小纯看到自己在天上飞,下面是万丈深渊,立刻脸色苍白,斧头一扔,死死的抱住仙人的大腿。 | |||||
| 中年修士看了眼自己的腿,无奈开口。 | |||||
| “灵溪宗。” | |||||
| 兄弟姐妹们,阔别2个月,你们想不想我啊,我非常想你们! | |||||
| 这本书,我做了详细的大纲,每次回顾大纲里的情节,都很兴奋,有种燃烧的感觉,我非常满意,明天,正式更新,依旧是中午一章,晚上一章! | |||||
| 很兴奋,我们已沉寂了数月,如今归来,要……再战起点! | |||||
| 新书期,兄弟姐妹,别忘了收藏与推荐啊,收藏与推荐至关重要! | |||||
| 求收藏!!求推荐!! | |||||
| 让众人知晓,我们……归来了! | |||||
| 我们的目标,依旧是……点击榜,推荐榜,第一! | |||||
| */ | |||||
| private String title; | |||||
| private String body; | |||||
| public String getTitle() { | |||||
| return title; | |||||
| } | |||||
| public void setTitle(String title) { | |||||
| this.title = title; | |||||
| } | |||||
| public String getBody() { | |||||
| return body; | |||||
| } | |||||
| public void setBody(String body) { | |||||
| this.body = body; | |||||
| } | |||||
| } | |||||
| @@ -1,52 +0,0 @@ | |||||
| package com.yzx.webebook.model.bean; | |||||
| import org.greenrobot.greendao.annotation.Entity; | |||||
| import org.greenrobot.greendao.annotation.Id; | |||||
| import org.greenrobot.greendao.annotation.Generated; | |||||
| import org.greenrobot.greendao.annotation.Index; | |||||
| @Entity | |||||
| public class ChapterPageCount { | |||||
| @Id | |||||
| private String _id; // 本地书籍中,path 的 md5 值作为本地书籍的 id | |||||
| private int total; | |||||
| @Index | |||||
| private String book_id; | |||||
| @Generated(hash = 774780221) | |||||
| public ChapterPageCount(String _id, int total, String book_id) { | |||||
| this._id = _id; | |||||
| this.total = total; | |||||
| this.book_id = book_id; | |||||
| } | |||||
| @Generated(hash = 876465118) | |||||
| public ChapterPageCount() { | |||||
| } | |||||
| public void setTotal(int total) { | |||||
| this.total = total; | |||||
| } | |||||
| public void set_id(String _id) { | |||||
| this._id = _id; | |||||
| } | |||||
| public void setBook_id(String book_id) { | |||||
| this.book_id = book_id; | |||||
| } | |||||
| public int getTotal() { | |||||
| return total; | |||||
| } | |||||
| public String get_id() { | |||||
| return _id; | |||||
| } | |||||
| public String getBook_id() { | |||||
| return book_id; | |||||
| } | |||||
| } | |||||
| @@ -1,372 +0,0 @@ | |||||
| package com.yzx.webebook.model.bean; | |||||
| import android.os.Parcel; | |||||
| import android.os.Parcelable; | |||||
| import com.yzx.webebook.App; | |||||
| import com.yzx.webebook.utils.StringUtils; | |||||
| import org.greenrobot.greendao.DaoException; | |||||
| import org.greenrobot.greendao.annotation.Entity; | |||||
| import org.greenrobot.greendao.annotation.Generated; | |||||
| import org.greenrobot.greendao.annotation.Id; | |||||
| import org.greenrobot.greendao.annotation.ToMany; | |||||
| import java.util.List; | |||||
| import com.yzx.webebook.model.gen.DaoSession; | |||||
| import com.yzx.webebook.model.gen.BookChapterBeanDao; | |||||
| import com.yzx.webebook.model.gen.CollBookBeanDao; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-8. | |||||
| * 收藏的书籍 | |||||
| */ | |||||
| @Entity | |||||
| public class CollBookBean implements Parcelable{ | |||||
| public static final int STATUS_UNCACHE = 0; //未缓存 | |||||
| public static final int STATUS_CACHING = 1; //正在缓存 | |||||
| public static final int STATUS_CACHED = 2; //已经缓存 | |||||
| /** | |||||
| * _id : 53663ae356bdc93e49004474 | |||||
| * title : 逍遥派 | |||||
| * author : 白马出淤泥 | |||||
| * shortIntro : 金庸武侠中有不少的神秘高手,书中或提起名字,或不曾提起,总之他们要么留下了绝世秘笈,要么就名震武林。 独孤九剑的创始者,独孤求败,他真的只创出九剑吗? 残本葵花... | |||||
| * cover : /cover/149273897447137 | |||||
| * hasCp : true | |||||
| * latelyFollower : 60213 | |||||
| * retentionRatio : 22.87 | |||||
| * updated : 2017-05-07T18:24:34.720Z | |||||
| * | |||||
| * chaptersCount : 1660 | |||||
| * lastChapter : 第1659章 朱长老 | |||||
| */ | |||||
| @Id | |||||
| private String _id; // 本地书籍中,path 的 md5 值作为本地书籍的 id | |||||
| private String title; | |||||
| private String author; | |||||
| private String shortIntro; | |||||
| private String cover; // 在本地书籍中,该字段作为本地文件的路径 | |||||
| private boolean hasCp; | |||||
| private int latelyFollower; | |||||
| private double retentionRatio; | |||||
| //最新更新日期 | |||||
| private String updated; | |||||
| //最新阅读日期 | |||||
| private String lastRead; | |||||
| private int chaptersCount; | |||||
| private String lastChapter; | |||||
| //是否更新或未阅读 | |||||
| private boolean isUpdate = true; | |||||
| //是否是本地文件 | |||||
| private boolean isLocal = false; | |||||
| @ToMany(referencedJoinProperty = "bookId") | |||||
| private List<BookChapterBean> bookChapterList; | |||||
| /** Used to resolve relations */ | |||||
| @Generated(hash = 2040040024) | |||||
| private transient DaoSession daoSession; | |||||
| /** Used for active entity operations. */ | |||||
| @Generated(hash = 1552163441) | |||||
| private transient CollBookBeanDao myDao; | |||||
| @Generated(hash = 757968961) | |||||
| public CollBookBean(String _id, String title, String author, String shortIntro, String cover, | |||||
| boolean hasCp, int latelyFollower, double retentionRatio, String updated, String lastRead, | |||||
| int chaptersCount, String lastChapter, boolean isUpdate, boolean isLocal) { | |||||
| this._id = _id; | |||||
| this.title = title; | |||||
| this.author = author; | |||||
| this.shortIntro = shortIntro; | |||||
| this.cover = cover; | |||||
| this.hasCp = hasCp; | |||||
| this.latelyFollower = latelyFollower; | |||||
| this.retentionRatio = retentionRatio; | |||||
| this.updated = updated; | |||||
| this.lastRead = lastRead; | |||||
| this.chaptersCount = chaptersCount; | |||||
| this.lastChapter = lastChapter; | |||||
| this.isUpdate = isUpdate; | |||||
| this.isLocal = isLocal; | |||||
| } | |||||
| public CollBookBean() { | |||||
| } | |||||
| public String get_id() { | |||||
| return _id; | |||||
| } | |||||
| public void set_id(String _id) { | |||||
| this._id = _id; | |||||
| } | |||||
| public String getTitle() { | |||||
| return StringUtils.convertCC(title, App.Companion.getContext()); | |||||
| } | |||||
| public void setTitle(String title) { | |||||
| this.title = title; | |||||
| } | |||||
| public String getAuthor() { | |||||
| return StringUtils.convertCC(author, App.Companion.getContext()); | |||||
| } | |||||
| public void setAuthor(String author) { | |||||
| this.author = author; | |||||
| } | |||||
| public String getShortIntro() { | |||||
| return StringUtils.convertCC(shortIntro, App.Companion.getContext()); | |||||
| } | |||||
| public void setShortIntro(String shortIntro) { | |||||
| this.shortIntro = shortIntro; | |||||
| } | |||||
| public String getCover() { | |||||
| return StringUtils.convertCC(cover, App.Companion.getContext()); | |||||
| } | |||||
| public void setCover(String cover) { | |||||
| this.cover = cover; | |||||
| } | |||||
| public boolean isHasCp() { | |||||
| return hasCp; | |||||
| } | |||||
| public void setHasCp(boolean hasCp) { | |||||
| this.hasCp = hasCp; | |||||
| } | |||||
| public int getLatelyFollower() { | |||||
| return latelyFollower; | |||||
| } | |||||
| public void setLatelyFollower(int latelyFollower) { | |||||
| this.latelyFollower = latelyFollower; | |||||
| } | |||||
| public double getRetentionRatio() { | |||||
| return retentionRatio; | |||||
| } | |||||
| public void setRetentionRatio(double retentionRatio) { | |||||
| this.retentionRatio = retentionRatio; | |||||
| } | |||||
| public String getUpdated() { | |||||
| return StringUtils.convertCC(updated, App.Companion.getContext()); | |||||
| } | |||||
| public void setUpdated(String updated) { | |||||
| this.updated = updated; | |||||
| } | |||||
| public int getChaptersCount() { | |||||
| return chaptersCount; | |||||
| } | |||||
| public void setChaptersCount(int chaptersCount) { | |||||
| this.chaptersCount = chaptersCount; | |||||
| } | |||||
| public String getLastChapter() { | |||||
| return StringUtils.convertCC(lastChapter, App.Companion.getContext()); | |||||
| } | |||||
| public void setLastChapter(String lastChapter) { | |||||
| this.lastChapter = lastChapter; | |||||
| } | |||||
| public boolean isUpdate() { | |||||
| return isUpdate; | |||||
| } | |||||
| public void setUpdate(boolean update) { | |||||
| isUpdate = update; | |||||
| } | |||||
| public boolean getHasCp() { | |||||
| return this.hasCp; | |||||
| } | |||||
| public boolean getIsUpdate() { | |||||
| return this.isUpdate; | |||||
| } | |||||
| public void setIsUpdate(boolean isUpdate) { | |||||
| this.isUpdate = isUpdate; | |||||
| } | |||||
| public boolean isLocal() { | |||||
| return isLocal; | |||||
| } | |||||
| public void setLocal(boolean local) { | |||||
| isLocal = local; | |||||
| } | |||||
| public String getLastRead() { | |||||
| return StringUtils.convertCC(lastRead, App.Companion.getContext()); | |||||
| } | |||||
| public void setLastRead(String lastRead) { | |||||
| this.lastRead = lastRead; | |||||
| } | |||||
| public void setBookChapters(List<BookChapterBean> beans){ | |||||
| bookChapterList = beans; | |||||
| for (BookChapterBean bean : bookChapterList){ | |||||
| bean.setBookId(get_id()); | |||||
| } | |||||
| } | |||||
| public List<BookChapterBean> getBookChapters(){ | |||||
| if (daoSession == null){ | |||||
| return bookChapterList; | |||||
| } | |||||
| else { | |||||
| return getBookChapterList(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * To-many relationship, resolved on first access (and after reset). | |||||
| * Changes to to-many relations are not persisted, make changes to the target entity. | |||||
| */ | |||||
| @Generated(hash = 711740787) | |||||
| public List<BookChapterBean> getBookChapterList() { | |||||
| if (bookChapterList == null) { | |||||
| final DaoSession daoSession = this.daoSession; | |||||
| if (daoSession == null) { | |||||
| throw new DaoException("Entity is detached from DAO context"); | |||||
| } | |||||
| BookChapterBeanDao targetDao = daoSession.getBookChapterBeanDao(); | |||||
| List<BookChapterBean> bookChapterListNew = targetDao | |||||
| ._queryCollBookBean_BookChapterList(_id); | |||||
| synchronized (this) { | |||||
| if (bookChapterList == null) { | |||||
| bookChapterList = bookChapterListNew; | |||||
| } | |||||
| } | |||||
| } | |||||
| return bookChapterList; | |||||
| } | |||||
| /** Resets a to-many relationship, making the next get call to query for a fresh result. */ | |||||
| @Generated(hash = 1077762221) | |||||
| public synchronized void resetBookChapterList() { | |||||
| bookChapterList = null; | |||||
| } | |||||
| /** | |||||
| * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}. | |||||
| * Entity must attached to an entity context. | |||||
| */ | |||||
| @Generated(hash = 128553479) | |||||
| public void delete() { | |||||
| if (myDao == null) { | |||||
| throw new DaoException("Entity is detached from DAO context"); | |||||
| } | |||||
| myDao.delete(this); | |||||
| } | |||||
| /** | |||||
| * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}. | |||||
| * Entity must attached to an entity context. | |||||
| */ | |||||
| @Generated(hash = 1942392019) | |||||
| public void refresh() { | |||||
| if (myDao == null) { | |||||
| throw new DaoException("Entity is detached from DAO context"); | |||||
| } | |||||
| myDao.refresh(this); | |||||
| } | |||||
| /** | |||||
| * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}. | |||||
| * Entity must attached to an entity context. | |||||
| */ | |||||
| @Generated(hash = 713229351) | |||||
| public void update() { | |||||
| if (myDao == null) { | |||||
| throw new DaoException("Entity is detached from DAO context"); | |||||
| } | |||||
| myDao.update(this); | |||||
| } | |||||
| public boolean getIsLocal() { | |||||
| return this.isLocal; | |||||
| } | |||||
| public void setIsLocal(boolean isLocal) { | |||||
| this.isLocal = isLocal; | |||||
| } | |||||
| @Override | |||||
| public int describeContents() { | |||||
| return 0; | |||||
| } | |||||
| @Override | |||||
| public void writeToParcel(Parcel dest, int flags) { | |||||
| dest.writeString(this._id); | |||||
| dest.writeString(this.title); | |||||
| dest.writeString(this.author); | |||||
| dest.writeString(this.shortIntro); | |||||
| dest.writeString(this.cover); | |||||
| dest.writeByte(this.hasCp ? (byte) 1 : (byte) 0); | |||||
| dest.writeInt(this.latelyFollower); | |||||
| dest.writeDouble(this.retentionRatio); | |||||
| dest.writeString(this.updated); | |||||
| dest.writeString(this.lastRead); | |||||
| dest.writeInt(this.chaptersCount); | |||||
| dest.writeString(this.lastChapter); | |||||
| dest.writeByte(this.isUpdate ? (byte) 1 : (byte) 0); | |||||
| dest.writeByte(this.isLocal ? (byte) 1 : (byte) 0); | |||||
| } | |||||
| /** called by internal mechanisms, do not call yourself. */ | |||||
| @Generated(hash = 159260324) | |||||
| public void __setDaoSession(DaoSession daoSession) { | |||||
| this.daoSession = daoSession; | |||||
| myDao = daoSession != null ? daoSession.getCollBookBeanDao() : null; | |||||
| } | |||||
| protected CollBookBean(Parcel in) { | |||||
| this._id = in.readString(); | |||||
| this.title = in.readString(); | |||||
| this.author = in.readString(); | |||||
| this.shortIntro = in.readString(); | |||||
| this.cover = in.readString(); | |||||
| this.hasCp = in.readByte() != 0; | |||||
| this.latelyFollower = in.readInt(); | |||||
| this.retentionRatio = in.readDouble(); | |||||
| this.updated = in.readString(); | |||||
| this.lastRead = in.readString(); | |||||
| this.chaptersCount = in.readInt(); | |||||
| this.lastChapter = in.readString(); | |||||
| this.isUpdate = in.readByte() != 0; | |||||
| this.isLocal = in.readByte() != 0; | |||||
| } | |||||
| public static final Creator<CollBookBean> CREATOR = new Creator<CollBookBean>() { | |||||
| @Override | |||||
| public CollBookBean createFromParcel(Parcel source) { | |||||
| return new CollBookBean(source); | |||||
| } | |||||
| @Override | |||||
| public CollBookBean[] newArray(int size) { | |||||
| return new CollBookBean[size]; | |||||
| } | |||||
| }; | |||||
| } | |||||
| @@ -1,81 +0,0 @@ | |||||
| package com.yzx.webebook.model.bean; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-29. | |||||
| */ | |||||
| public class CommentBean { | |||||
| /** | |||||
| * _id : 57fd69356b613e9d1e69febb | |||||
| * content : 2000年 | |||||
| * author : {"_id":"57b6794f138527405e83382c","avatar":"/avatar/bc/3f/bc3f0b58815e497b00dabb7a14476891","nickname":"孤独患者","activityAvatar":"","type":"normal","lv":6,"gender":"female"} | |||||
| * floor : 7150 | |||||
| * likeCount : 0 | |||||
| * created : 2016-10-11T22:35:33.303Z | |||||
| * replyTo : {"_id":"57caec937a142c2277757f2d","floor":7038,"author":{"_id":"576a96dd4cb19fa249303369","nickname":"刘"}} | |||||
| */ | |||||
| private String _id; | |||||
| private String content; | |||||
| private AuthorBean author; | |||||
| private int floor; | |||||
| private int likeCount; | |||||
| private String created; | |||||
| private ReplyToBean replyTo; | |||||
| public String get_id() { | |||||
| return _id; | |||||
| } | |||||
| public void set_id(String _id) { | |||||
| this._id = _id; | |||||
| } | |||||
| public String getContent() { | |||||
| return content; | |||||
| } | |||||
| public void setContent(String content) { | |||||
| this.content = content; | |||||
| } | |||||
| public AuthorBean getAuthor() { | |||||
| return author; | |||||
| } | |||||
| public void setAuthor(AuthorBean author) { | |||||
| this.author = author; | |||||
| } | |||||
| public int getFloor() { | |||||
| return floor; | |||||
| } | |||||
| public void setFloor(int floor) { | |||||
| this.floor = floor; | |||||
| } | |||||
| public int getLikeCount() { | |||||
| return likeCount; | |||||
| } | |||||
| public void setLikeCount(int likeCount) { | |||||
| this.likeCount = likeCount; | |||||
| } | |||||
| public String getCreated() { | |||||
| return created; | |||||
| } | |||||
| public void setCreated(String created) { | |||||
| this.created = created; | |||||
| } | |||||
| public ReplyToBean getReplyTo() { | |||||
| return replyTo; | |||||
| } | |||||
| public void setReplyTo(ReplyToBean replyTo) { | |||||
| this.replyTo = replyTo; | |||||
| } | |||||
| } | |||||
| @@ -1,31 +0,0 @@ | |||||
| package com.yzx.webebook.model.bean; | |||||
| import java.util.List; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-29. | |||||
| */ | |||||
| public class DetailBean<T> { | |||||
| private T detail; | |||||
| private List<CommentBean> bestComments; | |||||
| private List<CommentBean> comments; | |||||
| public DetailBean(T details, List<CommentBean> bestComments, List<CommentBean> comments) { | |||||
| this.detail = details; | |||||
| this.bestComments = bestComments; | |||||
| this.comments = comments; | |||||
| } | |||||
| public T getDetail() { | |||||
| return detail; | |||||
| } | |||||
| public List<CommentBean> getBestComments() { | |||||
| return bestComments; | |||||
| } | |||||
| public List<CommentBean> getComments() { | |||||
| return comments; | |||||
| } | |||||
| } | |||||
| @@ -1,212 +0,0 @@ | |||||
| package com.yzx.webebook.model.bean; | |||||
| import org.greenrobot.greendao.DaoException; | |||||
| import org.greenrobot.greendao.annotation.Entity; | |||||
| import org.greenrobot.greendao.annotation.Generated; | |||||
| import org.greenrobot.greendao.annotation.Id; | |||||
| import org.greenrobot.greendao.annotation.ToMany; | |||||
| import java.util.List; | |||||
| import com.yzx.webebook.model.gen.DaoSession; | |||||
| import com.yzx.webebook.model.gen.BookChapterBeanDao; | |||||
| import com.yzx.webebook.model.gen.DownloadTaskBeanDao; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-11. | |||||
| */ | |||||
| @Entity | |||||
| public class DownloadTaskBean { | |||||
| public static final int STATUS_LOADING = 1; | |||||
| public static final int STATUS_WAIT = 2; | |||||
| public static final int STATUS_PAUSE = 3; | |||||
| public static final int STATUS_ERROR = 4; | |||||
| public static final int STATUS_FINISH = 5; | |||||
| //任务名称 -> 名称唯一不重复 | |||||
| @Id | |||||
| private String taskName; | |||||
| //所属的bookId(外健) | |||||
| private String bookId; | |||||
| @ToMany(referencedJoinProperty = "taskName") | |||||
| private List<BookChapterBean> bookChapterList; | |||||
| //章节的下载进度,默认为初始状态 | |||||
| private int currentChapter = 0; | |||||
| //最后的章节 | |||||
| private int lastChapter = 0; | |||||
| //状态:正在下载、下载完成、暂停、等待、下载错误。 | |||||
| private volatile int status = STATUS_WAIT; | |||||
| //总大小 -> (完成之后才会赋值) | |||||
| private long size = 0; | |||||
| /** Used to resolve relations */ | |||||
| @Generated(hash = 2040040024) | |||||
| private transient DaoSession daoSession; | |||||
| /** Used for active entity operations. */ | |||||
| @Generated(hash = 1584592296) | |||||
| private transient DownloadTaskBeanDao myDao; | |||||
| @Generated(hash = 597395122) | |||||
| public DownloadTaskBean(String taskName, String bookId, int currentChapter, int lastChapter, | |||||
| int status, long size) { | |||||
| this.taskName = taskName; | |||||
| this.bookId = bookId; | |||||
| this.currentChapter = currentChapter; | |||||
| this.lastChapter = lastChapter; | |||||
| this.status = status; | |||||
| this.size = size; | |||||
| } | |||||
| @Generated(hash = 2123101309) | |||||
| public DownloadTaskBean() { | |||||
| } | |||||
| public String getBookId() { | |||||
| return bookId; | |||||
| } | |||||
| public void setBookId(String bookId) { | |||||
| this.bookId = bookId; | |||||
| } | |||||
| public String getTaskName() { | |||||
| return taskName; | |||||
| } | |||||
| public void setTaskName(String taskName) { | |||||
| this.taskName = taskName; | |||||
| if (bookChapterList!=null){ | |||||
| for (BookChapterBean bean : bookChapterList){ | |||||
| bean.setTaskName(getTaskName()); | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * To-many relationship, resolved on first access (and after reset). | |||||
| * Changes to to-many relations are not persisted, make changes to the target entity. | |||||
| */ | |||||
| @Generated(hash = 389263273) | |||||
| public List<BookChapterBean> getBookChapterList() { | |||||
| if (bookChapterList == null) { | |||||
| final DaoSession daoSession = this.daoSession; | |||||
| if (daoSession == null) { | |||||
| throw new DaoException("Entity is detached from DAO context"); | |||||
| } | |||||
| BookChapterBeanDao targetDao = daoSession.getBookChapterBeanDao(); | |||||
| List<BookChapterBean> bookChapterListNew = targetDao | |||||
| ._queryDownloadTaskBean_BookChapterList(taskName); | |||||
| synchronized (this) { | |||||
| if (bookChapterList == null) { | |||||
| bookChapterList = bookChapterListNew; | |||||
| } | |||||
| } | |||||
| } | |||||
| return bookChapterList; | |||||
| } | |||||
| /** | |||||
| * 这才是真正的列表使用类。 | |||||
| * | |||||
| */ | |||||
| public void setBookChapters(List<BookChapterBean> beans){ | |||||
| bookChapterList = beans; | |||||
| for (BookChapterBean bean : bookChapterList){ | |||||
| bean.setTaskName(getTaskName()); | |||||
| } | |||||
| } | |||||
| public List<BookChapterBean> getBookChapters(){ | |||||
| if (daoSession == null){ | |||||
| return bookChapterList; | |||||
| } | |||||
| else { | |||||
| return getBookChapterList(); | |||||
| } | |||||
| } | |||||
| public int getCurrentChapter() { | |||||
| return currentChapter; | |||||
| } | |||||
| public void setCurrentChapter(int current) { | |||||
| this.currentChapter = current; | |||||
| } | |||||
| public int getLastChapter() { | |||||
| return lastChapter; | |||||
| } | |||||
| public void setLastChapter(int lastChapter) { | |||||
| this.lastChapter = lastChapter; | |||||
| } | |||||
| //多线程访问的问题,所以需要同步机制 | |||||
| public int getStatus() { | |||||
| return status; | |||||
| } | |||||
| public void setStatus(int status){ | |||||
| this.status = status; | |||||
| } | |||||
| public long getSize() { | |||||
| return size; | |||||
| } | |||||
| public void setSize(long size) { | |||||
| this.size = size; | |||||
| } | |||||
| /** Resets a to-many relationship, making the next get call to query for a fresh result. */ | |||||
| @Generated(hash = 1077762221) | |||||
| public synchronized void resetBookChapterList() { | |||||
| bookChapterList = null; | |||||
| } | |||||
| /** | |||||
| * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}. | |||||
| * Entity must attached to an entity context. | |||||
| */ | |||||
| @Generated(hash = 128553479) | |||||
| public void delete() { | |||||
| if (myDao == null) { | |||||
| throw new DaoException("Entity is detached from DAO context"); | |||||
| } | |||||
| myDao.delete(this); | |||||
| } | |||||
| /** | |||||
| * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}. | |||||
| * Entity must attached to an entity context. | |||||
| */ | |||||
| @Generated(hash = 1942392019) | |||||
| public void refresh() { | |||||
| if (myDao == null) { | |||||
| throw new DaoException("Entity is detached from DAO context"); | |||||
| } | |||||
| myDao.refresh(this); | |||||
| } | |||||
| /** | |||||
| * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}. | |||||
| * Entity must attached to an entity context. | |||||
| */ | |||||
| @Generated(hash = 713229351) | |||||
| public void update() { | |||||
| if (myDao == null) { | |||||
| throw new DaoException("Entity is detached from DAO context"); | |||||
| } | |||||
| myDao.update(this); | |||||
| } | |||||
| /** called by internal mechanisms, do not call yourself. */ | |||||
| @Generated(hash = 1923117869) | |||||
| public void __setDaoSession(DaoSession daoSession) { | |||||
| this.daoSession = daoSession; | |||||
| myDao = daoSession != null ? daoSession.getDownloadTaskBeanDao() : null; | |||||
| } | |||||
| } | |||||
| @@ -1,67 +0,0 @@ | |||||
| package com.yzx.webebook.model.bean; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-29. | |||||
| */ | |||||
| public class ReplyToBean { | |||||
| /** | |||||
| * _id : 57caec937a142c2277757f2d | |||||
| * floor : 7038 | |||||
| * author : {"_id":"576a96dd4cb19fa249303369","nickname":"刘"} | |||||
| */ | |||||
| private String _id; | |||||
| private int floor; | |||||
| private ReplyAuthorBean author; | |||||
| public String get_id() { | |||||
| return _id; | |||||
| } | |||||
| public void set_id(String _id) { | |||||
| this._id = _id; | |||||
| } | |||||
| public int getFloor() { | |||||
| return floor; | |||||
| } | |||||
| public void setFloor(int floor) { | |||||
| this.floor = floor; | |||||
| } | |||||
| public ReplyAuthorBean getAuthor() { | |||||
| return author; | |||||
| } | |||||
| public void setAuthor(ReplyAuthorBean author) { | |||||
| this.author = author; | |||||
| } | |||||
| public static class ReplyAuthorBean { | |||||
| /** | |||||
| * _id : 576a96dd4cb19fa249303369 | |||||
| * nickname : 刘 | |||||
| */ | |||||
| private String _id; | |||||
| private String nickname; | |||||
| public String get_id() { | |||||
| return _id; | |||||
| } | |||||
| public void set_id(String _id) { | |||||
| this._id = _id; | |||||
| } | |||||
| public String getNickname() { | |||||
| return nickname; | |||||
| } | |||||
| public void setNickname(String nickname) { | |||||
| this.nickname = nickname; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,276 +0,0 @@ | |||||
| package com.yzx.webebook.model.local; | |||||
| import android.util.Log; | |||||
| import com.yzx.webebook.model.bean.BookChapterBean; | |||||
| import com.yzx.webebook.model.bean.BookRecordBean; | |||||
| import com.yzx.webebook.model.bean.ChapterInfoBean; | |||||
| import com.yzx.webebook.model.bean.CollBookBean; | |||||
| import com.yzx.webebook.model.gen.BookChapterBeanDao; | |||||
| import com.yzx.webebook.model.gen.BookRecordBeanDao; | |||||
| import com.yzx.webebook.model.gen.CollBookBeanDao; | |||||
| import com.yzx.webebook.model.gen.DaoSession; | |||||
| import com.yzx.webebook.model.gen.DownloadTaskBeanDao; | |||||
| import com.yzx.webebook.utils.BookManager; | |||||
| import com.yzx.webebook.utils.Constant; | |||||
| import com.yzx.webebook.utils.FileUtils; | |||||
| import com.yzx.webebook.utils.IOUtils; | |||||
| import java.io.BufferedReader; | |||||
| import java.io.BufferedWriter; | |||||
| import java.io.File; | |||||
| import java.io.FileNotFoundException; | |||||
| import java.io.FileReader; | |||||
| import java.io.FileWriter; | |||||
| import java.io.IOException; | |||||
| import java.io.Reader; | |||||
| import java.io.Writer; | |||||
| import java.util.List; | |||||
| import io.reactivex.Single; | |||||
| import io.reactivex.SingleEmitter; | |||||
| import io.reactivex.SingleOnSubscribe; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-8. | |||||
| * 存储关于书籍内容的信息(CollBook(收藏书籍),BookChapter(书籍列表),ChapterInfo(书籍章节),BookRecord(记录)) | |||||
| */ | |||||
| public class BookRepository { | |||||
| private static final String TAG = "CollBookManager"; | |||||
| private static volatile BookRepository sInstance; | |||||
| private DaoSession mSession; | |||||
| private CollBookBeanDao mCollBookDao; | |||||
| private BookRepository(){ | |||||
| mSession = DaoDbHelper.getInstance() | |||||
| .getSession(); | |||||
| mCollBookDao = mSession.getCollBookBeanDao(); | |||||
| } | |||||
| public static BookRepository getInstance(){ | |||||
| if (sInstance == null){ | |||||
| synchronized (BookRepository.class){ | |||||
| if (sInstance == null){ | |||||
| sInstance = new BookRepository(); | |||||
| } | |||||
| } | |||||
| } | |||||
| return sInstance; | |||||
| } | |||||
| //存储已收藏书籍 | |||||
| public void saveCollBookWithAsync(CollBookBean bean){ | |||||
| //启动异步存储 | |||||
| mSession.startAsyncSession() | |||||
| .runInTx( | |||||
| () -> { | |||||
| if (bean.getBookChapters() != null){ | |||||
| // 存储BookChapterBean | |||||
| mSession.getBookChapterBeanDao() | |||||
| .insertOrReplaceInTx(bean.getBookChapters()); | |||||
| } | |||||
| //存储CollBook (确保先后顺序,否则出错) | |||||
| mCollBookDao.insertOrReplace(bean); | |||||
| } | |||||
| ); | |||||
| } | |||||
| /** | |||||
| * 异步存储。 | |||||
| * 同时保存BookChapter | |||||
| * @param beans | |||||
| */ | |||||
| public void saveCollBooksWithAsync(List<CollBookBean> beans){ | |||||
| mSession.startAsyncSession() | |||||
| .runInTx( | |||||
| () -> { | |||||
| for (CollBookBean bean : beans){ | |||||
| if (bean.getBookChapters() != null){ | |||||
| //存储BookChapterBean(需要修改,如果存在id相同的则无视) | |||||
| mSession.getBookChapterBeanDao() | |||||
| .insertOrReplaceInTx(bean.getBookChapters()); | |||||
| } | |||||
| } | |||||
| //存储CollBook (确保先后顺序,否则出错) | |||||
| mCollBookDao.insertOrReplaceInTx(beans); | |||||
| } | |||||
| ); | |||||
| } | |||||
| public void saveCollBook(CollBookBean bean){ | |||||
| mCollBookDao.insertOrReplace(bean); | |||||
| } | |||||
| public void saveCollBooks(List<CollBookBean> beans){ | |||||
| mCollBookDao.insertOrReplaceInTx(beans); | |||||
| } | |||||
| /** | |||||
| * 异步存储BookChapter | |||||
| * @param beans | |||||
| */ | |||||
| public void saveBookChaptersWithAsync(List<BookChapterBean> beans){ | |||||
| mSession.startAsyncSession() | |||||
| .runInTx( | |||||
| () -> { | |||||
| //存储BookChapterBean | |||||
| mSession.getBookChapterBeanDao() | |||||
| .insertOrReplaceInTx(beans); | |||||
| Log.d(TAG, "saveBookChaptersWithAsync: "+"进行存储"); | |||||
| } | |||||
| ); | |||||
| } | |||||
| /** | |||||
| * 存储章节 | |||||
| * @param folderName | |||||
| * @param fileName | |||||
| * @param content | |||||
| */ | |||||
| public void saveChapterInfo(String folderName,String fileName,String content){ | |||||
| File file = BookManager.getBookFile(folderName, fileName); | |||||
| //获取流并存储 | |||||
| Writer writer = null; | |||||
| try { | |||||
| writer = new BufferedWriter(new FileWriter(file)); | |||||
| writer.write(content); | |||||
| writer.flush(); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| IOUtils.close(writer); | |||||
| } | |||||
| } | |||||
| public void saveBookRecord(BookRecordBean bean){ | |||||
| mSession.getBookRecordBeanDao() | |||||
| .insertOrReplace(bean); | |||||
| } | |||||
| /*****************************get************************************************/ | |||||
| public CollBookBean getCollBook(String bookId){ | |||||
| CollBookBean bean = mCollBookDao.queryBuilder() | |||||
| .where(CollBookBeanDao.Properties._id.eq(bookId)) | |||||
| .unique(); | |||||
| return bean; | |||||
| } | |||||
| public List<CollBookBean> getCollBooks(){ | |||||
| return mCollBookDao | |||||
| .queryBuilder() | |||||
| .orderDesc(CollBookBeanDao.Properties.LastRead) | |||||
| .list(); | |||||
| } | |||||
| //获取书籍列表 | |||||
| public Single<List<BookChapterBean>> getBookChaptersInRx(String bookId){ | |||||
| return Single.create(new SingleOnSubscribe<List<BookChapterBean>>() { | |||||
| @Override | |||||
| public void subscribe(SingleEmitter<List<BookChapterBean>> e) throws Exception { | |||||
| List<BookChapterBean> beans = mSession | |||||
| .getBookChapterBeanDao() | |||||
| .queryBuilder() | |||||
| .where(BookChapterBeanDao.Properties.BookId.eq(bookId)) | |||||
| .list(); | |||||
| e.onSuccess(beans); | |||||
| } | |||||
| }); | |||||
| } | |||||
| //获取阅读记录 | |||||
| public BookRecordBean getBookRecord(String bookId){ | |||||
| return mSession.getBookRecordBeanDao() | |||||
| .queryBuilder() | |||||
| .where(BookRecordBeanDao.Properties.BookId.eq(bookId)) | |||||
| .unique(); | |||||
| } | |||||
| //TODO:需要进行获取编码并转换的问题 | |||||
| public ChapterInfoBean getChapterInfoBean(String folderName, String fileName){ | |||||
| File file = new File(Constant.BOOK_CACHE_PATH + folderName | |||||
| + File.separator + fileName + FileUtils.SUFFIX_NB); | |||||
| if (!file.exists()) return null; | |||||
| Reader reader = null; | |||||
| String str = null; | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| try { | |||||
| reader = new FileReader(file); | |||||
| BufferedReader br = new BufferedReader(reader); | |||||
| while ((str = br.readLine()) != null){ | |||||
| sb.append(str); | |||||
| } | |||||
| } catch (FileNotFoundException e) { | |||||
| e.printStackTrace(); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| }finally { | |||||
| IOUtils.close(reader); | |||||
| } | |||||
| ChapterInfoBean bean = new ChapterInfoBean(); | |||||
| bean.setTitle(fileName); | |||||
| bean.setBody(sb.toString()); | |||||
| return bean; | |||||
| } | |||||
| /************************************************************/ | |||||
| /************************************************************/ | |||||
| public Single<Void> deleteCollBookInRx(CollBookBean bean) { | |||||
| return Single.create(new SingleOnSubscribe<Void>() { | |||||
| @Override | |||||
| public void subscribe(SingleEmitter<Void> e) throws Exception { | |||||
| //查看文本中是否存在删除的数据 | |||||
| deleteBook(bean.get_id()); | |||||
| //删除任务 | |||||
| deleteDownloadTask(bean.get_id()); | |||||
| //删除目录 | |||||
| deleteBookChapter(bean.get_id()); | |||||
| //删除CollBook | |||||
| mCollBookDao.delete(bean); | |||||
| e.onSuccess(new Void()); | |||||
| } | |||||
| }); | |||||
| } | |||||
| //这个需要用rx,进行删除 | |||||
| public void deleteBookChapter(String bookId){ | |||||
| mSession.getBookChapterBeanDao() | |||||
| .queryBuilder() | |||||
| .where(BookChapterBeanDao.Properties.BookId.eq(bookId)) | |||||
| .buildDelete() | |||||
| .executeDeleteWithoutDetachingEntities(); | |||||
| } | |||||
| public void deleteCollBook(CollBookBean collBook){ | |||||
| mCollBookDao.delete(collBook); | |||||
| } | |||||
| //删除书籍 | |||||
| public void deleteBook(String bookId){ | |||||
| FileUtils.deleteFile(Constant.BOOK_CACHE_PATH+bookId); | |||||
| } | |||||
| public void deleteBookRecord(String id){ | |||||
| mSession.getBookRecordBeanDao() | |||||
| .queryBuilder() | |||||
| .where(BookRecordBeanDao.Properties.BookId.eq(id)) | |||||
| .buildDelete() | |||||
| .executeDeleteWithoutDetachingEntities(); | |||||
| } | |||||
| //删除任务 | |||||
| public void deleteDownloadTask(String bookId){ | |||||
| mSession.getDownloadTaskBeanDao() | |||||
| .queryBuilder() | |||||
| .where(DownloadTaskBeanDao.Properties.BookId.eq(bookId)) | |||||
| .buildDelete() | |||||
| .executeDeleteWithoutDetachingEntities(); | |||||
| } | |||||
| public DaoSession getSession(){ | |||||
| return mSession; | |||||
| } | |||||
| } | |||||
| @@ -1,56 +0,0 @@ | |||||
| package com.yzx.webebook.model.local; | |||||
| import android.database.sqlite.SQLiteDatabase; | |||||
| import com.yzx.webebook.App; | |||||
| import com.yzx.webebook.model.gen.DaoMaster; | |||||
| import com.yzx.webebook.model.gen.DaoSession; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-26. | |||||
| */ | |||||
| public class DaoDbHelper { | |||||
| private static final String DB_NAME = "IReader_DB"; | |||||
| private static volatile DaoDbHelper sInstance; | |||||
| private SQLiteDatabase mDb; | |||||
| private DaoMaster mDaoMaster; | |||||
| private DaoSession mSession; | |||||
| private DaoDbHelper(){ | |||||
| //封装数据库的创建、更新、删除 | |||||
| DaoMaster.DevOpenHelper openHelper = new MyOpenHelper(App.Companion.getContext(),DB_NAME,null); | |||||
| //获取数据库 | |||||
| mDb = openHelper.getWritableDatabase(); | |||||
| //封装数据库中表的创建、更新、删除 | |||||
| mDaoMaster = new DaoMaster(mDb); //合起来就是对数据库的操作 | |||||
| //对表操作的对象。 | |||||
| mSession = mDaoMaster.newSession(); //可以认为是对数据的操作 | |||||
| } | |||||
| public static DaoDbHelper getInstance(){ | |||||
| if (sInstance == null){ | |||||
| synchronized (DaoDbHelper.class){ | |||||
| if (sInstance == null){ | |||||
| sInstance = new DaoDbHelper(); | |||||
| } | |||||
| } | |||||
| } | |||||
| return sInstance; | |||||
| } | |||||
| public DaoSession getSession(){ | |||||
| return mSession; | |||||
| } | |||||
| public SQLiteDatabase getDatabase(){ | |||||
| return mDb; | |||||
| } | |||||
| public DaoSession getNewSession(){ | |||||
| return mDaoMaster.newSession(); | |||||
| } | |||||
| } | |||||
| @@ -1,16 +0,0 @@ | |||||
| package com.yzx.webebook.model.local; | |||||
| import com.yzx.webebook.model.bean.AuthorBean; | |||||
| import java.util.List; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-28. | |||||
| */ | |||||
| public interface DeleteDbHelper { | |||||
| void deleteAuthors(List<AuthorBean> beans); | |||||
| void deleteAll(); | |||||
| } | |||||
| @@ -1,23 +0,0 @@ | |||||
| package com.yzx.webebook.model.local; | |||||
| import com.yzx.webebook.model.bean.AuthorBean; | |||||
| import com.yzx.webebook.model.bean.DownloadTaskBean; | |||||
| import java.util.List; | |||||
| import io.reactivex.Single; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-28. | |||||
| */ | |||||
| public interface GetDbHelper { | |||||
| AuthorBean getAuthor(String id); | |||||
| /******************************/ | |||||
| List<DownloadTaskBean> getDownloadTaskList(); | |||||
| } | |||||
| @@ -1,116 +0,0 @@ | |||||
| package com.yzx.webebook.model.local; | |||||
| import com.google.gson.Gson; | |||||
| import com.yzx.webebook.model.bean.AuthorBean; | |||||
| import com.yzx.webebook.model.bean.BookCount; | |||||
| import com.yzx.webebook.model.bean.ChapterPageCount; | |||||
| import com.yzx.webebook.model.bean.DownloadTaskBean; | |||||
| import com.yzx.webebook.model.gen.BookCountDao; | |||||
| import com.yzx.webebook.model.gen.ChapterPageCountDao; | |||||
| import com.yzx.webebook.model.gen.DaoSession; | |||||
| import org.greenrobot.greendao.Property; | |||||
| import org.greenrobot.greendao.query.Join; | |||||
| import org.greenrobot.greendao.query.QueryBuilder; | |||||
| import java.lang.reflect.Field; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| import io.reactivex.Single; | |||||
| import io.reactivex.SingleEmitter; | |||||
| import io.reactivex.SingleOnSubscribe; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-26. | |||||
| */ | |||||
| public class LocalRepository implements SaveDbHelper,GetDbHelper,DeleteDbHelper{ | |||||
| private static final String TAG = "LocalRepository"; | |||||
| private static final String DISTILLATE_ALL = "normal"; | |||||
| private static final String DISTILLATE_BOUTIQUES = "distillate"; | |||||
| private static volatile LocalRepository sInstance; | |||||
| private DaoSession mSession; | |||||
| private LocalRepository(){ | |||||
| mSession = DaoDbHelper.getInstance().getSession(); | |||||
| } | |||||
| public static LocalRepository getInstance(){ | |||||
| if (sInstance == null){ | |||||
| synchronized (LocalRepository.class){ | |||||
| if (sInstance == null){ | |||||
| sInstance = new LocalRepository(); | |||||
| } | |||||
| } | |||||
| } | |||||
| return sInstance; | |||||
| } | |||||
| @Override | |||||
| public void deleteAuthors(List<AuthorBean> beans) { | |||||
| } | |||||
| @Override | |||||
| public void deleteAll() { | |||||
| //清空全部数据。 | |||||
| } | |||||
| @Override | |||||
| public AuthorBean getAuthor(String id) { | |||||
| return null; | |||||
| } | |||||
| @Override | |||||
| public List<DownloadTaskBean> getDownloadTaskList() { | |||||
| return null; | |||||
| } | |||||
| @Override | |||||
| public void saveAuthors(List<AuthorBean> beans) { | |||||
| } | |||||
| @Override | |||||
| public void saveDownloadTask(DownloadTaskBean bean) { | |||||
| } | |||||
| @Override | |||||
| public void saveBookCount(BookCount bookCount) { | |||||
| mSession.getBookCountDao().insertOrReplaceInTx(bookCount); | |||||
| } | |||||
| @Override | |||||
| public int getBookCount(String id) { | |||||
| BookCount list = mSession.getBookCountDao() | |||||
| .queryBuilder() | |||||
| .where(BookCountDao.Properties._id.eq(id)) | |||||
| .unique(); | |||||
| if(list!=null){ | |||||
| return list.getTotal(); | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| @Override | |||||
| public void saveChapterCount(List<ChapterPageCount> list) { | |||||
| mSession.getChapterPageCountDao().insertOrReplaceInTx(list); | |||||
| } | |||||
| @Override | |||||
| public List<ChapterPageCount> getChapterCount(String book_id) { | |||||
| List<ChapterPageCount> list = mSession.getChapterPageCountDao() | |||||
| .queryBuilder() | |||||
| .where(ChapterPageCountDao.Properties.Book_id.eq(book_id)) | |||||
| .list(); | |||||
| if(list!=null && list.size()>0){ | |||||
| return list; | |||||
| } | |||||
| return new ArrayList<ChapterPageCount>(); | |||||
| } | |||||
| } | |||||
| @@ -1,34 +0,0 @@ | |||||
| package com.yzx.webebook.model.local; | |||||
| import android.content.Context; | |||||
| import android.database.sqlite.SQLiteDatabase; | |||||
| import com.yzx.webebook.model.gen.DaoMaster; | |||||
| import com.yzx.webebook.model.local.update.Update2Helper; | |||||
| import org.greenrobot.greendao.database.Database; | |||||
| /** | |||||
| * Created by newbiechen on 2017/10/9. | |||||
| */ | |||||
| public class MyOpenHelper extends DaoMaster.DevOpenHelper{ | |||||
| public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) { | |||||
| super(context, name, factory); | |||||
| } | |||||
| @Override | |||||
| public void onUpgrade(Database db, int oldVersion, int newVersion) { | |||||
| // 跨版本更新策略 | |||||
| switch (oldVersion){ | |||||
| case 1: | |||||
| // 暂无 1.0 | |||||
| case 2: | |||||
| // 更新数据到 3.0 | |||||
| Update2Helper.getInstance().update(db); | |||||
| default: | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,134 +0,0 @@ | |||||
| package com.yzx.webebook.model.local; | |||||
| import com.yzx.webebook.utils.ScreenUtils; | |||||
| import com.yzx.webebook.utils.SharedPreUtils; | |||||
| import com.yzx.webebook.widget.page.PageMode; | |||||
| import com.yzx.webebook.widget.page.PageStyle; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-17. | |||||
| * 阅读器的配置管理 | |||||
| */ | |||||
| public class ReadSettingManager { | |||||
| /*************实在想不出什么好记的命名方式。。******************/ | |||||
| public static final int READ_BG_DEFAULT = 0; | |||||
| public static final int READ_BG_1 = 1; | |||||
| public static final int READ_BG_2 = 2; | |||||
| public static final int READ_BG_3 = 3; | |||||
| public static final int READ_BG_4 = 4; | |||||
| public static final int NIGHT_MODE = 5; | |||||
| public static final String SHARED_READ_BG = "shared_read_bg"; | |||||
| public static final String SHARED_READ_BRIGHTNESS = "shared_read_brightness"; | |||||
| public static final String SHARED_READ_IS_BRIGHTNESS_AUTO = "shared_read_is_brightness_auto"; | |||||
| public static final String SHARED_READ_TEXT_SIZE = "shared_read_text_size"; | |||||
| public static final String SHARED_READ_IS_TEXT_DEFAULT = "shared_read_text_default"; | |||||
| public static final String SHARED_READ_PAGE_MODE = "shared_read_mode"; | |||||
| public static final String SHARED_READ_NIGHT_MODE = "shared_night_mode"; | |||||
| public static final String SHARED_READ_VOLUME_TURN_PAGE = "shared_read_volume_turn_page"; | |||||
| public static final String SHARED_READ_FULL_SCREEN = "shared_read_full_screen"; | |||||
| public static final String SHARED_READ_CONVERT_TYPE = "shared_read_convert_type"; | |||||
| private static volatile ReadSettingManager sInstance; | |||||
| private SharedPreUtils sharedPreUtils; | |||||
| public static ReadSettingManager getInstance() { | |||||
| if (sInstance == null) { | |||||
| synchronized (ReadSettingManager.class) { | |||||
| if (sInstance == null) { | |||||
| sInstance = new ReadSettingManager(); | |||||
| } | |||||
| } | |||||
| } | |||||
| return sInstance; | |||||
| } | |||||
| private ReadSettingManager() { | |||||
| sharedPreUtils = SharedPreUtils.getInstance(); | |||||
| } | |||||
| public void setPageStyle(PageStyle pageStyle) { | |||||
| sharedPreUtils.putInt(SHARED_READ_BG, pageStyle.ordinal()); | |||||
| } | |||||
| public void setBrightness(int progress) { | |||||
| sharedPreUtils.putInt(SHARED_READ_BRIGHTNESS, progress); | |||||
| } | |||||
| public void setAutoBrightness(boolean isAuto) { | |||||
| sharedPreUtils.putBoolean(SHARED_READ_IS_BRIGHTNESS_AUTO, isAuto); | |||||
| } | |||||
| public void setDefaultTextSize(boolean isDefault) { | |||||
| sharedPreUtils.putBoolean(SHARED_READ_IS_TEXT_DEFAULT, isDefault); | |||||
| } | |||||
| public void setTextSize(int textSize) { | |||||
| sharedPreUtils.putInt(SHARED_READ_TEXT_SIZE, textSize); | |||||
| } | |||||
| public void setPageMode(PageMode mode) { | |||||
| sharedPreUtils.putInt(SHARED_READ_PAGE_MODE, mode.ordinal()); | |||||
| } | |||||
| public void setNightMode(boolean isNight) { | |||||
| sharedPreUtils.putBoolean(SHARED_READ_NIGHT_MODE, isNight); | |||||
| } | |||||
| public int getBrightness() { | |||||
| return sharedPreUtils.getInt(SHARED_READ_BRIGHTNESS, 40); | |||||
| } | |||||
| public boolean isBrightnessAuto() { | |||||
| return sharedPreUtils.getBoolean(SHARED_READ_IS_BRIGHTNESS_AUTO, false); | |||||
| } | |||||
| public int getTextSize() { | |||||
| return sharedPreUtils.getInt(SHARED_READ_TEXT_SIZE, ScreenUtils.spToPx(28)); | |||||
| } | |||||
| public boolean isDefaultTextSize() { | |||||
| return sharedPreUtils.getBoolean(SHARED_READ_IS_TEXT_DEFAULT, false); | |||||
| } | |||||
| public PageMode getPageMode() { | |||||
| int mode = sharedPreUtils.getInt(SHARED_READ_PAGE_MODE, PageMode.NONE.ordinal()); | |||||
| return PageMode.values()[mode]; | |||||
| } | |||||
| public PageStyle getPageStyle() { | |||||
| int style = sharedPreUtils.getInt(SHARED_READ_BG, PageStyle.BG_0.ordinal()); | |||||
| return PageStyle.values()[style]; | |||||
| } | |||||
| public boolean isNightMode() { | |||||
| return sharedPreUtils.getBoolean(SHARED_READ_NIGHT_MODE, false); | |||||
| } | |||||
| public void setVolumeTurnPage(boolean isTurn) { | |||||
| sharedPreUtils.putBoolean(SHARED_READ_VOLUME_TURN_PAGE, isTurn); | |||||
| } | |||||
| public boolean isVolumeTurnPage() { | |||||
| return sharedPreUtils.getBoolean(SHARED_READ_VOLUME_TURN_PAGE, false); | |||||
| } | |||||
| public void setFullScreen(boolean isFullScreen) { | |||||
| sharedPreUtils.putBoolean(SHARED_READ_FULL_SCREEN, isFullScreen); | |||||
| } | |||||
| public boolean isFullScreen() { | |||||
| return sharedPreUtils.getBoolean(SHARED_READ_FULL_SCREEN, false); | |||||
| } | |||||
| public void setConvertType(int convertType) { | |||||
| sharedPreUtils.putInt(SHARED_READ_CONVERT_TYPE, convertType); | |||||
| } | |||||
| public int getConvertType() { | |||||
| return sharedPreUtils.getInt(SHARED_READ_CONVERT_TYPE, 0); | |||||
| } | |||||
| } | |||||
| @@ -1,28 +0,0 @@ | |||||
| package com.yzx.webebook.model.local; | |||||
| import com.yzx.webebook.model.bean.AuthorBean; | |||||
| import com.yzx.webebook.model.bean.BookCount; | |||||
| import com.yzx.webebook.model.bean.ChapterPageCount; | |||||
| import com.yzx.webebook.model.bean.DownloadTaskBean; | |||||
| import java.util.List; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-28. | |||||
| */ | |||||
| public interface SaveDbHelper { | |||||
| void saveAuthors(List<AuthorBean> beans); | |||||
| /*************DownloadTask*********************/ | |||||
| void saveDownloadTask(DownloadTaskBean bean); | |||||
| void saveBookCount(BookCount bookCount); | |||||
| int getBookCount(String id); | |||||
| void saveChapterCount(List<ChapterPageCount> list); | |||||
| List<ChapterPageCount> getChapterCount(String book_id); | |||||
| } | |||||
| @@ -1,8 +0,0 @@ | |||||
| package com.yzx.webebook.model.local; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-27. | |||||
| */ | |||||
| public final class Void { | |||||
| } | |||||
| @@ -1,207 +0,0 @@ | |||||
| package com.yzx.webebook.model.local.update; | |||||
| import android.database.Cursor; | |||||
| import android.text.TextUtils; | |||||
| import android.util.Log; | |||||
| import org.greenrobot.greendao.AbstractDao; | |||||
| import org.greenrobot.greendao.database.Database; | |||||
| import org.greenrobot.greendao.internal.DaoConfig; | |||||
| import java.lang.reflect.InvocationTargetException; | |||||
| import java.lang.reflect.Method; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Arrays; | |||||
| import java.util.List; | |||||
| /** | |||||
| * Created by newbiechen on 2017/10/9. | |||||
| * 数据库更新策略 | |||||
| */ | |||||
| public class MigrationHelper { | |||||
| private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION = "MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS"; | |||||
| private static MigrationHelper instance; | |||||
| public static MigrationHelper getInstance() { | |||||
| if (instance == null) { | |||||
| instance = new MigrationHelper(); | |||||
| } | |||||
| return instance; | |||||
| } | |||||
| public void migrate(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) { | |||||
| generateTempTables(db, daoClasses); | |||||
| deleteOriginalTables(db, daoClasses); | |||||
| createOrignalTables(db, daoClasses); | |||||
| restoreData(db, daoClasses); | |||||
| } | |||||
| /** | |||||
| * 生成临时列表 | |||||
| * | |||||
| * @param db | |||||
| * @param daoClasses | |||||
| */ | |||||
| private void generateTempTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) { | |||||
| for (int i = 0; i < daoClasses.length; i++) { | |||||
| DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]); | |||||
| String divider = ""; | |||||
| String tableName = daoConfig.tablename; | |||||
| String tempTableName = daoConfig.tablename.concat("_TEMP"); | |||||
| ArrayList<String> properties = new ArrayList<>(); | |||||
| StringBuilder createTableStringBuilder = new StringBuilder(); | |||||
| createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" ("); | |||||
| for (int j = 0; j < daoConfig.properties.length; j++) { | |||||
| String columnName = daoConfig.properties[j].columnName; | |||||
| if (getColumns(db, tableName).contains(columnName)) { | |||||
| properties.add(columnName); | |||||
| String type = null; | |||||
| try { | |||||
| type = getTypeByClass(daoConfig.properties[j].type); | |||||
| } catch (Exception exception) { | |||||
| exception.printStackTrace(); | |||||
| } | |||||
| createTableStringBuilder.append(divider).append(columnName).append(" ").append(type); | |||||
| if (daoConfig.properties[j].primaryKey) { | |||||
| createTableStringBuilder.append(" PRIMARY KEY"); | |||||
| } | |||||
| divider = ","; | |||||
| } | |||||
| } | |||||
| createTableStringBuilder.append(");"); | |||||
| db.execSQL(createTableStringBuilder.toString()); | |||||
| StringBuilder insertTableStringBuilder = new StringBuilder(); | |||||
| insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" ("); | |||||
| insertTableStringBuilder.append(TextUtils.join(",", properties)); | |||||
| insertTableStringBuilder.append(") SELECT "); | |||||
| insertTableStringBuilder.append(TextUtils.join(",", properties)); | |||||
| insertTableStringBuilder.append(" FROM ").append(tableName).append(";"); | |||||
| db.execSQL(insertTableStringBuilder.toString()); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 通过反射,删除要更新的表 | |||||
| */ | |||||
| private void deleteOriginalTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) { | |||||
| for (Class<? extends AbstractDao<?, ?>> daoClass : daoClasses) { | |||||
| try { | |||||
| Method method = daoClass.getMethod("dropTable", Database.class, boolean.class); | |||||
| method.invoke(null, db, true); | |||||
| } catch (IllegalAccessException e) { | |||||
| e.printStackTrace(); | |||||
| } catch (InvocationTargetException e) { | |||||
| e.printStackTrace(); | |||||
| } catch (NoSuchMethodException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 通过反射,重新创建要更新的表 | |||||
| */ | |||||
| private void createOrignalTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) { | |||||
| for (Class<? extends AbstractDao<?, ?>> daoClass : daoClasses) { | |||||
| try { | |||||
| Method method = daoClass.getMethod("createTable", Database.class, boolean.class); | |||||
| method.invoke(null, db, false); | |||||
| } catch (IllegalAccessException e) { | |||||
| e.printStackTrace(); | |||||
| } catch (InvocationTargetException e) { | |||||
| e.printStackTrace(); | |||||
| } catch (NoSuchMethodException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 存储新的数据库表 以及数据 | |||||
| * | |||||
| * @param db | |||||
| * @param daoClasses | |||||
| */ | |||||
| private void restoreData(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) { | |||||
| for (int i = 0; i < daoClasses.length; i++) { | |||||
| DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]); | |||||
| String tableName = daoConfig.tablename; | |||||
| String tempTableName = daoConfig.tablename.concat("_TEMP"); | |||||
| ArrayList<String> properties = new ArrayList(); | |||||
| for (int j = 0; j < daoConfig.properties.length; j++) { | |||||
| String columnName = daoConfig.properties[j].columnName; | |||||
| if (getColumns(db, tempTableName).contains(columnName)) { | |||||
| properties.add(columnName); | |||||
| } | |||||
| } | |||||
| StringBuilder insertTableStringBuilder = new StringBuilder(); | |||||
| insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" ("); | |||||
| insertTableStringBuilder.append(TextUtils.join(",", properties)); | |||||
| insertTableStringBuilder.append(") SELECT "); | |||||
| insertTableStringBuilder.append(TextUtils.join(",", properties)); | |||||
| insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";"); | |||||
| StringBuilder dropTableStringBuilder = new StringBuilder(); | |||||
| dropTableStringBuilder.append("DROP TABLE ").append(tempTableName); | |||||
| db.execSQL(insertTableStringBuilder.toString()); | |||||
| db.execSQL(dropTableStringBuilder.toString()); | |||||
| } | |||||
| } | |||||
| private String getTypeByClass(Class<?> type) throws Exception { | |||||
| if (type.equals(String.class)) { | |||||
| return "TEXT"; | |||||
| } | |||||
| if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) { | |||||
| return "INTEGER"; | |||||
| } | |||||
| if (type.equals(Boolean.class)) { | |||||
| return "BOOLEAN"; | |||||
| } | |||||
| Exception exception = new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString())); | |||||
| exception.printStackTrace(); | |||||
| throw exception; | |||||
| } | |||||
| private List<String> getColumns(Database db, String tableName) { | |||||
| List<String> columns = new ArrayList<>(); | |||||
| Cursor cursor = null; | |||||
| try { | |||||
| cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null); | |||||
| if (cursor != null) { | |||||
| columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames())); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| Log.v(tableName, e.getMessage(), e); | |||||
| e.printStackTrace(); | |||||
| } finally { | |||||
| if (cursor != null) | |||||
| cursor.close(); | |||||
| } | |||||
| return columns; | |||||
| } | |||||
| } | |||||
| @@ -1,284 +0,0 @@ | |||||
| package com.yzx.webebook.model.local.update; | |||||
| import android.database.Cursor; | |||||
| import android.text.TextUtils; | |||||
| import android.util.Log; | |||||
| import com.yzx.webebook.model.gen.BookChapterBeanDao; | |||||
| import com.yzx.webebook.model.gen.CollBookBeanDao; | |||||
| import com.yzx.webebook.utils.MD5Utils; | |||||
| import org.greenrobot.greendao.AbstractDao; | |||||
| import org.greenrobot.greendao.database.Database; | |||||
| import org.greenrobot.greendao.internal.DaoConfig; | |||||
| import java.lang.reflect.InvocationTargetException; | |||||
| import java.lang.reflect.Method; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Arrays; | |||||
| import java.util.List; | |||||
| /** | |||||
| * Created by newbiechen on 2018/1/5. | |||||
| * 由于 BookChapterBean 做了一次表的大更改,所以需要自定义更新。 | |||||
| * 作用:将数据库2.0 升级到 3.0 | |||||
| */ | |||||
| public class Update2Helper { | |||||
| private static final String TAG = "BookChapterHelper"; | |||||
| private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION = "MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS"; | |||||
| private static final String DIVIDER = ","; | |||||
| private static final String QUOTE = "'%s'"; | |||||
| private static Update2Helper instance; | |||||
| public static Update2Helper getInstance() { | |||||
| if (instance == null) { | |||||
| instance = new Update2Helper(); | |||||
| } | |||||
| return instance; | |||||
| } | |||||
| public void update(Database db) { | |||||
| updateCollBook(db); | |||||
| updateBookChapter(db); | |||||
| } | |||||
| private void updateBookChapter(Database db) { | |||||
| Class<? extends AbstractDao<?, ?>> bookChapterClass = BookChapterBeanDao.class; | |||||
| generateTempTables(db, bookChapterClass); | |||||
| deleteOriginalTables(db, bookChapterClass); | |||||
| createOrignalTables(db, bookChapterClass); | |||||
| restoreData(db, bookChapterClass); | |||||
| } | |||||
| private void updateCollBook(Database db) { | |||||
| Class<? extends AbstractDao<?, ?>> collBookClass = CollBookBeanDao.class; | |||||
| // 遍历查找本地文件,然后修改本地文件的数据 | |||||
| DaoConfig daoConfig = new DaoConfig(db, collBookClass); | |||||
| String tableName = daoConfig.tablename; | |||||
| Cursor cursor = db.rawQuery("select _ID,IS_LOCAL from " + tableName, null); | |||||
| String id = null; | |||||
| String cover = null; | |||||
| String isLocal = null; | |||||
| StringBuilder updateSb = new StringBuilder(); | |||||
| while (cursor.moveToNext()) { | |||||
| cover = cursor.getString(0); | |||||
| id = MD5Utils.strToMd5By16(cover); | |||||
| isLocal = cursor.getString(1); | |||||
| //如果是本地文件 | |||||
| if (isLocal.equals("1")) { | |||||
| // 数据更新 | |||||
| updateSb.append("UPDATE " + tableName + " SET "); | |||||
| updateSb.append("_ID=").append(String.format(QUOTE, id)).append(DIVIDER); | |||||
| updateSb.append("COVER=").append(String.format(QUOTE, cover)).append(" "); | |||||
| updateSb.append("WHERE _ID=").append(String.format(QUOTE,cover)).append(";"); | |||||
| db.execSQL(updateSb.toString()); | |||||
| updateSb.delete(0, updateSb.length()); | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 生成临时列表 | |||||
| * | |||||
| * @param db | |||||
| */ | |||||
| private void generateTempTables(Database db, Class<? extends AbstractDao<?, ?>> bookChapterClass) { | |||||
| // 解析 GreenDao,获取 table 名 | |||||
| DaoConfig daoConfig = new DaoConfig(db, bookChapterClass); | |||||
| String tableName = daoConfig.tablename; | |||||
| // 创建临时 table 名。 | |||||
| String tempTableName = daoConfig.tablename.concat("_TEMP"); | |||||
| ArrayList<String> properties = new ArrayList<>(); | |||||
| StringBuilder createTableStringBuilder = new StringBuilder(); | |||||
| createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" ("); | |||||
| // 新增的三个字段 | |||||
| String ID = "ID"; | |||||
| String START = "START"; | |||||
| String END = "end"; | |||||
| // 新建的 id 主键字段 | |||||
| createTableStringBuilder.append(ID + " ").append("TEXT ").append("PRIMARY KEY"); | |||||
| properties.add(ID); | |||||
| // 获取符合新表的旧字段。 | |||||
| for (int j = 0; j < daoConfig.properties.length; j++) { | |||||
| String columnName = daoConfig.properties[j].columnName; | |||||
| if (getColumns(db, tableName).contains(columnName)) { | |||||
| properties.add(columnName); | |||||
| String type = null; | |||||
| try { | |||||
| type = getTypeByClass(daoConfig.properties[j].type); | |||||
| } catch (Exception exception) { | |||||
| exception.printStackTrace(); | |||||
| } | |||||
| createTableStringBuilder.append(DIVIDER).append(columnName).append(" ").append(type); | |||||
| } | |||||
| } | |||||
| // 新建的 START,和 END 字段。 | |||||
| createTableStringBuilder.append(DIVIDER).append(START).append(" ").append("INTEGER"); | |||||
| createTableStringBuilder.append(DIVIDER).append(END).append(" ").append("INTEGER"); | |||||
| properties.add(START); | |||||
| properties.add(END); | |||||
| createTableStringBuilder.append(");"); | |||||
| // 创建临时数据表 | |||||
| db.execSQL(createTableStringBuilder.toString()); | |||||
| StringBuilder insertTableStringBuilder = new StringBuilder(); | |||||
| // 将 link 字段的文件的内容转换成 Id | |||||
| Cursor cursor = db.rawQuery("select * from " + daoConfig.tablename, null); | |||||
| String id = null; | |||||
| String link = null; | |||||
| String title = null; | |||||
| String taskName = null; | |||||
| String unreadble = null; | |||||
| String bookId = null; | |||||
| while (cursor.moveToNext()) { | |||||
| link = cursor.getString(0); | |||||
| id = MD5Utils.strToMd5By16(link); | |||||
| title = cursor.getString(1); | |||||
| taskName = cursor.getString(2); | |||||
| unreadble = cursor.getString(4); | |||||
| bookId = cursor.getString(3); | |||||
| insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" ("); | |||||
| insertTableStringBuilder.append(TextUtils.join(",", properties)); | |||||
| insertTableStringBuilder.append(") VALUES ("); | |||||
| insertTableStringBuilder.append(String.format(QUOTE, id)).append(DIVIDER); | |||||
| insertTableStringBuilder.append(String.format(QUOTE, link)).append(DIVIDER); | |||||
| insertTableStringBuilder.append(String.format(QUOTE, title)).append(DIVIDER); | |||||
| insertTableStringBuilder.append(String.format(QUOTE, taskName)).append(DIVIDER); | |||||
| insertTableStringBuilder.append(unreadble).append(DIVIDER); | |||||
| insertTableStringBuilder.append(String.format(QUOTE, bookId)).append(DIVIDER); | |||||
| insertTableStringBuilder.append("0").append(DIVIDER); | |||||
| insertTableStringBuilder.append("0").append(");"); | |||||
| db.execSQL(insertTableStringBuilder.toString()); | |||||
| insertTableStringBuilder.delete(0, insertTableStringBuilder.length()); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 通过反射,删除要更新的表 | |||||
| */ | |||||
| private void deleteOriginalTables(Database db,Class<? extends AbstractDao<?, ?>> bookChapterClass) { | |||||
| try { | |||||
| Method method = bookChapterClass.getMethod("dropTable", Database.class, boolean.class); | |||||
| method.invoke(null, db, true); | |||||
| } catch (IllegalAccessException e) { | |||||
| e.printStackTrace(); | |||||
| } catch (InvocationTargetException e) { | |||||
| e.printStackTrace(); | |||||
| } catch (NoSuchMethodException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 通过反射,重新创建要更新的表 | |||||
| */ | |||||
| private void createOrignalTables(Database db,Class<? extends AbstractDao<?, ?>> bookChapterClass) { | |||||
| try { | |||||
| Method method = bookChapterClass.getMethod("createTable", Database.class, boolean.class); | |||||
| method.invoke(null, db, false); | |||||
| } catch (IllegalAccessException e) { | |||||
| e.printStackTrace(); | |||||
| } catch (InvocationTargetException e) { | |||||
| e.printStackTrace(); | |||||
| } catch (NoSuchMethodException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 存储新的数据库表 以及数据 | |||||
| * | |||||
| * @param db | |||||
| */ | |||||
| private void restoreData(Database db,Class<? extends AbstractDao<?, ?>> bookChapterClass) { | |||||
| DaoConfig daoConfig = new DaoConfig(db, bookChapterClass); | |||||
| String tableName = daoConfig.tablename; | |||||
| String tempTableName = daoConfig.tablename.concat("_TEMP"); | |||||
| ArrayList<String> properties = new ArrayList(); | |||||
| for (int j = 0; j < daoConfig.properties.length; j++) { | |||||
| String columnName = daoConfig.properties[j].columnName; | |||||
| if (getColumns(db, tableName).contains(columnName)) { | |||||
| properties.add(columnName); | |||||
| } | |||||
| } | |||||
| StringBuilder insertTableStringBuilder = new StringBuilder(); | |||||
| insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" ("); | |||||
| insertTableStringBuilder.append(TextUtils.join(",", properties)); | |||||
| insertTableStringBuilder.append(") SELECT "); | |||||
| insertTableStringBuilder.append(TextUtils.join(",", properties)); | |||||
| insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";"); | |||||
| Log.d(TAG, "restoreData: " + insertTableStringBuilder.toString()); | |||||
| StringBuilder dropTableStringBuilder = new StringBuilder(); | |||||
| dropTableStringBuilder.append("DROP TABLE ").append(tempTableName); | |||||
| db.execSQL(insertTableStringBuilder.toString()); | |||||
| db.execSQL(dropTableStringBuilder.toString()); | |||||
| } | |||||
| private String getTypeByClass(Class<?> type) throws Exception { | |||||
| if (type.equals(String.class)) { | |||||
| return "TEXT"; | |||||
| } | |||||
| if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) { | |||||
| return "INTEGER"; | |||||
| } | |||||
| if (type.equals(boolean.class)) { | |||||
| return "BOOLEAN"; | |||||
| } | |||||
| Exception exception = new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString())); | |||||
| exception.printStackTrace(); | |||||
| throw exception; | |||||
| } | |||||
| private List<String> getColumns(Database db, String tableName) { | |||||
| List<String> columns = new ArrayList<>(); | |||||
| Cursor cursor = null; | |||||
| try { | |||||
| cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null); | |||||
| if (cursor != null) { | |||||
| columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames())); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| Log.v(tableName, e.getMessage(), e); | |||||
| e.printStackTrace(); | |||||
| } finally { | |||||
| if (cursor != null) | |||||
| cursor.close(); | |||||
| } | |||||
| return columns; | |||||
| } | |||||
| } | |||||
| @@ -1,25 +0,0 @@ | |||||
| package com.yzx.webebook.modules | |||||
| import android.widget.Toast | |||||
| import com.yzx.webebook.activity.WeexTestActivity | |||||
| import org.apache.weex.annotation.JSMethod | |||||
| import org.apache.weex.common.WXModule | |||||
| import org.jetbrains.anko.startActivity | |||||
| class ActivityWXModule : WXModule() { | |||||
| @JSMethod(uiThread = true) | |||||
| public fun navigateTo(url:String,params: String) { | |||||
| // val intent = Intent(mWXSDKInstance.context, WeexTestActivity::class.java) | |||||
| // intent.putExtra("url", url) | |||||
| // intent.putExtra("params", params) | |||||
| mWXSDKInstance.context.startActivity<WeexTestActivity>("url" to url,"params" to params) | |||||
| } | |||||
| @JSMethod(uiThread = true) | |||||
| public fun toast(msg: String?) { | |||||
| Toast.makeText(mWXSDKInstance.context, msg, Toast.LENGTH_SHORT).show() | |||||
| } | |||||
| } | |||||
| @@ -1,211 +0,0 @@ | |||||
| package com.yzx.webebook.presenter; | |||||
| import android.util.Log; | |||||
| import com.blankj.utilcode.util.FileIOUtils; | |||||
| import com.blankj.utilcode.util.FileUtils; | |||||
| import com.blankj.utilcode.util.LogUtils; | |||||
| import com.blankj.utilcode.util.TimeUtils; | |||||
| import com.blankj.utilcode.util.ToastUtils; | |||||
| import com.google.gson.Gson; | |||||
| import com.google.gson.reflect.TypeToken; | |||||
| import com.lzy.okgo.OkGo; | |||||
| import com.lzy.okgo.callback.FileCallback; | |||||
| import com.lzy.okgo.callback.StringCallback; | |||||
| import com.lzy.okgo.model.HttpHeaders; | |||||
| import com.lzy.okgo.model.Response; | |||||
| import com.yzx.webebook.config.Config; | |||||
| import com.yzx.webebook.model.BaseBean; | |||||
| import com.yzx.webebook.model.Book; | |||||
| import com.yzx.webebook.model.Sections; | |||||
| import com.yzx.webebook.model.User; | |||||
| import com.yzx.webebook.model.Volumes; | |||||
| import com.yzx.webebook.model.bean.CollBookBean; | |||||
| import com.yzx.webebook.model.local.BookRepository; | |||||
| import com.yzx.webebook.presenter.base.BasePresenter; | |||||
| import com.yzx.webebook.widget.page.TxtChapter; | |||||
| import org.jetbrains.annotations.NotNull; | |||||
| import java.io.File; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| public class ReadPresenter extends BasePresenter<ReadView> { | |||||
| static String NOTE_FOLDER_DIR = "/mnt/sdcard/ebook/book/"; | |||||
| public ReadPresenter(@NotNull ReadView view) { | |||||
| super(view); | |||||
| } | |||||
| public void getReadProgress(String bookId,String readTaskId){ | |||||
| User user = User.Companion.getUser(); | |||||
| String url = Config.INSTANCE.getBASE_URL() + "/parent/readTask/getBookWarehouseContent"; | |||||
| HttpHeaders headers = new HttpHeaders(); | |||||
| headers.put("phone", user.getPhone()); | |||||
| headers.put("token", user.getToken()); | |||||
| OkGo.<String>post(url) | |||||
| .tag(this) | |||||
| .params("id", bookId) | |||||
| .params("read_task_id", readTaskId) | |||||
| .headers(headers) | |||||
| .execute(new StringCallback() { | |||||
| @Override | |||||
| public void onSuccess(Response<String> response) { | |||||
| Gson gson = new Gson(); | |||||
| BaseBean<Book> bean = gson.fromJson(response.body(), new TypeToken<BaseBean<Book>>() { | |||||
| }.getType()); | |||||
| getMView().onProgressSuccess(bean.getData().getRead_progress()); | |||||
| } | |||||
| @Override | |||||
| public void onError(Response<String> response) { | |||||
| super.onError(response); | |||||
| } | |||||
| }); | |||||
| } | |||||
| public void loadCategory(String bookTaskId) { | |||||
| User user = User.Companion.getUser(); | |||||
| String localId = user.getUser_id() + "_" + bookTaskId; | |||||
| CollBookBean collBook = BookRepository.getInstance().getCollBook(localId); | |||||
| if (collBook != null) { | |||||
| getMView().showCategory(localId); | |||||
| } else { | |||||
| String url = Config.INSTANCE.getBASE_URL() + "/parent/readTask/getBookWarehouseContent"; | |||||
| HttpHeaders headers = new HttpHeaders(); | |||||
| headers.put("phone", user.getPhone()); | |||||
| headers.put("token", user.getToken()); | |||||
| OkGo.<String>post(url) | |||||
| .tag(this) | |||||
| .params("id", bookTaskId) | |||||
| .headers(headers) | |||||
| .execute(new StringCallback() { | |||||
| @Override | |||||
| public void onSuccess(Response<String> response) { | |||||
| Log.d("ReadActivity", "onSuccess: " + response.body()); | |||||
| Gson gson = new Gson(); | |||||
| BaseBean<Book> bean = gson.fromJson(response.body(), new TypeToken<BaseBean<Book>>() { | |||||
| }.getType()); | |||||
| if ("txt".equals(bean.getData().getFile_type()) || "pdf".equals(bean.getData().getFile_type().toLowerCase())) { | |||||
| downloadBook(bean.getData(), bookTaskId); | |||||
| } else { | |||||
| Book book = bean.getData(); | |||||
| StringBuffer builder = new StringBuffer() ; | |||||
| if (book.getVolumes().size() > 0) { | |||||
| for (Volumes volume : book.getVolumes()) { | |||||
| builder.append("----------"); | |||||
| builder.append("\r\n"); | |||||
| for (Sections section : volume.getSections()) { | |||||
| builder.append(section.getTitle()); | |||||
| builder.append("\r\n"); | |||||
| builder.append(section.getContent()); | |||||
| builder.append("\r\n"); | |||||
| } | |||||
| } | |||||
| } | |||||
| LogUtils.d(builder); | |||||
| LogUtils.d(builder.toString()); | |||||
| String filePath = NOTE_FOLDER_DIR + user.getUser_id() + "_" + bookTaskId + ".txt"; | |||||
| boolean success = FileUtils.createOrExistsFile(filePath); | |||||
| boolean whiteSuccess = FileIOUtils.writeFileFromString(new File(filePath),builder.toString()); | |||||
| if(success && whiteSuccess){ | |||||
| CollBookBean bookBean = new CollBookBean(); | |||||
| String localId = user.getUser_id() + "_" + bookTaskId; | |||||
| bookBean.set_id(localId); | |||||
| bookBean.setAuthor(book.getAuthor()); | |||||
| bookBean.setTitle(book.getBook_name()); | |||||
| bookBean.setShortIntro(book.getRead_requires()); | |||||
| bookBean.setLastChapter("开始阅读"); | |||||
| bookBean.setUpdate(true); | |||||
| bookBean.setIsLocal(true); | |||||
| bookBean.setLastRead(TimeUtils.getNowString()); | |||||
| bookBean.setUpdated(TimeUtils.getNowString()); | |||||
| bookBean.setCover(filePath); | |||||
| List<CollBookBean> list = new ArrayList<CollBookBean>(); | |||||
| list.add(bookBean); | |||||
| BookRepository.getInstance() | |||||
| .saveCollBooks(list); | |||||
| getMView().showCategory(localId); | |||||
| }else{ | |||||
| ToastUtils.showLong("书籍信息读取失败!"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public void onError(Response<String> response) { | |||||
| super.onError(response); | |||||
| } | |||||
| }); | |||||
| } | |||||
| } | |||||
| private void downloadBook(Book data, String bookTaskId) { | |||||
| User user = User.Companion.getUser(); | |||||
| OkGo.<File>get("https://" + data.getBook_file_identity() + ".oa.qbjjyyun.net/edufile/download?uniqueKey=" + data.getBook_file_id()) | |||||
| .tag(this) | |||||
| .execute(new FileCallback(NOTE_FOLDER_DIR, user.getUser_id() + "_" + data.getBook_name() + "." + data.getFile_type()) { | |||||
| @Override | |||||
| public void onSuccess(Response<File> response) { | |||||
| File file = response.body(); | |||||
| CollBookBean bookBean = new CollBookBean(); | |||||
| String localId = user.getUser_id() + "_" + bookTaskId; | |||||
| bookBean.set_id(localId); | |||||
| bookBean.setAuthor(data.getAuthor()); | |||||
| bookBean.setTitle(data.getBook_name()); | |||||
| bookBean.setShortIntro(data.getRead_requires()); | |||||
| bookBean.setLastChapter("开始阅读"); | |||||
| bookBean.setUpdate(true); | |||||
| bookBean.setIsLocal(true); | |||||
| bookBean.setLastRead(TimeUtils.getNowString()); | |||||
| bookBean.setUpdated(TimeUtils.getNowString()); | |||||
| bookBean.setCover(file.getAbsolutePath()); | |||||
| List<CollBookBean> list = new ArrayList<CollBookBean>(); | |||||
| list.add(bookBean); | |||||
| BookRepository.getInstance() | |||||
| .saveCollBooks(list); | |||||
| getMView().showCategory(localId); | |||||
| } | |||||
| }); | |||||
| } | |||||
| public void loadChapter(String bookId, List<TxtChapter> bookChapterList) { | |||||
| } | |||||
| public void updateReadProgress(String bookId,String readTaskId,String progress){ | |||||
| User user = User.Companion.getUser(); | |||||
| String url = Config.INSTANCE.getBASE_URL() + "/parent/readTask/updateReadProgress"; | |||||
| HttpHeaders headers = new HttpHeaders(); | |||||
| headers.put("phone", user.getPhone()); | |||||
| headers.put("token", user.getToken()); | |||||
| OkGo.<String>post(url) | |||||
| .tag(this) | |||||
| .params("id", bookId) | |||||
| .params("read_task_id", readTaskId) | |||||
| .params("read_progress", progress) | |||||
| .headers(headers) | |||||
| .execute(new StringCallback() { | |||||
| @Override | |||||
| public void onSuccess(Response<String> response) { | |||||
| } | |||||
| @Override | |||||
| public void onError(Response<String> response) { | |||||
| super.onError(response); | |||||
| } | |||||
| }); | |||||
| } | |||||
| } | |||||
| @@ -1,15 +0,0 @@ | |||||
| package com.yzx.webebook.presenter; | |||||
| import com.yzx.webebook.model.bean.BookChapterBean; | |||||
| import com.yzx.webebook.presenter.base.IView; | |||||
| import java.util.List; | |||||
| public interface ReadView extends IView { | |||||
| void showCategory(String localId); | |||||
| void finishChapter(); | |||||
| void errorChapter(); | |||||
| void onProgressSuccess(float progress); | |||||
| } | |||||
| @@ -1,16 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import android.app.Application; | |||||
| public class AppInstance { | |||||
| private static Application sApplication; | |||||
| public static void init(Application application) { | |||||
| sApplication = application; | |||||
| } | |||||
| public static Application get() { | |||||
| return sApplication; | |||||
| } | |||||
| } | |||||
| @@ -1,221 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import java.io.File; | |||||
| import java.lang.ref.WeakReference; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-20. | |||||
| * 处理书籍的工具类,配合PageFactory使用 | |||||
| * 已弃用, | |||||
| */ | |||||
| public class BookManager{ | |||||
| private static final String TAG = "BookManager"; | |||||
| private String chapterName; | |||||
| private String bookId; | |||||
| private long chapterLen; | |||||
| private long position; | |||||
| private Map<String, Cache> cacheMap = new HashMap<>(); | |||||
| private static volatile BookManager sInstance; | |||||
| public static BookManager getInstance(){ | |||||
| if (sInstance == null){ | |||||
| synchronized (BookManager.class){ | |||||
| if (sInstance == null){ | |||||
| sInstance = new BookManager(); | |||||
| } | |||||
| } | |||||
| } | |||||
| return sInstance; | |||||
| } | |||||
| public boolean openChapter(String bookId,String chapterName){ | |||||
| return openChapter(bookId,chapterName,0); | |||||
| } | |||||
| public boolean openChapter(String bookId,String chapterName,long position){ | |||||
| //如果文件不存在,则打开失败 | |||||
| File file = new File(Constant.BOOK_CACHE_PATH + bookId | |||||
| + File.separator + chapterName + FileUtils.SUFFIX_NB); | |||||
| if (!file.exists()){ | |||||
| return false; | |||||
| } | |||||
| this.bookId = bookId; | |||||
| this.chapterName = chapterName; | |||||
| this.position = position; | |||||
| createCache(); | |||||
| return true; | |||||
| } | |||||
| private void createCache(){ | |||||
| //创建Cache | |||||
| if (!cacheMap.containsKey(chapterName)){ | |||||
| Cache cache = new Cache(); | |||||
| File file = getBookFile(bookId, chapterName); | |||||
| //TODO:数据加载默认utf-8(以后会增加判断),FileUtils采用Reader获取数据的,可能用byte会更好一点 | |||||
| char[] array = FileUtils.getFileContent(file).toCharArray(); | |||||
| WeakReference<char[]> charReference = new WeakReference<char[]>(array); | |||||
| cache.size = array.length; | |||||
| cache.data = charReference; | |||||
| cacheMap.put(chapterName, cache); | |||||
| chapterLen = cache.size; | |||||
| } | |||||
| else { | |||||
| chapterLen = cacheMap.get(chapterName).getSize(); | |||||
| } | |||||
| } | |||||
| public void setPosition(long position){ | |||||
| this.position = position; | |||||
| } | |||||
| public long getPosition(){ | |||||
| return position; | |||||
| } | |||||
| //获取上一段 | |||||
| public String getPrevPara(){ | |||||
| //首先判断是否Position已经达到起始位置,已经越界 | |||||
| if (position < 0){ | |||||
| return null; | |||||
| } | |||||
| //初始化从后向前获取的起始点,终止点,文本 | |||||
| int end = (int)position; | |||||
| int begin = end; | |||||
| char[] array = getContent(); | |||||
| while (begin >= 0) { //判断指针是否达到章节的起始位置 | |||||
| char character = array[begin]; //获取当前指针下的字符 | |||||
| //判断当前字符是否为换行,如果为换行,就代表获取到了一个段落,并退出。 | |||||
| //有可能发生初始指针指的就是换行符的情况。 | |||||
| if ((character+"").equals("\n") && begin != end) { | |||||
| position = begin; | |||||
| //当当前指针指向换行符的时候向后退一步 | |||||
| begin++; | |||||
| break; | |||||
| } | |||||
| //向前进一步 | |||||
| begin--; | |||||
| } | |||||
| //最后end获取到段落的起始点,begin是段落的终止点。 | |||||
| //当越界的时候,保证begin在章节内 | |||||
| if (begin < 0){ | |||||
| begin = 0;//在章节内 | |||||
| position = -1; //越界 | |||||
| } | |||||
| int size = end+1 - begin; | |||||
| return new String(array,begin,size); | |||||
| } | |||||
| //获取下一段 | |||||
| public String getNextPara(){ | |||||
| //首先判断是否Position已经达到终点位置 | |||||
| if (position >= chapterLen){ | |||||
| return null; | |||||
| } | |||||
| //初始化起始点,终止点。 | |||||
| int begin = (int)position; | |||||
| int end = begin; | |||||
| char[] array = getContent(); | |||||
| while (end < chapterLen) { //判断指针是否在章节的末尾位置 | |||||
| char character = array[end]; //获取当前指针下的字符 | |||||
| //判断当前字符是否为换行,如果为换行,就代表获取到了一个段落,并退出。 | |||||
| //有可能发生初始指针指的就是换行符的情况。 | |||||
| //这里当遇到\n的时候,不需要回退 | |||||
| if ((character+"").equals("\n") && begin != end){ | |||||
| ++end;//指向下一字段 | |||||
| position = end; | |||||
| break; | |||||
| } | |||||
| //指向下一字段 | |||||
| end++; | |||||
| } | |||||
| //所要获取的字段的长度 | |||||
| int size = end - begin; | |||||
| return new String(array,begin,size); | |||||
| } | |||||
| //获取章节的内容 | |||||
| public char[] getContent() { | |||||
| if (cacheMap.size() == 0){ | |||||
| return new char[1]; | |||||
| } | |||||
| char[] block = cacheMap.get(chapterName).getData().get(); | |||||
| if (block == null) { | |||||
| File file = getBookFile(bookId, chapterName); | |||||
| block = FileUtils.getFileContent(file).toCharArray(); | |||||
| Cache cache = cacheMap.get(chapterName); | |||||
| cache.data = new WeakReference<char[]>(block); | |||||
| } | |||||
| return block; | |||||
| } | |||||
| public long getChapterLen(){ | |||||
| return chapterLen; | |||||
| } | |||||
| public void clear(){ | |||||
| cacheMap.clear(); | |||||
| position = 0; | |||||
| chapterLen = 0; | |||||
| } | |||||
| /** | |||||
| * 创建或获取存储文件 | |||||
| * @param folderName | |||||
| * @param fileName | |||||
| * @return | |||||
| */ | |||||
| public static File getBookFile(String folderName, String fileName){ | |||||
| return FileUtils.getFile(Constant.BOOK_CACHE_PATH + folderName | |||||
| + File.separator + fileName + FileUtils.SUFFIX_NB); | |||||
| } | |||||
| public static long getBookSize(String folderName){ | |||||
| return FileUtils.getDirSize(FileUtils | |||||
| .getFolder(Constant.BOOK_CACHE_PATH + folderName)); | |||||
| } | |||||
| /** | |||||
| * 根据文件名判断是否被缓存过 (因为可能数据库显示被缓存过,但是文件中却没有的情况,所以需要根据文件判断是否被缓存 | |||||
| * 过) | |||||
| * @param folderName : bookId | |||||
| * @param fileName: chapterName | |||||
| * @return | |||||
| */ | |||||
| public static boolean isChapterCached(String folderName, String fileName){ | |||||
| File file = new File(Constant.BOOK_CACHE_PATH + folderName | |||||
| + File.separator + fileName + FileUtils.SUFFIX_NB); | |||||
| return file.exists(); | |||||
| } | |||||
| public class Cache { | |||||
| private long size; | |||||
| private WeakReference<char[]> data; | |||||
| public WeakReference<char[]> getData() { | |||||
| return data; | |||||
| } | |||||
| public void setData(WeakReference<char[]> data) { | |||||
| this.data = data; | |||||
| } | |||||
| public long getSize() { | |||||
| return size; | |||||
| } | |||||
| public void setSize(long size) { | |||||
| this.size = size; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,108 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import android.app.Activity; | |||||
| import android.content.ContentResolver; | |||||
| import android.provider.Settings; | |||||
| import android.util.Log; | |||||
| import android.view.WindowManager; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-19. | |||||
| * 调节亮度的工具类 | |||||
| */ | |||||
| public class BrightnessUtils { | |||||
| private static final String TAG = "BrightnessUtils"; | |||||
| /** | |||||
| * 判断是否开启了自动亮度调节 | |||||
| */ | |||||
| public static boolean isAutoBrightness(Activity activity) { | |||||
| boolean isAuto = false; | |||||
| try { | |||||
| isAuto = Settings.System.getInt(activity.getContentResolver(), | |||||
| Settings.System.SCREEN_BRIGHTNESS_MODE) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC; | |||||
| } catch (Settings.SettingNotFoundException e){ | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return isAuto; | |||||
| } | |||||
| /** | |||||
| * 获取屏幕的亮度 | |||||
| * 系统亮度模式中,自动模式与手动模式获取到的系统亮度的值不同 | |||||
| */ | |||||
| public static int getScreenBrightness(Activity activity) { | |||||
| if(isAutoBrightness(activity)){ | |||||
| return getAutoScreenBrightness(activity); | |||||
| }else{ | |||||
| return getManualScreenBrightness(activity); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 获取手动模式下的屏幕亮度 | |||||
| * @return value:0~255 | |||||
| */ | |||||
| public static int getManualScreenBrightness(Activity activity) { | |||||
| int nowBrightnessValue = 0; | |||||
| ContentResolver resolver = activity.getContentResolver(); | |||||
| try { | |||||
| nowBrightnessValue = Settings.System.getInt(resolver, Settings.System.SCREEN_BRIGHTNESS); | |||||
| } catch (Exception e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return nowBrightnessValue; | |||||
| } | |||||
| /** | |||||
| * 获取自动模式下的屏幕亮度 | |||||
| * @return value:0~255 | |||||
| */ | |||||
| public static int getAutoScreenBrightness(Activity activity) { | |||||
| float nowBrightnessValue = 0; | |||||
| //获取自动调节下的亮度范围在 0~1 之间 | |||||
| ContentResolver resolver = activity.getContentResolver(); | |||||
| try { | |||||
| nowBrightnessValue = Settings.System.getFloat(resolver, Settings.System.SCREEN_BRIGHTNESS); | |||||
| Log.d(TAG, "getAutoScreenBrightness: " + nowBrightnessValue); | |||||
| } catch (Exception e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| //转换范围为 (0~255) | |||||
| float fValue = nowBrightnessValue * 225.0f; | |||||
| Log.d(TAG,"brightness: " + fValue); | |||||
| return (int)fValue; | |||||
| } | |||||
| /** | |||||
| * 设置亮度:通过设置 Windows 的 screenBrightness 来修改当前 Windows 的亮度 | |||||
| * lp.screenBrightness:参数范围为 0~1 | |||||
| */ | |||||
| public static void setBrightness(Activity activity, int brightness) { | |||||
| try{ | |||||
| WindowManager.LayoutParams lp = activity.getWindow().getAttributes(); | |||||
| //将 0~255 范围内的数据,转换为 0~1 | |||||
| lp.screenBrightness = Float.valueOf(brightness) * (1f / 255f); | |||||
| Log.d(TAG, "lp.screenBrightness == " + lp.screenBrightness); | |||||
| activity.getWindow().setAttributes(lp); | |||||
| }catch(Exception ex){ | |||||
| ex.printStackTrace(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 获取当前系统的亮度 | |||||
| * @param activity | |||||
| */ | |||||
| public static void setDefaultBrightness(Activity activity) { | |||||
| try { | |||||
| WindowManager.LayoutParams lp = activity.getWindow().getAttributes(); | |||||
| lp.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE; | |||||
| activity.getWindow().setAttributes(lp); | |||||
| } catch (Exception ex) { | |||||
| ex.printStackTrace(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,22 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| /** | |||||
| * 编码类型 | |||||
| */ | |||||
| public enum Charset { | |||||
| UTF8("UTF-8"), | |||||
| UTF16LE("UTF-16LE"), | |||||
| UTF16BE("UTF-16BE"), | |||||
| GBK("GBK"); | |||||
| private String mName; | |||||
| public static final byte BLANK = 0x0a; | |||||
| private Charset(String name) { | |||||
| mName = name; | |||||
| } | |||||
| public String getName() { | |||||
| return mName; | |||||
| } | |||||
| } | |||||
| @@ -1,101 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import androidx.annotation.StringDef; | |||||
| import java.io.File; | |||||
| import java.lang.annotation.Retention; | |||||
| import java.lang.annotation.RetentionPolicy; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-16. | |||||
| */ | |||||
| public class Constant { | |||||
| /*SharedPreference*/ | |||||
| public static final String SHARED_SEX = "sex"; | |||||
| public static final String SHARED_SAVE_BOOK_SORT = "book_sort"; | |||||
| public static final String SHARED_SAVE_BILLBOARD = "billboard"; | |||||
| public static final String SHARED_CONVERT_TYPE = "convert_type"; | |||||
| public static final String SEX_BOY = "boy"; | |||||
| public static final String SEX_GIRL = "girl"; | |||||
| /*URL_BASE*/ | |||||
| public static final String API_BASE_URL = "http://api.zhuishushenqi.com"; | |||||
| public static final String IMG_BASE_URL = "http://statics.zhuishushenqi.com"; | |||||
| //book type | |||||
| public static final String BOOK_TYPE_COMMENT = "normal"; | |||||
| public static final String BOOK_TYPE_VOTE = "vote"; | |||||
| //book state | |||||
| public static final String BOOK_STATE_NORMAL = "normal"; | |||||
| public static final String BOOK_STATE_DISTILLATE = "distillate"; | |||||
| //Book Date Convert Format | |||||
| public static final String FORMAT_BOOK_DATE = "yyyy-MM-dd'T'HH:mm:ss"; | |||||
| public static final String FORMAT_TIME = "HH:mm"; | |||||
| public static final String FORMAT_FILE_DATE = "yyyy-MM-dd"; | |||||
| //RxBus | |||||
| public static final int MSG_SELECTOR = 1; | |||||
| //BookCachePath (因为getCachePath引用了Context,所以必须是静态变量,不能够是静态常量) | |||||
| public static String BOOK_CACHE_PATH = FileUtils.getCachePath()+File.separator | |||||
| + "book_cache"+ File.separator ; | |||||
| //文件阅读记录保存的路径 | |||||
| public static String BOOK_RECORD_PATH = FileUtils.getCachePath() + File.separator | |||||
| + "book_record" + File.separator; | |||||
| //BookType | |||||
| @StringDef({ | |||||
| BookType.ALL, | |||||
| BookType.XHQH, | |||||
| BookType.WXXX, | |||||
| BookType.DSYN, | |||||
| BookType.LSJS, | |||||
| BookType.YXJJ, | |||||
| BookType.KHLY, | |||||
| BookType.CYJK, | |||||
| BookType.HMZC, | |||||
| BookType.XDYQ, | |||||
| BookType.GDYQ, | |||||
| BookType.HXYQ, | |||||
| BookType.DMTR | |||||
| }) | |||||
| @Retention(RetentionPolicy.SOURCE) | |||||
| public @interface BookType { | |||||
| String ALL = "all"; | |||||
| String XHQH = "xhqh"; | |||||
| String WXXX = "wxxx"; | |||||
| String DSYN = "dsyn"; | |||||
| String LSJS = "lsjs"; | |||||
| String YXJJ = "yxjj"; | |||||
| String KHLY = "khly"; | |||||
| String CYJK = "cyjk"; | |||||
| String HMZC = "hmzc"; | |||||
| String XDYQ = "xdyq"; | |||||
| String GDYQ = "gdyq"; | |||||
| String HXYQ = "hxyq"; | |||||
| String DMTR = "dmtr"; | |||||
| } | |||||
| public static Map<String, String> bookType = new HashMap<String, String>() {{ | |||||
| put("qt", "其他"); | |||||
| put(BookType.XHQH, "玄幻奇幻"); | |||||
| put(BookType.WXXX, "武侠仙侠"); | |||||
| put(BookType.DSYN, "都市异能"); | |||||
| put(BookType.LSJS, "历史军事"); | |||||
| put(BookType.YXJJ, "游戏竞技"); | |||||
| put(BookType.KHLY, "科幻灵异"); | |||||
| put(BookType.CYJK, "穿越架空"); | |||||
| put(BookType.HMZC, "豪门总裁"); | |||||
| put(BookType.XDYQ, "现代言情"); | |||||
| put(BookType.GDYQ, "古代言情"); | |||||
| put(BookType.HXYQ, "幻想言情"); | |||||
| put(BookType.DMTR, "耽美同人"); | |||||
| }}; | |||||
| } | |||||
| @@ -1,49 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import java.io.File; | |||||
| import java.util.List; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-28. | |||||
| */ | |||||
| public class FileStack { | |||||
| private Node node = null; | |||||
| private int count = 0; | |||||
| public void push(FileSnapshot fileSnapshot){ | |||||
| if (fileSnapshot == null) return; | |||||
| Node fileNode = new Node(); | |||||
| fileNode.fileSnapshot = fileSnapshot; | |||||
| fileNode.next = node; | |||||
| node = fileNode; | |||||
| ++count; | |||||
| } | |||||
| public FileSnapshot pop(){ | |||||
| Node fileNode = node; | |||||
| if (fileNode == null) return null; | |||||
| FileSnapshot fileSnapshot = fileNode.fileSnapshot; | |||||
| node = fileNode.next; | |||||
| --count; | |||||
| return fileSnapshot; | |||||
| } | |||||
| public int getSize(){ | |||||
| return count; | |||||
| } | |||||
| //节点 | |||||
| public class Node { | |||||
| FileSnapshot fileSnapshot; | |||||
| Node next; | |||||
| } | |||||
| //文件快照 | |||||
| public static class FileSnapshot{ | |||||
| public String filePath; | |||||
| public List<File> files; | |||||
| public int scrollOffset; | |||||
| } | |||||
| } | |||||
| @@ -1,328 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import android.os.Environment; | |||||
| import android.util.Log; | |||||
| import com.yzx.webebook.App; | |||||
| import java.io.BufferedInputStream; | |||||
| import java.io.BufferedReader; | |||||
| import java.io.File; | |||||
| import java.io.FileInputStream; | |||||
| import java.io.FileNotFoundException; | |||||
| import java.io.FileReader; | |||||
| import java.io.IOException; | |||||
| import java.io.RandomAccessFile; | |||||
| import java.io.Reader; | |||||
| import java.text.DecimalFormat; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| import io.reactivex.Single; | |||||
| import io.reactivex.SingleEmitter; | |||||
| import io.reactivex.SingleOnSubscribe; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-11. | |||||
| */ | |||||
| public class FileUtils { | |||||
| //采用自己的格式去设置文件,防止文件被系统文件查询到 | |||||
| public static final String SUFFIX_NB = ".nb"; | |||||
| public static final String SUFFIX_TXT = ".txt"; | |||||
| public static final String SUFFIX_EPUB = ".epub"; | |||||
| public static final String SUFFIX_PDF = ".pdf"; | |||||
| //获取文件夹 | |||||
| public static File getFolder(String filePath){ | |||||
| File file = new File(filePath); | |||||
| //如果文件夹不存在,就创建它 | |||||
| if (!file.exists()){ | |||||
| file.mkdirs(); | |||||
| } | |||||
| return file; | |||||
| } | |||||
| //获取文件 | |||||
| public static synchronized File getFile(String filePath){ | |||||
| File file = new File(filePath); | |||||
| try { | |||||
| if (!file.exists()){ | |||||
| //创建父类文件夹 | |||||
| getFolder(file.getParent()); | |||||
| //创建文件 | |||||
| file.createNewFile(); | |||||
| } | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return file; | |||||
| } | |||||
| //获取Cache文件夹 | |||||
| public static String getCachePath(){ | |||||
| if (isSdCardExist()){ | |||||
| return App.Companion.getContext() | |||||
| .getExternalCacheDir() | |||||
| .getAbsolutePath(); | |||||
| } | |||||
| else{ | |||||
| return App.Companion.getContext() | |||||
| .getCacheDir() | |||||
| .getAbsolutePath(); | |||||
| } | |||||
| } | |||||
| public static long getDirSize(File file){ | |||||
| //判断文件是否存在 | |||||
| if (file.exists()) { | |||||
| //如果是目录则递归计算其内容的总大小 | |||||
| if (file.isDirectory()) { | |||||
| File[] children = file.listFiles(); | |||||
| long size = 0; | |||||
| for (File f : children) | |||||
| size += getDirSize(f); | |||||
| return size; | |||||
| } else { | |||||
| return file.length(); | |||||
| } | |||||
| } else { | |||||
| return 0; | |||||
| } | |||||
| } | |||||
| public static String getFileSize(long size) { | |||||
| if (size <= 0) return "0"; | |||||
| final String[] units = new String[]{"b", "kb", "M", "G", "T"}; | |||||
| //计算单位的,原理是利用lg,公式是 lg(1024^n) = nlg(1024),最后 nlg(1024)/lg(1024) = n。 | |||||
| int digitGroups = (int) (Math.log10(size) / Math.log10(1024)); | |||||
| //计算原理是,size/单位值。单位值指的是:比如说b = 1024,KB = 1024^2 | |||||
| return new DecimalFormat("#,##0.##").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; | |||||
| } | |||||
| /** | |||||
| * 本来是获取File的内容的。但是为了解决文本缩进、换行的问题 | |||||
| * 这个方法就是专门用来获取书籍的... | |||||
| * | |||||
| * 应该放在BookRepository中。。。 | |||||
| * @param file | |||||
| * @return | |||||
| */ | |||||
| public static String getFileContent(File file){ | |||||
| Reader reader = null; | |||||
| String str = null; | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| try { | |||||
| reader = new FileReader(file); | |||||
| BufferedReader br = new BufferedReader(reader); | |||||
| while ((str = br.readLine()) != null){ | |||||
| //过滤空语句 | |||||
| if (!str.equals("")){ | |||||
| //由于sb会自动过滤\n,所以需要加上去 | |||||
| sb.append(" "+str+"\n"); | |||||
| } | |||||
| } | |||||
| } catch (FileNotFoundException e) { | |||||
| e.printStackTrace(); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| }finally { | |||||
| IOUtils.close(reader); | |||||
| } | |||||
| return sb.toString(); | |||||
| } | |||||
| //判断是否挂载了SD卡 | |||||
| public static boolean isSdCardExist(){ | |||||
| if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){ | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| //递归删除文件夹下的数据 | |||||
| public static synchronized void deleteFile(String filePath){ | |||||
| File file = new File(filePath); | |||||
| if (!file.exists()) return; | |||||
| if (file.isDirectory()){ | |||||
| File[] files = file.listFiles(); | |||||
| for (File subFile : files){ | |||||
| String path = subFile.getPath(); | |||||
| deleteFile(path); | |||||
| } | |||||
| } | |||||
| //删除文件 | |||||
| file.delete(); | |||||
| } | |||||
| //由于递归的耗时问题,取巧只遍历内部三层 | |||||
| //获取txt文件 | |||||
| public static List<File> getTxtFiles(String filePath,int layer){ | |||||
| List txtFiles = new ArrayList(); | |||||
| File file = new File(filePath); | |||||
| //如果层级为 3,则直接返回 | |||||
| if (layer == 3){ | |||||
| return txtFiles; | |||||
| } | |||||
| //获取文件夹 | |||||
| File[] dirs = file.listFiles( | |||||
| pathname -> { | |||||
| if (pathname.isDirectory() && !pathname.getName().startsWith(".")) { | |||||
| return true; | |||||
| } | |||||
| //获取txt文件 | |||||
| else if(pathname.getName().endsWith(".txt")){ | |||||
| txtFiles.add(pathname); | |||||
| return false; | |||||
| } | |||||
| else{ | |||||
| return false; | |||||
| } | |||||
| } | |||||
| ); | |||||
| //遍历文件夹 | |||||
| for (File dir : dirs){ | |||||
| //递归遍历txt文件 | |||||
| txtFiles.addAll(getTxtFiles(dir.getPath(),layer + 1)); | |||||
| } | |||||
| return txtFiles; | |||||
| } | |||||
| //由于遍历比较耗时 | |||||
| public static Single<List<File>> getSDTxtFile(){ | |||||
| //外部存储卡路径 | |||||
| String rootPath = Environment.getExternalStorageDirectory().getPath(); | |||||
| return Single.create(new SingleOnSubscribe<List<File>>() { | |||||
| @Override | |||||
| public void subscribe(SingleEmitter<List<File>> e) throws Exception { | |||||
| List<File> files = getTxtFiles(rootPath,0); | |||||
| e.onSuccess(files); | |||||
| } | |||||
| }); | |||||
| } | |||||
| //获取文件的编码格式 | |||||
| public static Charset getCharset(String fileName) { | |||||
| BufferedInputStream bis = null; | |||||
| Charset charset = Charset.GBK; | |||||
| byte[] first3Bytes = new byte[3]; | |||||
| try { | |||||
| boolean checked = false; | |||||
| bis = new BufferedInputStream(new FileInputStream(fileName)); | |||||
| bis.mark(0); | |||||
| int read = bis.read(first3Bytes, 0, 3); | |||||
| if (read == -1) | |||||
| return charset; | |||||
| if (first3Bytes[0] == (byte) 0xEF | |||||
| && first3Bytes[1] == (byte) 0xBB | |||||
| && first3Bytes[2] == (byte) 0xBF) { | |||||
| charset = Charset.UTF8; | |||||
| checked = true; | |||||
| } | |||||
| /* | |||||
| * 不支持 UTF16LE 和 UTF16BE | |||||
| else if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) { | |||||
| charset = Charset.UTF16LE; | |||||
| checked = true; | |||||
| } else if (first3Bytes[0] == (byte) 0xFE | |||||
| && first3Bytes[1] == (byte) 0xFF) { | |||||
| charset = Charset.UTF16BE; | |||||
| checked = true; | |||||
| } else */ | |||||
| bis.mark(0); | |||||
| if (!checked) { | |||||
| while ((read = bis.read()) != -1) { | |||||
| if (read >= 0xF0) | |||||
| break; | |||||
| if (0x80 <= read && read <= 0xBF) // 单独出现BF以下的,也算是GBK | |||||
| break; | |||||
| if (0xC0 <= read && read <= 0xDF) { | |||||
| read = bis.read(); | |||||
| if (0x80 <= read && read <= 0xBF) // 双字节 (0xC0 - 0xDF) | |||||
| // (0x80 - 0xBF),也可能在GB编码内 | |||||
| continue; | |||||
| else | |||||
| break; | |||||
| } else if (0xE0 <= read && read <= 0xEF) {// 也有可能出错,但是几率较小 | |||||
| read = bis.read(); | |||||
| if (0x80 <= read && read <= 0xBF) { | |||||
| read = bis.read(); | |||||
| if (0x80 <= read && read <= 0xBF) { | |||||
| charset = Charset.UTF8; | |||||
| break; | |||||
| } else | |||||
| break; | |||||
| } else | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| } catch (Exception e) { | |||||
| e.printStackTrace(); | |||||
| } finally { | |||||
| IOUtils.close(bis); | |||||
| } | |||||
| return charset; | |||||
| } | |||||
| // 将字符串写入到文本文件中 | |||||
| public static String writeTxtToFile(String strcontent, String filePath, String fileName) { | |||||
| //生成文件夹之后,再生成文件,不然会出错 | |||||
| makeFilePath(filePath, fileName); | |||||
| String strFilePath = filePath + fileName; | |||||
| // 每次写入时,都换行写 | |||||
| String strContent = strcontent + "\r\n"; | |||||
| try { | |||||
| File file = new File(strFilePath); | |||||
| if (!file.exists()) { | |||||
| Log.d("TestFile", "Create the file:" + strFilePath); | |||||
| file.getParentFile().mkdirs(); | |||||
| file.createNewFile(); | |||||
| } | |||||
| RandomAccessFile raf = new RandomAccessFile(file, "rwd"); | |||||
| raf.seek(file.length()); | |||||
| raf.write(strContent.getBytes()); | |||||
| raf.close(); | |||||
| return strFilePath; | |||||
| } catch (Exception e) { | |||||
| Log.e("TestFile", "Error on write File:" + e); | |||||
| return ""; | |||||
| } | |||||
| } | |||||
| //生成文件 | |||||
| public static File makeFilePath(String filePath, String fileName) { | |||||
| File file = null; | |||||
| makeRootDirectory(filePath); | |||||
| try { | |||||
| file = new File(filePath + fileName); | |||||
| if (!file.exists()) { | |||||
| file.createNewFile(); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return file; | |||||
| } | |||||
| //生成文件夹 | |||||
| public static void makeRootDirectory(String filePath) { | |||||
| File file = null; | |||||
| try { | |||||
| file = new File(filePath); | |||||
| if (!file.exists()) { | |||||
| file.mkdir(); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| Log.i("error:", e + ""); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,58 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import com.google.gson.Gson; | |||||
| import com.google.gson.JsonArray; | |||||
| import com.google.gson.JsonElement; | |||||
| import com.google.gson.JsonParser; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| /** | |||||
| * Created by andrew on 2016/8/15 0015. | |||||
| */ | |||||
| public class GsonHelper { | |||||
| public static String toJson(Object src){ | |||||
| try { | |||||
| return new Gson().toJson(src); | |||||
| } catch (Exception e){ | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| public static <T> T fromJson(String json, Class<T> clazz) { | |||||
| try { | |||||
| return new Gson().fromJson(json, clazz); | |||||
| } catch (Exception e){ | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| public static <T> List<T> fromJsonArray(String json, Class<T> clazz) { | |||||
| try { | |||||
| List<T> lst = new ArrayList<T>(); | |||||
| JsonArray array = new JsonParser().parse(json).getAsJsonArray(); | |||||
| for(final JsonElement elem : array){ | |||||
| lst.add(new Gson().fromJson(elem, clazz)); | |||||
| } | |||||
| return lst; | |||||
| } catch (Exception e){ | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| public static <T> T fromJsonObject(String json, Class<T> clazz) { | |||||
| try { | |||||
| JsonElement elem = new JsonParser().parse(json).getAsJsonObject(); | |||||
| return new Gson().fromJson(elem, clazz); | |||||
| } catch (Exception e){ | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -1,21 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import java.io.Closeable; | |||||
| import java.io.IOException; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-11. | |||||
| */ | |||||
| public class IOUtils { | |||||
| public static void close(Closeable closeable){ | |||||
| if (closeable == null) return; | |||||
| try { | |||||
| closeable.close(); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| //close error | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,2 +0,0 @@ | |||||
| package com.yzx.webebook.utils | |||||
| @@ -1,204 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import android.text.TextUtils; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| /** | |||||
| * List Utils | |||||
| * | |||||
| * @author andrew 2015-9-2 | |||||
| */ | |||||
| public class ListUtils { | |||||
| /** default join separator **/ | |||||
| public static final String DEFAULT_JOIN_SEPARATOR = ","; | |||||
| private ListUtils() { | |||||
| throw new AssertionError(); | |||||
| } | |||||
| /** | |||||
| * get size of list | |||||
| * | |||||
| * <pre> | |||||
| * getSize(null) = 0; | |||||
| * getSize({}) = 0; | |||||
| * getSize({1}) = 1; | |||||
| * </pre> | |||||
| * | |||||
| * @param <V> | |||||
| * @param sourceList | |||||
| * @return if list is null or empty, return 0, else return {@link List#size()}. | |||||
| */ | |||||
| public static <V> int getSize(List<V> sourceList) { | |||||
| return sourceList == null ? 0 : sourceList.size(); | |||||
| } | |||||
| /** | |||||
| * is null or its size is 0 | |||||
| * | |||||
| * <pre> | |||||
| * isEmpty(null) = true; | |||||
| * isEmpty({}) = true; | |||||
| * isEmpty({1}) = false; | |||||
| * </pre> | |||||
| * | |||||
| * @param <V> | |||||
| * @param sourceList | |||||
| * @return if list is null or its size is 0, return true, else return false. | |||||
| */ | |||||
| public static <V> boolean isEmpty(List<V> sourceList) { | |||||
| return (sourceList == null || sourceList.size() == 0); | |||||
| } | |||||
| /** | |||||
| * join list to string, separator is "," | |||||
| * | |||||
| * <pre> | |||||
| * join(null) = ""; | |||||
| * join({}) = ""; | |||||
| * join({a,b}) = "a,b"; | |||||
| * </pre> | |||||
| * | |||||
| * @param list | |||||
| * @return join list to string, separator is ",". if list is empty, return "" | |||||
| */ | |||||
| public static String join(List<String> list) { | |||||
| return join(list, DEFAULT_JOIN_SEPARATOR); | |||||
| } | |||||
| /** | |||||
| * join list to string | |||||
| * | |||||
| * <pre> | |||||
| * join(null, '#') = ""; | |||||
| * join({}, '#') = ""; | |||||
| * join({a,b,c}, ' ') = "abc"; | |||||
| * join({a,b,c}, '#') = "a#b#c"; | |||||
| * </pre> | |||||
| * | |||||
| * @param list | |||||
| * @param separator | |||||
| * @return join list to string. if list is empty, return "" | |||||
| */ | |||||
| public static String join(List<String> list, char separator) { | |||||
| return join(list, new String(new char[] {separator})); | |||||
| } | |||||
| /** | |||||
| * join list to string. if separator is null, use {@link #DEFAULT_JOIN_SEPARATOR} | |||||
| * | |||||
| * <pre> | |||||
| * join(null, "#") = ""; | |||||
| * join({}, "#$") = ""; | |||||
| * join({a,b,c}, null) = "a,b,c"; | |||||
| * join({a,b,c}, "") = "abc"; | |||||
| * join({a,b,c}, "#") = "a#b#c"; | |||||
| * join({a,b,c}, "#$") = "a#$b#$c"; | |||||
| * </pre> | |||||
| * | |||||
| * @param list | |||||
| * @param separator | |||||
| * @return join list to string with separator. if list is empty, return "" | |||||
| */ | |||||
| public static String join(List<String> list, String separator) { | |||||
| return list == null ? "" : TextUtils.join(separator, list); | |||||
| } | |||||
| /** | |||||
| * add distinct entry to list | |||||
| * | |||||
| * @param <V> | |||||
| * @param sourceList | |||||
| * @param entry | |||||
| * @return if entry already exist in sourceList, return false, else add it and return true. | |||||
| */ | |||||
| public static <V> boolean addDistinctEntry(List<V> sourceList, V entry) { | |||||
| return (sourceList != null && !sourceList.contains(entry)) ? sourceList.add(entry) : false; | |||||
| } | |||||
| /** | |||||
| * add all distinct entry to list1 from list2 | |||||
| * | |||||
| * @param <V> | |||||
| * @param sourceList | |||||
| * @param entryList | |||||
| * @return the count of entries be added | |||||
| */ | |||||
| public static <V> int addDistinctList(List<V> sourceList, List<V> entryList) { | |||||
| if (sourceList == null || isEmpty(entryList)) { | |||||
| return 0; | |||||
| } | |||||
| int sourceCount = sourceList.size(); | |||||
| for (V entry : entryList) { | |||||
| if (!sourceList.contains(entry)) { | |||||
| sourceList.add(entry); | |||||
| } | |||||
| } | |||||
| return sourceList.size() - sourceCount; | |||||
| } | |||||
| /** | |||||
| * remove duplicate entries in list | |||||
| * | |||||
| * @param <V> | |||||
| * @param sourceList | |||||
| * @return the count of entries be removed | |||||
| */ | |||||
| public static <V> int distinctList(List<V> sourceList) { | |||||
| if (isEmpty(sourceList)) { | |||||
| return 0; | |||||
| } | |||||
| int sourceCount = sourceList.size(); | |||||
| int sourceListSize = sourceList.size(); | |||||
| for (int i = 0; i < sourceListSize; i++) { | |||||
| for (int j = (i + 1); j < sourceListSize; j++) { | |||||
| if (sourceList.get(i).equals(sourceList.get(j))) { | |||||
| sourceList.remove(j); | |||||
| sourceListSize = sourceList.size(); | |||||
| j--; | |||||
| } | |||||
| } | |||||
| } | |||||
| return sourceCount - sourceList.size(); | |||||
| } | |||||
| /** | |||||
| * add not null entry to list | |||||
| * | |||||
| * @param sourceList | |||||
| * @param value | |||||
| * @return <ul> | |||||
| * <li>if sourceList is null, return false</li> | |||||
| * <li>if value is null, return false</li> | |||||
| * <li>return {@link List#add(Object)}</li> | |||||
| * </ul> | |||||
| */ | |||||
| public static <V> boolean addListNotNullValue(List<V> sourceList, V value) { | |||||
| return (sourceList != null && value != null) ? sourceList.add(value) : false; | |||||
| } | |||||
| /** | |||||
| * invert list | |||||
| * | |||||
| * @param <V> | |||||
| * @param sourceList | |||||
| * @return | |||||
| */ | |||||
| public static <V> List<V> invertList(List<V> sourceList) { | |||||
| if (isEmpty(sourceList)) { | |||||
| return sourceList; | |||||
| } | |||||
| List<V> invertList = new ArrayList<V>(sourceList.size()); | |||||
| for (int i = sourceList.size() - 1; i >= 0; i--) { | |||||
| invertList.add(sourceList.get(i)); | |||||
| } | |||||
| return invertList; | |||||
| } | |||||
| } | |||||
| @@ -1,222 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import android.content.Context; | |||||
| import android.os.Environment; | |||||
| import android.util.Log; | |||||
| import com.yzx.webebook.App; | |||||
| import java.io.BufferedWriter; | |||||
| import java.io.File; | |||||
| import java.io.FileWriter; | |||||
| import java.io.IOException; | |||||
| import java.text.SimpleDateFormat; | |||||
| import java.util.Calendar; | |||||
| import java.util.Date; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-27. | |||||
| */ | |||||
| public class LogUtils { | |||||
| private static Boolean LOG_SWITCH = true; // 日志文件总开关 | |||||
| private static Boolean LOG_TO_FILE = false; // 日志写入文件开关 | |||||
| private static String LOG_TAG = "IReader"; // 默认的tag | |||||
| private static char LOG_TYPE = 'v';// 输入日志类型,v代表输出所有信息,w则只输出警告... | |||||
| private static int LOG_SAVE_DAYS = 7;// sd卡中日志文件的最多保存天数 | |||||
| private final static SimpleDateFormat LOG_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 日志的输出格式 | |||||
| private final static SimpleDateFormat FILE_SUFFIX = new SimpleDateFormat("yyyy-MM-dd");// 日志文件格式 | |||||
| private static String LOG_FILE_PATH; // 日志文件保存路径 | |||||
| private static String LOG_FILE_NAME;// 日志文件保存名称 | |||||
| public static void init(Context context) { // 在Application中初始化 | |||||
| LOG_FILE_PATH = Environment.getExternalStorageDirectory().getPath() + File.separator + App.Companion.getContext().getPackageName(); | |||||
| LOG_FILE_NAME = "Log"; | |||||
| } | |||||
| /**************************** | |||||
| * Warn | |||||
| *********************************/ | |||||
| public static void w(Object msg) { | |||||
| w(LOG_TAG, msg); | |||||
| } | |||||
| public static void w(String tag, Object msg) { | |||||
| w(tag, msg, null); | |||||
| } | |||||
| public static void w(String tag, Object msg, Throwable tr) { | |||||
| if (msg == null) return; | |||||
| log(tag, msg.toString(), tr, 'w'); | |||||
| } | |||||
| /*************************** | |||||
| * Error | |||||
| ********************************/ | |||||
| public static void e(Object msg) { | |||||
| e(LOG_TAG, msg); | |||||
| } | |||||
| public static void e(String tag, Object msg) { | |||||
| e(tag, msg, null); | |||||
| } | |||||
| public static void e(String tag, Object msg, Throwable tr) { | |||||
| if (msg == null) return; | |||||
| log(tag, msg.toString(), tr, 'e'); | |||||
| } | |||||
| /*************************** | |||||
| * Debug | |||||
| ********************************/ | |||||
| public static void d(Object msg) { | |||||
| d(LOG_TAG, msg); | |||||
| } | |||||
| public static void d(String tag, Object msg) {// 调试信息 | |||||
| d(tag, msg, null); | |||||
| } | |||||
| public static void d(String tag, Object msg, Throwable tr) { | |||||
| if (msg == null) return; | |||||
| log(tag, msg.toString(), tr, 'd'); | |||||
| } | |||||
| /**************************** | |||||
| * Info | |||||
| *********************************/ | |||||
| public static void i(Object msg) { | |||||
| i(LOG_TAG, msg); | |||||
| } | |||||
| public static void i(String tag, Object msg) { | |||||
| i(tag, msg, null); | |||||
| } | |||||
| public static void i(String tag, Object msg, Throwable tr) { | |||||
| if (msg == null) return; | |||||
| log(tag, msg.toString(), tr, 'i'); | |||||
| } | |||||
| /************************** | |||||
| * Verbose | |||||
| ********************************/ | |||||
| public static void v(Object msg) { | |||||
| v(LOG_TAG, msg); | |||||
| } | |||||
| public static void v(String tag, Object msg) { | |||||
| v(tag, msg, null); | |||||
| } | |||||
| public static void v(String tag, Object msg, Throwable tr) { | |||||
| if (msg == null) return; | |||||
| log(tag, msg.toString(), tr, 'v'); | |||||
| } | |||||
| /** | |||||
| * 根据tag, msg和等级,输出日志 | |||||
| * | |||||
| * @param tag | |||||
| * @param msg | |||||
| * @param level | |||||
| */ | |||||
| private static void log(String tag, String msg, Throwable tr, char level) { | |||||
| if (tag == null || msg == null || tr == null) return; | |||||
| if (LOG_SWITCH) { | |||||
| if ('e' == level && ('e' == LOG_TYPE || 'v' == LOG_TYPE)) { // 输出错误信息 | |||||
| Log.e(tag, createMessage(msg), tr); | |||||
| } else if ('w' == level && ('w' == LOG_TYPE || 'v' == LOG_TYPE)) { | |||||
| Log.w(tag, createMessage(msg), tr); | |||||
| } else if ('d' == level && ('d' == LOG_TYPE || 'v' == LOG_TYPE)) { | |||||
| Log.d(tag, createMessage(msg), tr); | |||||
| } else if ('i' == level && ('d' == LOG_TYPE || 'v' == LOG_TYPE)) { | |||||
| Log.i(tag, createMessage(msg), tr); | |||||
| } else { | |||||
| Log.v(tag, createMessage(msg), tr); | |||||
| } | |||||
| if (LOG_TO_FILE) | |||||
| log2File(String.valueOf(level), tag, msg + tr == null ? "" : "\n" + Log.getStackTraceString(tr)); | |||||
| } | |||||
| } | |||||
| private static String getFunctionName() { | |||||
| StackTraceElement[] sts = Thread.currentThread().getStackTrace(); | |||||
| if (sts == null) { | |||||
| return null; | |||||
| } | |||||
| for (StackTraceElement st : sts) { | |||||
| if (st.isNativeMethod()) { | |||||
| continue; | |||||
| } | |||||
| if (st.getClassName().equals(Thread.class.getName())) { | |||||
| continue; | |||||
| } | |||||
| if (st.getFileName().equals("LogUtils.java")) { | |||||
| continue; | |||||
| } | |||||
| return "[" + Thread.currentThread().getName() + "(" | |||||
| + Thread.currentThread().getId() + "): " + st.getFileName() | |||||
| + ":" + st.getLineNumber() + "]"; | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private static String createMessage(String msg) { | |||||
| String functionName = getFunctionName(); | |||||
| String message = (functionName == null ? msg | |||||
| : (functionName + " - " + msg)); | |||||
| return message; | |||||
| } | |||||
| /** | |||||
| * 打开日志文件并写入日志 | |||||
| * | |||||
| * @return | |||||
| **/ | |||||
| private synchronized static void log2File(String mylogtype, String tag, String text) { | |||||
| Date nowtime = new Date(); | |||||
| String date = FILE_SUFFIX.format(nowtime); | |||||
| String dateLogContent = LOG_FORMAT.format(nowtime) + ":" + mylogtype + ":" + tag + ":" + text; // 日志输出格式 | |||||
| File destDir = new File(LOG_FILE_PATH); | |||||
| if (!destDir.exists()) { | |||||
| destDir.mkdirs(); | |||||
| } | |||||
| File file = new File(LOG_FILE_PATH, LOG_FILE_NAME + date); | |||||
| try { | |||||
| FileWriter filerWriter = new FileWriter(file, true); | |||||
| BufferedWriter bufWriter = new BufferedWriter(filerWriter); | |||||
| bufWriter.write(dateLogContent); | |||||
| bufWriter.newLine(); | |||||
| bufWriter.close(); | |||||
| filerWriter.close(); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 删除指定的日志文件 | |||||
| */ | |||||
| public static void delFile() {// 删除日志文件 | |||||
| String needDelFiel = FILE_SUFFIX.format(getDateBefore()); | |||||
| File file = new File(LOG_FILE_PATH, needDelFiel + LOG_FILE_NAME); | |||||
| if (file.exists()) { | |||||
| file.delete(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 得到LOG_SAVE_DAYS天前的日期 | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| private static Date getDateBefore() { | |||||
| Date nowtime = new Date(); | |||||
| Calendar now = Calendar.getInstance(); | |||||
| now.setTime(nowtime); | |||||
| now.set(Calendar.DATE, now.get(Calendar.DATE) - LOG_SAVE_DAYS); | |||||
| return now.getTime(); | |||||
| } | |||||
| } | |||||
| @@ -1,43 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| /** | |||||
| * Created by newbiechen on 2018/1/1. | |||||
| */ | |||||
| import java.security.MessageDigest; | |||||
| import java.security.NoSuchAlgorithmException; | |||||
| /** | |||||
| *@Description: 将字符串转化为MD5 | |||||
| */ | |||||
| public class MD5Utils { | |||||
| public static String strToMd5By32(String str){ | |||||
| String reStr = null; | |||||
| try { | |||||
| MessageDigest md5 = MessageDigest.getInstance("MD5"); | |||||
| byte[] bytes = md5.digest(str.getBytes()); | |||||
| StringBuffer stringBuffer = new StringBuffer(); | |||||
| for (byte b : bytes){ | |||||
| int bt = b&0xff; | |||||
| if (bt < 16){ | |||||
| stringBuffer.append(0); | |||||
| } | |||||
| stringBuffer.append(Integer.toHexString(bt)); | |||||
| } | |||||
| reStr = stringBuffer.toString(); | |||||
| } catch (NoSuchAlgorithmException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return reStr; | |||||
| } | |||||
| public static String strToMd5By16(String str){ | |||||
| String reStr = strToMd5By32(str); | |||||
| if (reStr != null){ | |||||
| reStr = reStr.substring(8, 24); | |||||
| } | |||||
| return reStr; | |||||
| } | |||||
| } | |||||
| @@ -1,63 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import android.content.Context; | |||||
| import android.net.ConnectivityManager; | |||||
| import android.net.NetworkInfo; | |||||
| import com.yzx.webebook.App; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-11. | |||||
| */ | |||||
| public class NetworkUtils { | |||||
| /** | |||||
| * 获取活动网络信息 | |||||
| * @return NetworkInfo | |||||
| */ | |||||
| public static NetworkInfo getNetworkInfo(){ | |||||
| ConnectivityManager cm = (ConnectivityManager) App.Companion | |||||
| .getContext() | |||||
| .getSystemService(Context.CONNECTIVITY_SERVICE); | |||||
| return cm.getActiveNetworkInfo(); | |||||
| } | |||||
| /** | |||||
| * 网络是否可用 | |||||
| * @return | |||||
| */ | |||||
| public static boolean isAvailable(){ | |||||
| NetworkInfo info = getNetworkInfo(); | |||||
| return info != null && info.isAvailable(); | |||||
| } | |||||
| /** | |||||
| * 网络是否连接 | |||||
| * @return | |||||
| */ | |||||
| public static boolean isConnected(){ | |||||
| NetworkInfo info = getNetworkInfo(); | |||||
| return info != null && info.isConnected(); | |||||
| } | |||||
| /** | |||||
| * 判断wifi是否连接状态 | |||||
| * <p>需添加权限 {@code <uses-permission android:name="android.permission | |||||
| * .ACCESS_NETWORK_STATE"/>}</p> | |||||
| * | |||||
| * @param context 上下文 | |||||
| * @return {@code true}: 连接<br>{@code false}: 未连接 | |||||
| */ | |||||
| public static boolean isWifiConnected(Context context) { | |||||
| ConnectivityManager cm = (ConnectivityManager) context | |||||
| .getSystemService(Context.CONNECTIVITY_SERVICE); | |||||
| return cm != null && cm.getActiveNetworkInfo() != null | |||||
| && cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI; | |||||
| } | |||||
| } | |||||
| @@ -1,34 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import android.content.Context; | |||||
| import android.content.pm.PackageManager; | |||||
| import androidx.core.content.ContextCompat; | |||||
| /** | |||||
| * Created by newbiechen on 2017/10/8. | |||||
| */ | |||||
| public class PermissionsChecker { | |||||
| private final Context mContext; | |||||
| public PermissionsChecker(Context context) { | |||||
| mContext = context.getApplicationContext(); | |||||
| } | |||||
| // 判断权限集合 | |||||
| public boolean lacksPermissions(String... permissions) { | |||||
| for (String permission : permissions) { | |||||
| if (lacksPermission(permission)) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| // 判断是否缺少权限 | |||||
| private boolean lacksPermission(String permission) { | |||||
| return ContextCompat.checkSelfPermission(mContext, permission) == | |||||
| PackageManager.PERMISSION_DENIED; | |||||
| } | |||||
| } | |||||
| @@ -1,60 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import com.yzx.webebook.model.bean.CommentBean; | |||||
| import com.yzx.webebook.model.bean.DetailBean; | |||||
| import java.util.List; | |||||
| import io.reactivex.Observable; | |||||
| import io.reactivex.ObservableSource; | |||||
| import io.reactivex.Single; | |||||
| import io.reactivex.SingleSource; | |||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | |||||
| import io.reactivex.functions.Function3; | |||||
| import io.reactivex.schedulers.Schedulers; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-29. | |||||
| */ | |||||
| public class RxUtils { | |||||
| public static <T> SingleSource<T> toSimpleSingle(Single<T> upstream){ | |||||
| return upstream.subscribeOn(Schedulers.io()) | |||||
| .observeOn(AndroidSchedulers.mainThread()); | |||||
| } | |||||
| public static <T> ObservableSource<T> toSimpleSingle(Observable<T> upstream){ | |||||
| return upstream.subscribeOn(Schedulers.io()) | |||||
| .observeOn(AndroidSchedulers.mainThread()); | |||||
| } | |||||
| public static <T,R> TwoTuple<T,R> twoTuple(T first,R second){ | |||||
| return new TwoTuple<T, R>(first, second); | |||||
| } | |||||
| public static <T> Single<DetailBean<T>> toCommentDetail(Single<T> detailSingle, | |||||
| Single<List<CommentBean>> bestCommentsSingle, | |||||
| Single<List<CommentBean>> commentsSingle){ | |||||
| return Single.zip(detailSingle, bestCommentsSingle, commentsSingle, | |||||
| new Function3<T, List<CommentBean>, List<CommentBean>, DetailBean<T>>() { | |||||
| @Override | |||||
| public DetailBean<T> apply(T t, List<CommentBean> commentBeen, | |||||
| List<CommentBean> commentBeen2) throws Exception { | |||||
| return new DetailBean<T>(t,commentBeen,commentBeen2); | |||||
| } | |||||
| }); | |||||
| } | |||||
| public static class TwoTuple<A, B> { | |||||
| public final A first; | |||||
| public final B second; | |||||
| public TwoTuple(A a, B b) { | |||||
| this.first = a; | |||||
| this.second = b; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,127 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import android.content.res.Resources; | |||||
| import android.util.DisplayMetrics; | |||||
| import android.util.TypedValue; | |||||
| import android.view.View; | |||||
| import androidx.appcompat.app.AppCompatActivity; | |||||
| import com.yzx.webebook.App; | |||||
| import java.lang.reflect.Method; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-1. | |||||
| */ | |||||
| public class ScreenUtils { | |||||
| public static int dpToPx(int dp) { | |||||
| DisplayMetrics metrics = getDisplayMetrics(); | |||||
| return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, metrics); | |||||
| } | |||||
| public static int pxToDp(int px) { | |||||
| DisplayMetrics metrics = getDisplayMetrics(); | |||||
| return (int) (px / metrics.density); | |||||
| } | |||||
| public static int spToPx(int sp) { | |||||
| DisplayMetrics metrics = getDisplayMetrics(); | |||||
| return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, metrics); | |||||
| } | |||||
| public static int pxToSp(int px) { | |||||
| DisplayMetrics metrics = getDisplayMetrics(); | |||||
| return (int) (px / metrics.scaledDensity); | |||||
| } | |||||
| /** | |||||
| * 获取手机显示App区域的大小(头部导航栏+ActionBar+根布局),不包括虚拟按钮 | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| public static int[] getAppSize() { | |||||
| int[] size = new int[2]; | |||||
| DisplayMetrics metrics = getDisplayMetrics(); | |||||
| size[0] = metrics.widthPixels; | |||||
| size[1] = metrics.heightPixels; | |||||
| return size; | |||||
| } | |||||
| /** | |||||
| * 获取整个手机屏幕的大小(包括虚拟按钮) | |||||
| * 必须在onWindowFocus方法之后使用 | |||||
| * | |||||
| * @param activity | |||||
| * @return | |||||
| */ | |||||
| public static int[] getScreenSize(AppCompatActivity activity) { | |||||
| int[] size = new int[2]; | |||||
| View decorView = activity.getWindow().getDecorView(); | |||||
| size[0] = decorView.getWidth(); | |||||
| size[1] = decorView.getHeight(); | |||||
| return size; | |||||
| } | |||||
| /** | |||||
| * 获取导航栏的高度 | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| public static int getStatusBarHeight() { | |||||
| Resources resources = App.Companion.getContext().getResources(); | |||||
| int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android"); | |||||
| return resources.getDimensionPixelSize(resourceId); | |||||
| } | |||||
| /** | |||||
| * 获取虚拟按键的高度 | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| public static int getNavigationBarHeight() { | |||||
| int navigationBarHeight = 0; | |||||
| Resources rs = App.Companion.getContext().getResources(); | |||||
| int id = rs.getIdentifier("navigation_bar_height", "dimen", "android"); | |||||
| if (id > 0 && hasNavigationBar()) { | |||||
| navigationBarHeight = rs.getDimensionPixelSize(id); | |||||
| } | |||||
| return navigationBarHeight; | |||||
| } | |||||
| /** | |||||
| * 是否存在虚拟按键 | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| private static boolean hasNavigationBar() { | |||||
| boolean hasNavigationBar = false; | |||||
| Resources rs = App.Companion.getContext().getResources(); | |||||
| int id = rs.getIdentifier("config_showNavigationBar", "bool", "android"); | |||||
| if (id > 0) { | |||||
| hasNavigationBar = rs.getBoolean(id); | |||||
| } | |||||
| try { | |||||
| Class systemPropertiesClass = Class.forName("android.os.SystemProperties"); | |||||
| Method m = systemPropertiesClass.getMethod("get", String.class); | |||||
| String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys"); | |||||
| if ("1".equals(navBarOverride)) { | |||||
| hasNavigationBar = false; | |||||
| } else if ("0".equals(navBarOverride)) { | |||||
| hasNavigationBar = true; | |||||
| } | |||||
| } catch (Exception e) { | |||||
| } | |||||
| return hasNavigationBar; | |||||
| } | |||||
| public static DisplayMetrics getDisplayMetrics() { | |||||
| DisplayMetrics metrics = App.Companion | |||||
| .getContext() | |||||
| .getResources() | |||||
| .getDisplayMetrics(); | |||||
| return metrics; | |||||
| } | |||||
| } | |||||
| @@ -1,61 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import android.content.Context; | |||||
| import android.content.SharedPreferences; | |||||
| import com.yzx.webebook.App; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-16. | |||||
| */ | |||||
| public class SharedPreUtils { | |||||
| private static final String SHARED_NAME = "IReader_pref"; | |||||
| private static SharedPreUtils sInstance; | |||||
| private SharedPreferences sharedReadable; | |||||
| private SharedPreferences.Editor sharedWritable; | |||||
| private SharedPreUtils(){ | |||||
| sharedReadable = App.Companion.getContext() | |||||
| .getSharedPreferences(SHARED_NAME, Context.MODE_MULTI_PROCESS); | |||||
| sharedWritable = sharedReadable.edit(); | |||||
| } | |||||
| public static SharedPreUtils getInstance(){ | |||||
| if(sInstance == null){ | |||||
| synchronized (SharedPreUtils.class){ | |||||
| if (sInstance == null){ | |||||
| sInstance = new SharedPreUtils(); | |||||
| } | |||||
| } | |||||
| } | |||||
| return sInstance; | |||||
| } | |||||
| public String getString(String key){ | |||||
| return sharedReadable.getString(key,""); | |||||
| } | |||||
| public void putString(String key,String value){ | |||||
| sharedWritable.putString(key,value); | |||||
| sharedWritable.commit(); | |||||
| } | |||||
| public void putInt(String key,int value){ | |||||
| sharedWritable.putInt(key, value); | |||||
| sharedWritable.commit(); | |||||
| } | |||||
| public void putBoolean(String key,boolean value){ | |||||
| sharedWritable.putBoolean(key, value); | |||||
| sharedWritable.commit(); | |||||
| } | |||||
| public int getInt(String key,int def){ | |||||
| return sharedReadable.getInt(key, def); | |||||
| } | |||||
| public boolean getBoolean(String key,boolean def){ | |||||
| return sharedReadable.getBoolean(key, def); | |||||
| } | |||||
| } | |||||
| @@ -1,190 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import android.content.Context; | |||||
| import androidx.annotation.StringRes; | |||||
| import com.yzx.webebook.App; | |||||
| import java.text.DateFormat; | |||||
| import java.text.ParseException; | |||||
| import java.text.SimpleDateFormat; | |||||
| import java.util.Calendar; | |||||
| import java.util.Date; | |||||
| //import com.zqc.opencc.android.lib.ChineseConverter; | |||||
| //import com.zqc.opencc.android.lib.ConversionType; | |||||
| /** | |||||
| * Created by newbiechen on 17-4-22. | |||||
| * 对文字操作的工具类 | |||||
| */ | |||||
| public class StringUtils { | |||||
| private static final String TAG = "StringUtils"; | |||||
| private static final int HOUR_OF_DAY = 24; | |||||
| private static final int DAY_OF_YESTERDAY = 2; | |||||
| private static final int TIME_UNIT = 60; | |||||
| //将时间转换成日期 | |||||
| public static String dateConvert(long time,String pattern){ | |||||
| Date date = new Date(time); | |||||
| SimpleDateFormat format = new SimpleDateFormat(pattern); | |||||
| return format.format(date); | |||||
| } | |||||
| //将日期转换成昨天、今天、明天 | |||||
| public static String dateConvert(String source,String pattern){ | |||||
| DateFormat format = new SimpleDateFormat(pattern); | |||||
| Calendar calendar = Calendar.getInstance(); | |||||
| try { | |||||
| Date date = format.parse(source); | |||||
| long curTime = calendar.getTimeInMillis(); | |||||
| calendar.setTime(date); | |||||
| //将MISC 转换成 sec | |||||
| long difSec = Math.abs((curTime - date.getTime())/1000); | |||||
| long difMin = difSec/60; | |||||
| long difHour = difMin/60; | |||||
| long difDate = difHour/60; | |||||
| int oldHour = calendar.get(Calendar.HOUR); | |||||
| //如果没有时间 | |||||
| if (oldHour == 0){ | |||||
| //比日期:昨天今天和明天 | |||||
| if (difDate == 0){ | |||||
| return "今天"; | |||||
| } | |||||
| else if (difDate < DAY_OF_YESTERDAY){ | |||||
| return "昨天"; | |||||
| } | |||||
| else { | |||||
| DateFormat convertFormat = new SimpleDateFormat("yyyy-MM-dd"); | |||||
| String value = convertFormat.format(date); | |||||
| return value; | |||||
| } | |||||
| } | |||||
| if (difSec < TIME_UNIT){ | |||||
| return difSec+"秒前"; | |||||
| } | |||||
| else if (difMin < TIME_UNIT){ | |||||
| return difMin+"分钟前"; | |||||
| } | |||||
| else if (difHour < HOUR_OF_DAY){ | |||||
| return difHour+"小时前"; | |||||
| } | |||||
| else if (difDate < DAY_OF_YESTERDAY){ | |||||
| return "昨天"; | |||||
| } | |||||
| else { | |||||
| DateFormat convertFormat = new SimpleDateFormat("yyyy-MM-dd"); | |||||
| String value = convertFormat.format(date); | |||||
| return value; | |||||
| } | |||||
| } catch (ParseException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return ""; | |||||
| } | |||||
| public static String toFirstCapital(String str){ | |||||
| return str.substring(0,1).toUpperCase()+str.substring(1); | |||||
| } | |||||
| public static String getString(@StringRes int id){ | |||||
| return App.Companion.getContext().getResources().getString(id); | |||||
| } | |||||
| public static String getString(@StringRes int id, Object... formatArgs){ | |||||
| return App.Companion.getContext().getResources().getString(id,formatArgs); | |||||
| } | |||||
| /** | |||||
| * 将文本中的半角字符,转换成全角字符 | |||||
| * @param input | |||||
| * @return | |||||
| */ | |||||
| public static String halfToFull(String input) | |||||
| { | |||||
| char[] c = input.toCharArray(); | |||||
| for (int i = 0; i< c.length; i++) | |||||
| { | |||||
| if (c[i] == 32) //半角空格 | |||||
| { | |||||
| c[i] = (char) 12288; | |||||
| continue; | |||||
| } | |||||
| //根据实际情况,过滤不需要转换的符号 | |||||
| //if (c[i] == 46) //半角点号,不转换 | |||||
| // continue; | |||||
| if (c[i]> 32 && c[i]< 127) //其他符号都转换为全角 | |||||
| c[i] = (char) (c[i] + 65248); | |||||
| } | |||||
| return new String(c); | |||||
| } | |||||
| //功能:字符串全角转换为半角 | |||||
| public static String fullToHalf(String input) | |||||
| { | |||||
| char[] c = input.toCharArray(); | |||||
| for (int i = 0; i< c.length; i++) | |||||
| { | |||||
| if (c[i] == 12288) //全角空格 | |||||
| { | |||||
| c[i] = (char) 32; | |||||
| continue; | |||||
| } | |||||
| if (c[i]> 65280&& c[i]< 65375) | |||||
| c[i] = (char) (c[i] - 65248); | |||||
| } | |||||
| return new String(c); | |||||
| } | |||||
| //繁簡轉換 | |||||
| public static String convertCC(String input, Context context) | |||||
| { | |||||
| // ConversionType currentConversionType = ConversionType.S2TWP; | |||||
| // int convertType = SharedPreUtils.getInstance().getInt(SHARED_READ_CONVERT_TYPE, 0); | |||||
| // | |||||
| // if (input.length() == 0) | |||||
| // return ""; | |||||
| // | |||||
| // switch (convertType) { | |||||
| // case 1: | |||||
| // currentConversionType = ConversionType.TW2SP; | |||||
| // break; | |||||
| // case 2: | |||||
| // currentConversionType = ConversionType.S2HK; | |||||
| // break; | |||||
| // case 3: | |||||
| // currentConversionType = ConversionType.S2T; | |||||
| // break; | |||||
| // case 4: | |||||
| // currentConversionType = ConversionType.S2TW; | |||||
| // break; | |||||
| // case 5: | |||||
| // currentConversionType = ConversionType.S2TWP; | |||||
| // break; | |||||
| // case 6: | |||||
| // currentConversionType = ConversionType.T2HK; | |||||
| // break; | |||||
| // case 7: | |||||
| // currentConversionType = ConversionType.T2S; | |||||
| // break; | |||||
| // case 8: | |||||
| // currentConversionType = ConversionType.T2TW; | |||||
| // break; | |||||
| // case 9: | |||||
| // currentConversionType = ConversionType.TW2S; | |||||
| // break; | |||||
| // case 10: | |||||
| // currentConversionType = ConversionType.HK2S; | |||||
| // break; | |||||
| // } | |||||
| // return (convertType != 0)?ChineseConverter.convert(input, currentConversionType, context):input; | |||||
| return input; | |||||
| } | |||||
| } | |||||
| @@ -1,162 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import android.app.Activity; | |||||
| import android.os.Build; | |||||
| import android.view.View; | |||||
| import android.view.WindowManager; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-16. | |||||
| * 基于 Android 4.4 | |||||
| * | |||||
| * 主要参数说明: | |||||
| * | |||||
| * SYSTEM_UI_FLAG_FULLSCREEN : 隐藏StatusBar | |||||
| * SYSTEM_UI_FLAG_HIDE_NAVIGATION : 隐藏NavigationBar | |||||
| * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN: 视图扩展到StatusBar的位置,并且StatusBar不消失。 | |||||
| * 这里需要一些处理,一般是将StatusBar设置为全透明或者半透明。之后还需要使用fitSystemWindows=防止视图扩展到Status | |||||
| * Bar上面(会在StatusBar上加一层View,该View可被移动) | |||||
| * SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION: 视图扩展到NavigationBar的位置 | |||||
| * SYSTEM_UI_FLAG_LAYOUT_STABLE:稳定效果 | |||||
| * SYSTEM_UI_FLAG_IMMERSIVE_STICKY:保证点击任意位置不会退出 | |||||
| * | |||||
| * 可设置特效说明: | |||||
| * 1. 全屏特效 | |||||
| * 2. 全屏点击不退出特效 | |||||
| * 3. 注意在19 <=sdk <=21 时候,必须通过Window设置透明栏 | |||||
| */ | |||||
| public class SystemBarUtils { | |||||
| private static final int UNSTABLE_STATUS = View.SYSTEM_UI_FLAG_FULLSCREEN; | |||||
| private static final int UNSTABLE_NAV = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; | |||||
| private static final int STABLE_STATUS = View.SYSTEM_UI_FLAG_FULLSCREEN | | |||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | | |||||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE | | |||||
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; | |||||
| private static final int STABLE_NAV = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | | |||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | | |||||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE | | |||||
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; | |||||
| private static final int EXPAND_STATUS = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | |||||
| | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; | |||||
| private static final int EXPAND_NAV = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | |||||
| | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; | |||||
| //设置隐藏StatusBar(点击任意地方会恢复) | |||||
| public static void hideUnStableStatusBar(Activity activity){ | |||||
| //App全屏,隐藏StatusBar | |||||
| setFlag(activity,UNSTABLE_STATUS); | |||||
| } | |||||
| public static void showUnStableStatusBar(Activity activity){ | |||||
| clearFlag(activity,UNSTABLE_STATUS); | |||||
| } | |||||
| //隐藏NavigationBar(点击任意地方会恢复) | |||||
| public static void hideUnStableNavBar(Activity activity){ | |||||
| setFlag(activity,UNSTABLE_NAV); | |||||
| } | |||||
| public static void showUnStableNavBar(Activity activity){ | |||||
| clearFlag(activity,UNSTABLE_NAV); | |||||
| } | |||||
| public static void hideStableStatusBar(Activity activity){ | |||||
| //App全屏,隐藏StatusBar | |||||
| setFlag(activity,STABLE_STATUS); | |||||
| } | |||||
| public static void showStableStatusBar(Activity activity){ | |||||
| clearFlag(activity,STABLE_STATUS); | |||||
| } | |||||
| public static void hideStableNavBar(Activity activity){ | |||||
| //App全屏,隐藏StatusBar | |||||
| setFlag(activity,STABLE_NAV); | |||||
| } | |||||
| public static void showStableNavBar(Activity activity){ | |||||
| clearFlag(activity,STABLE_NAV); | |||||
| } | |||||
| /** | |||||
| * 视图扩充到StatusBar | |||||
| */ | |||||
| public static void expandStatusBar(Activity activity){ | |||||
| setFlag(activity, EXPAND_STATUS); | |||||
| } | |||||
| /** | |||||
| * 视图扩充到NavBar | |||||
| * @param activity | |||||
| */ | |||||
| public static void expandNavBar(Activity activity){ | |||||
| setFlag(activity, EXPAND_NAV); | |||||
| } | |||||
| public static void transparentStatusBar(Activity activity){ | |||||
| if (Build.VERSION.SDK_INT >= 21){ | |||||
| expandStatusBar(activity); | |||||
| activity.getWindow() | |||||
| .setStatusBarColor(activity.getResources().getColor(android.R.color.transparent)); | |||||
| } | |||||
| else if (Build.VERSION.SDK_INT >= 19){ | |||||
| WindowManager.LayoutParams attrs = activity.getWindow().getAttributes(); | |||||
| attrs.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | attrs.flags); | |||||
| activity.getWindow().setAttributes(attrs); | |||||
| } | |||||
| } | |||||
| public static void transparentNavBar(Activity activity){ | |||||
| if (Build.VERSION.SDK_INT >= 21){ | |||||
| expandNavBar(activity); | |||||
| //下面这个方法在sdk:21以上才有 | |||||
| activity.getWindow() | |||||
| .setNavigationBarColor(activity.getResources().getColor(android.R.color.transparent)); | |||||
| } | |||||
| } | |||||
| public static void setFlag(Activity activity, int flag){ | |||||
| if (Build.VERSION.SDK_INT >= 19){ | |||||
| View decorView = activity.getWindow().getDecorView(); | |||||
| int option = decorView.getSystemUiVisibility() | flag; | |||||
| decorView.setSystemUiVisibility(option); | |||||
| } | |||||
| } | |||||
| //取消flag | |||||
| public static void clearFlag(Activity activity, int flag){ | |||||
| if (Build.VERSION.SDK_INT >= 19){ | |||||
| View decorView = activity.getWindow().getDecorView(); | |||||
| int option = decorView.getSystemUiVisibility() & (~flag); | |||||
| decorView.setSystemUiVisibility(option); | |||||
| } | |||||
| } | |||||
| public static void setToggleFlag(Activity activity, int option){ | |||||
| if (Build.VERSION.SDK_INT >= 19){ | |||||
| if (isFlagUsed(activity,option)){ | |||||
| clearFlag(activity,option); | |||||
| } | |||||
| else { | |||||
| setFlag(activity,option); | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * @param activity | |||||
| * @return flag是否已被使用 | |||||
| */ | |||||
| public static boolean isFlagUsed(Activity activity, int flag) { | |||||
| int currentFlag = activity.getWindow().getDecorView().getSystemUiVisibility(); | |||||
| if((currentFlag & flag) | |||||
| == flag) { | |||||
| return true; | |||||
| }else { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,17 +0,0 @@ | |||||
| package com.yzx.webebook.utils; | |||||
| import android.widget.Toast; | |||||
| import com.yzx.webebook.App; | |||||
| /** | |||||
| * Created by newbiechen on 17-5-11. | |||||
| */ | |||||
| public class ToastUtils { | |||||
| public static void show(String msg){ | |||||
| Toast.makeText(App.Companion.getContext(), msg, Toast.LENGTH_SHORT).show(); | |||||
| } | |||||
| } | |||||
| @@ -1,31 +0,0 @@ | |||||
| package com.yzx.webebook.utils.media; | |||||
| import android.content.Context; | |||||
| import android.os.Bundle; | |||||
| import androidx.loader.content.CursorLoader; | |||||
| /** | |||||
| * Created by newbiechen on 2018/1/14. | |||||
| */ | |||||
| public class LoaderCreator { | |||||
| public static final int ALL_BOOK_FILE = 1; | |||||
| public static CursorLoader create(Context context, int id, Bundle bundle) { | |||||
| LocalFileLoader loader = null; | |||||
| switch (id){ | |||||
| case ALL_BOOK_FILE: | |||||
| loader = new LocalFileLoader(context); | |||||
| break; | |||||
| default: | |||||
| loader = null; | |||||
| break; | |||||
| } | |||||
| if (loader != null) { | |||||
| return loader; | |||||
| } | |||||
| throw new IllegalArgumentException("The id of Loader is invalid!"); | |||||
| } | |||||
| } | |||||
| @@ -1,137 +0,0 @@ | |||||
| package com.yzx.webebook.utils.media; | |||||
| import android.content.Context; | |||||
| import android.database.Cursor; | |||||
| import android.net.Uri; | |||||
| import android.provider.MediaStore; | |||||
| import android.text.TextUtils; | |||||
| import androidx.annotation.NonNull; | |||||
| import androidx.loader.content.CursorLoader; | |||||
| import java.io.File; | |||||
| import java.sql.Blob; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| /** | |||||
| * Created by newbiechen on 2018/1/14. | |||||
| */ | |||||
| public class LocalFileLoader extends CursorLoader { | |||||
| private static final String TAG = "LocalFileLoader"; | |||||
| private static final Uri FILE_URI = Uri.parse("content://media/external/file"); | |||||
| private static final String SELECTION = MediaStore.Files.FileColumns.DATA + " like ?"; | |||||
| private static final String SEARCH_TYPE = "%.txt"; | |||||
| private static final String SORT_ORDER = MediaStore.Files.FileColumns.DISPLAY_NAME + " DESC"; | |||||
| private static final String[] FILE_PROJECTION = { | |||||
| MediaStore.Files.FileColumns.DATA, | |||||
| MediaStore.Files.FileColumns.DISPLAY_NAME | |||||
| }; | |||||
| public LocalFileLoader(Context context) { | |||||
| super(context); | |||||
| initLoader(); | |||||
| } | |||||
| /** | |||||
| * 为 Cursor 设置默认参数 | |||||
| */ | |||||
| private void initLoader() { | |||||
| setUri(FILE_URI); | |||||
| setProjection(FILE_PROJECTION); | |||||
| setSelection(SELECTION); | |||||
| setSelectionArgs(new String[]{SEARCH_TYPE}); | |||||
| setSortOrder(SORT_ORDER); | |||||
| } | |||||
| public void parseData(Cursor cursor, final MediaStoreHelper.MediaResultCallback resultCallback) { | |||||
| List<File> files = new ArrayList<>(); | |||||
| // 判断是否存在数据 | |||||
| if (cursor == null) { | |||||
| // TODO:当媒体库没有数据的时候,需要做相应的处理 | |||||
| // 暂时直接返回空数据 | |||||
| resultCallback.onResultCallback(files); | |||||
| return; | |||||
| } | |||||
| // 重复使用Loader时,需要重置cursor的position; | |||||
| cursor.moveToPosition(-1); | |||||
| while (cursor.moveToNext()) { | |||||
| String path; | |||||
| path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA)); | |||||
| // 路径无效 | |||||
| if (TextUtils.isEmpty(path)) { | |||||
| continue; | |||||
| } else { | |||||
| File file = new File(path); | |||||
| if (file.isDirectory() || !file.exists()){ | |||||
| continue; | |||||
| } | |||||
| else { | |||||
| files.add(file); | |||||
| } | |||||
| } | |||||
| } | |||||
| if (resultCallback != null) { | |||||
| resultCallback.onResultCallback(files); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 从Cursor中读取对应columnName的值 | |||||
| * | |||||
| * @param cursor | |||||
| * @param columnName | |||||
| * @param defaultValue | |||||
| * @return 当columnName无效时返回默认值; | |||||
| */ | |||||
| protected Object getValueFromCursor(@NonNull Cursor cursor, String columnName, Object defaultValue) { | |||||
| try { | |||||
| int index = cursor.getColumnIndexOrThrow(columnName); | |||||
| int type = cursor.getType(index); | |||||
| switch (type) { | |||||
| case Cursor.FIELD_TYPE_STRING: | |||||
| // TO SOLVE:某些手机的数据库将数值类型存为String类型 | |||||
| String value = cursor.getString(index); | |||||
| try { | |||||
| if (defaultValue instanceof String) { | |||||
| return value; | |||||
| } else if (defaultValue instanceof Long) { | |||||
| return Long.valueOf(value); | |||||
| } else if (defaultValue instanceof Integer) { | |||||
| return Integer.valueOf(value); | |||||
| } else if (defaultValue instanceof Double) { | |||||
| return Double.valueOf(value); | |||||
| } else if (defaultValue instanceof Float) { | |||||
| return Float.valueOf(value); | |||||
| } | |||||
| } catch (NumberFormatException e) { | |||||
| return defaultValue; | |||||
| } | |||||
| case Cursor.FIELD_TYPE_INTEGER: | |||||
| if (defaultValue instanceof Long) { | |||||
| return cursor.getLong(index); | |||||
| } else if (defaultValue instanceof Integer) { | |||||
| return cursor.getInt(index); | |||||
| } | |||||
| case Cursor.FIELD_TYPE_FLOAT: | |||||
| if (defaultValue instanceof Float) { | |||||
| return cursor.getFloat(index); | |||||
| } else if (defaultValue instanceof Double) { | |||||
| return cursor.getDouble(index); | |||||
| } | |||||
| case Cursor.FIELD_TYPE_BLOB: | |||||
| if (defaultValue instanceof Blob) { | |||||
| return cursor.getBlob(index); | |||||
| } | |||||
| case Cursor.FIELD_TYPE_NULL: | |||||
| default: | |||||
| return defaultValue; | |||||
| } | |||||
| } catch (IllegalArgumentException e) { | |||||
| return defaultValue; | |||||
| } | |||||
| } | |||||
| } | |||||