├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── ddy │ │ └── richeditorweb │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── editor.html │ │ ├── index.css │ │ ├── reload.png │ │ └── richeditor.js │ ├── java │ │ ├── android │ │ │ └── support │ │ │ │ └── v4 │ │ │ │ └── app │ │ │ │ └── BaseDialogFragment.java │ │ └── cn │ │ │ └── ddy │ │ │ └── richeditorweb │ │ │ ├── base │ │ │ └── depence │ │ │ │ ├── AppManager.java │ │ │ │ ├── basebeans │ │ │ │ ├── HttpResponseBase.java │ │ │ │ └── factories │ │ │ │ │ └── IBeanFactory.java │ │ │ │ ├── fresco │ │ │ │ ├── FrescoCacheParams.java │ │ │ │ └── FrescoImageLoader.java │ │ │ │ ├── mvp │ │ │ │ ├── BasePresenterImpl.java │ │ │ │ ├── Baseinterfaces │ │ │ │ │ ├── BaseModel.java │ │ │ │ │ ├── BaseModelCallBack.java │ │ │ │ │ ├── BasePresenter.java │ │ │ │ │ └── BaseView.java │ │ │ │ ├── LazyFragment.java │ │ │ │ ├── MvpBaseActivity.java │ │ │ │ └── MvpBaseFragment.java │ │ │ │ ├── retrofit │ │ │ │ ├── NetworkNoAvailableException.java │ │ │ │ ├── RetrofitClient.java │ │ │ │ └── uploader │ │ │ │ │ ├── RxUploader.java │ │ │ │ │ ├── UploadSingleTask.java │ │ │ │ │ ├── api │ │ │ │ │ ├── UploadState.java │ │ │ │ │ └── Uploader.java │ │ │ │ │ ├── beans │ │ │ │ │ ├── BaseUploadBean.java │ │ │ │ │ ├── EmptyBean.java │ │ │ │ │ ├── FailedBean.java │ │ │ │ │ ├── RequestBodyWrapper.java │ │ │ │ │ ├── SuccessBean.java │ │ │ │ │ ├── UploadBeanFactory.java │ │ │ │ │ ├── UploadInfoBean.java │ │ │ │ │ └── UploadProgress.java │ │ │ │ │ └── utils │ │ │ │ │ ├── UploadBeanUtil.java │ │ │ │ │ └── UploadHelper.java │ │ │ │ ├── rxjava │ │ │ │ ├── BaseHttpObserver.java │ │ │ │ ├── HttpResBase2Object.java │ │ │ │ ├── Notify.java │ │ │ │ ├── Progrezz.java │ │ │ │ ├── RxBus.java │ │ │ │ └── RxSchedulers.java │ │ │ │ └── tools │ │ │ │ ├── AESOperator.java │ │ │ │ ├── AndroidBug5497Workaround.java │ │ │ │ ├── Constant.java │ │ │ │ ├── SizeUtil.java │ │ │ │ ├── StatusBarUtils.java │ │ │ │ ├── TimeUtils.java │ │ │ │ ├── Utils.java │ │ │ │ └── Validator.java │ │ │ └── richtexteditor │ │ │ ├── MainActivity.java │ │ │ ├── SingleFileLimitInterceptor.java │ │ │ ├── bean │ │ │ └── Response.java │ │ │ └── dialogs │ │ │ ├── LinkDialog.java │ │ │ └── PictureHandleDialog.java │ └── res │ │ ├── drawable │ │ ├── left_arrow_black.png │ │ ├── left_arrow_white.png │ │ └── theme.png │ │ ├── layout │ │ ├── activity_main.xml │ │ └── dialog_fragment_link.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── cn │ └── ddy │ └── richeditorweb │ └── ExampleUnitTest.java ├── build.gradle ├── gif ├── 1513577833212.gif ├── 1513577898325.gif ├── 1513578199588.gif └── 1513578267429.gif ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── javascriptSource ├── index.css ├── index.html ├── package-lock.json ├── package.json ├── reload.png ├── rich_editor.js ├── richeditor-es5.js └── richeditor.js ├── lubottommenu ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lu │ │ └── lubottommenu │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── lu │ │ │ └── lubottommenu │ │ │ ├── AnimatorUtil.java │ │ │ ├── LuBottomMenu.java │ │ │ ├── Utils.java │ │ │ ├── api │ │ │ ├── IBottomMenuItem.java │ │ │ └── ITheme.java │ │ │ ├── logiclist │ │ │ ├── MenuItem.java │ │ │ ├── MenuItemFactory.java │ │ │ └── MenuItemTree.java │ │ │ ├── menuitem │ │ │ ├── AbstractBottomMenuItem.java │ │ │ ├── ImageViewButtonItem.java │ │ │ └── TextViewItem.java │ │ │ └── theme │ │ │ ├── AbstractTheme.java │ │ │ ├── BaseTheme.java │ │ │ ├── DarkTheme.java │ │ │ └── LightTheme.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── lu │ └── lubottommenu │ └── ExampleUnitTest.java ├── richtexteditorlib ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lu │ │ └── richtexteditorlib │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── lu │ │ │ └── richtexteditorlib │ │ │ ├── SimpleRichEditor.java │ │ │ ├── base │ │ │ └── RichEditor.java │ │ │ ├── constant │ │ │ └── ItemIndex.java │ │ │ ├── factories │ │ │ ├── BaseItemFactory.java │ │ │ ├── DefaultItemFactory.java │ │ │ └── IItemFactory.java │ │ │ └── utils │ │ │ ├── SelectController.java │ │ │ └── Utils.java │ └── res │ │ ├── drawable │ │ ├── a.png │ │ ├── blockquote.png │ │ ├── bold.png │ │ ├── h1.png │ │ ├── h2.png │ │ ├── h3.png │ │ ├── h4.png │ │ ├── halving_line.png │ │ ├── insert_image.png │ │ ├── italic.png │ │ ├── link.png │ │ ├── more.png │ │ ├── picture.png │ │ ├── redo.png │ │ ├── strikethrough.png │ │ └── undo.png │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── lu │ └── richtexteditorlib │ └── ExampleUnitTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RichEditorWeb 2 | WebView富文本编辑器,支持图片的插入和删除 3 | # 有趣有真相 4 | ![](https://github.com/dengdaoyus/RichEditorWeb/blob/master/gif/1513577833212.gif?raw=true) 5 | ![](https://github.com/dengdaoyus/RichEditorWeb/blob/master/gif/1513577898325.gif?raw=true) 6 | 7 | ![](https://github.com/dengdaoyus/RichEditorWeb/blob/master/gif/1513578199588.gif?raw=true) 8 | ![](https://github.com/dengdaoyus/RichEditorWeb/blob/master/gif/1513578267429.gif?raw=true) 9 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | // JitPack Maven 3 | apply plugin: 'com.github.dcendents.android-maven' 4 | // Your Group 5 | group='com.github.dengdaoyus' 6 | version = "1.0.0" //需更改,这个是Library的版本后,每次更新的时候,版本需要不一样 7 | android { 8 | compileSdkVersion 25 9 | buildToolsVersion "25.0.3" 10 | defaultConfig { 11 | applicationId "com.lu.richtexteditor" 12 | minSdkVersion 15 13 | targetSdkVersion 25 14 | versionCode 1 15 | versionName "1.0" 16 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 17 | } 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | } 25 | 26 | dependencies { 27 | compile fileTree(include: ['*.jar'], dir: 'libs') 28 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 29 | exclude group: 'com.android.support', module: 'support-annotations' 30 | }) 31 | compile 'com.squareup.retrofit2:converter-gson:2.2.0' 32 | compile 'com.squareup.retrofit2:retrofit:2.2.0' 33 | compile 'com.squareup.okhttp3:okhttp:3.6.0' 34 | compile 'io.reactivex.rxjava2:rxandroid:2.0.1' 35 | compile 'com.jakewharton.rxrelay2:rxrelay:2.0.0' 36 | compile 'com.squareup.okhttp3:logging-interceptor:3.6.0' 37 | compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0' 38 | compile 'com.github.martin90s:ImagePicker:v1.3.2' 39 | compile 'com.facebook.fresco:fresco:1.5.0' 40 | compile 'com.facebook.fresco:imagepipeline-okhttp3:1.5.0' 41 | compile 'com.android.support:recyclerview-v7:25.3.1' 42 | compile 'com.android.support:appcompat-v7:25.3.1' 43 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 44 | testCompile 'junit:junit:4.12' 45 | compile project(':lubottommenu') 46 | compile project(':richtexteditorlib') 47 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\Administrator\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/cn/ddy/richeditorweb/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("cn.ddy.richeditorweb", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/assets/editor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Mobile Rich Editor 8 | 9 | 10 | 11 |
12 |
13 | 14 |
15 |
16 |
17 |
18 |
19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/assets/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | line-height: 2; 4 | } 5 | p { 6 | padding: 0; 7 | margin: 0; 8 | } 9 | .content { 10 | width: auto; 11 | position: relative; 12 | padding-top: 20px; 13 | margin-left: 10px; 14 | margin-right: 10px; 15 | } 16 | .content .title { 17 | width: 100%; 18 | height: 40px; 19 | font-size: 24px; 20 | border: none; 21 | outline: none; 22 | background-color: transparent; 23 | color: inherit; 24 | border-color: inherit; 25 | } 26 | .content .line { 27 | border: 1px dashed #969696; 28 | margin-top: 5px; 29 | } 30 | .content #editor { 31 | margin-top: 20px; 32 | outline: none; 33 | } 34 | .content #editor hr { 35 | font-family: Avenir, sans-serif; 36 | border-right-width: 0px; 37 | border-bottom-width: 0px; 38 | border-left-width: 0px; 39 | border-top-style: solid; 40 | border-color: inherit; 41 | height: 1px; 42 | margin: 1em 0px; 43 | padding: 0px; 44 | color: inherit; 45 | font-size: 17px; 46 | white-space: normal; 47 | display: block; 48 | } 49 | .content #editor .block { 50 | text-align: center; 51 | position: relative; 52 | height: auto; 53 | overflow: hidden; 54 | } 55 | .content #editor .img-block .images { 56 | display: block; 57 | margin: 0 auto 10px; 58 | } 59 | .content #editor .block input { 60 | text-align: center; 61 | width: 10rem; 62 | border: none; 63 | outline: none; 64 | border-bottom: 1px solid; 65 | background-color:transparent; 66 | color: inherit; 67 | border-color: inherit; 68 | } 69 | 70 | .img-block .delete{ 71 | display: none; 72 | text-align: center; 73 | background: #ea6f5a; 74 | color: #fff; 75 | font-size: 0px; 76 | position: absolute; 77 | width: 100%; 78 | height: 100px; 79 | top: 50%; 80 | margin-top: -50px; 81 | padding-top: 10px; 82 | z-index: 3; 83 | } 84 | 85 | .img-block .delete img{ 86 | width: 36px; 87 | height: 36px; 88 | } 89 | 90 | .img-block .delete .tips{ 91 | margin: 5px auto; 92 | font-size: 20px; 93 | } 94 | 95 | #editor .editor-link{ 96 | text-decoration: none; 97 | color: #2AAFF3; 98 | } 99 | 100 | .block{ 101 | font-size: 0; 102 | } 103 | 104 | .process{ 105 | height: 5px; 106 | display: inline-block; 107 | } 108 | 109 | .fill{ 110 | height: 100%; 111 | background: #2AAFF3; 112 | width: 0; 113 | } 114 | 115 | .cover{ 116 | position: absolute; 117 | top: 5px; 118 | left: 50%; 119 | transform: translateX(-50%); 120 | z-index: 2; 121 | background: rgba(255, 255, 255, 0.3); 122 | } 123 | 124 | 125 | #editor:empty:not(:focus)::before { 126 | content: "请输入正文"; 127 | opacity: .5; 128 | } 129 | 130 | blockquote { 131 | background: rgba(90%, 90%, 90%, .3); 132 | border-left: 10px solid; 133 | border-color: rgba(30%, 30%, 30%, .3); 134 | margin: 1.5em 10px; 135 | padding: 0.5em 10px; 136 | quotes: "\201C""\201D"; 137 | } 138 | blockquote:before { 139 | color: inherit; 140 | font-size: 4em; 141 | line-height: 0.1em; 142 | margin-right: 0.25em; 143 | vertical-align: -0.4em; 144 | } 145 | blockquote p { 146 | display: inline; 147 | } -------------------------------------------------------------------------------- /app/src/main/assets/reload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dengdaoyus/RichEditorWeb/551925ad2fc2bc0ddf48dd337ec4b0a74bfd4dfd/app/src/main/assets/reload.png -------------------------------------------------------------------------------- /app/src/main/java/android/support/v4/app/BaseDialogFragment.java: -------------------------------------------------------------------------------- 1 | package android.support.v4.app; 2 | 3 | import android.support.v7.app.AppCompatDialogFragment; 4 | 5 | /** 6 | * 7 | * Created by 陆正威 on 2017/9/17. 8 | */ 9 | 10 | public class BaseDialogFragment extends AppCompatDialogFragment { 11 | @Override 12 | public void show(FragmentManager manager, String tag) { 13 | try { 14 | super.show(manager, tag); 15 | }catch (IllegalStateException e){ 16 | e.printStackTrace(); 17 | } 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/AppManager.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence; 2 | 3 | import android.app.ActivityManager; 4 | import android.app.Application; 5 | 6 | import com.facebook.cache.disk.DiskCacheConfig; 7 | import com.facebook.common.internal.Supplier; 8 | import com.facebook.common.util.ByteConstants; 9 | import com.facebook.drawee.backends.pipeline.Fresco; 10 | import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory; 11 | import com.facebook.imagepipeline.core.ImagePipelineConfig; 12 | import com.imnjh.imagepicker.PickerConfig; 13 | import com.imnjh.imagepicker.SImagePicker; 14 | 15 | 16 | import java.io.File; 17 | 18 | import cn.ddy.richeditorweb.base.depence.fresco.FrescoCacheParams; 19 | import cn.ddy.richeditorweb.base.depence.fresco.FrescoImageLoader; 20 | import cn.ddy.richeditorweb.base.depence.retrofit.RetrofitClient; 21 | import cn.ddy.richeditorweb.base.depence.tools.Constant; 22 | import cn.ddy.richeditorweb.base.depence.tools.Utils; 23 | 24 | 25 | /** 26 | * Created by 陆正威 on 2017/4/6. 27 | */ 28 | 29 | public class AppManager extends Application { 30 | private static AppManager context; 31 | private ActivityManager activityManager; 32 | // private HttpProxyCacheServer proxy; 33 | 34 | 35 | @Override 36 | public void onCreate() { 37 | super.onCreate(); 38 | context = this; 39 | activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); 40 | ScreenParamsInit(); 41 | FrescoInit(); 42 | SImagePicker.init(new PickerConfig.Builder().setAppContext(this) 43 | .setImageLoader(new FrescoImageLoader()) 44 | .build()); 45 | } 46 | 47 | public static AppManager app() { 48 | return context; 49 | } 50 | 51 | private void ScreenParamsInit() { 52 | int a[] = Utils.getScreenSize(); 53 | Constant.screenWithPx = a[0]; 54 | Constant.screenHeightPx = a[1]; 55 | Constant.screenWithDp = Utils.px2dip(Constant.screenWithPx); 56 | Constant.screenHeightDp = Utils.px2dip(Constant.screenHeightPx); 57 | } 58 | 59 | // public static HttpProxyCacheServer getProxy() { 60 | // if(context == null) 61 | // return null; 62 | // return context.proxy == null ? (context.proxy = context.newProxy()) : context.proxy; 63 | // } 64 | // 65 | // private HttpProxyCacheServer newProxy() { 66 | // return new HttpProxyCacheServer(this); 67 | // } 68 | 69 | // private void GreenDaoInit(){ 70 | // DBManager.initialize(this); 71 | // } 72 | 73 | private void FrescoInit() { 74 | DiskCacheConfig diskCacheConfig = DiskCacheConfig.newBuilder(this) 75 | .setMaxCacheSize(40 * ByteConstants.MB) 76 | .setBaseDirectoryPathSupplier(new Supplier() { 77 | @Override 78 | public File get() { 79 | return getCacheDir(); 80 | } 81 | }) 82 | .build(); 83 | 84 | final FrescoCacheParams bitmapCacheParams = new FrescoCacheParams(activityManager); 85 | //Set listeners = new HashSet<>(); 86 | ImagePipelineConfig imagePipelineConfig = OkHttpImagePipelineConfigFactory.newBuilder(this, RetrofitClient.getInstance().getOkHttpClient()) 87 | .setMainDiskCacheConfig(diskCacheConfig) 88 | .setBitmapMemoryCacheParamsSupplier(bitmapCacheParams) 89 | .setDownsampleEnabled(true) 90 | .build(); 91 | Fresco.initialize(this, imagePipelineConfig); 92 | } 93 | 94 | // public static String getBK1() { 95 | // return BuildConfig.localKey1; 96 | // } 97 | // public static String getBK2(){ 98 | // return app().getResources().getString(R.string.local_key2); 99 | // } 100 | // public static String getBK0(){ return getBK1().substring(0,16).replace("q","f").substring(4,8);} 101 | 102 | // public static String getDefaultBK(){ 103 | // return getBK0().concat(getBK1().substring(4).concat(getBK2()).concat("l")); 104 | // } 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/basebeans/HttpResponseBase.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.basebeans; 2 | import com.google.gson.annotations.SerializedName; 3 | 4 | import java.io.Serializable; 5 | 6 | /** 7 | * Created by 陆正威 on 2017/4/5. 8 | */ 9 | 10 | public class HttpResponseBase implements Serializable{ 11 | 12 | @SerializedName("message") 13 | private String message; 14 | @SerializedName("state") 15 | private int state; 16 | @SerializedName("data") 17 | private T data; 18 | 19 | public boolean isSuccessful() 20 | { 21 | return state>=0; 22 | } 23 | 24 | public String getError() 25 | { 26 | return message == null ? "":message; 27 | } 28 | 29 | protected HttpResponseBase(String message, int state, T data) { 30 | this.message = message; 31 | this.state = state; 32 | this.data = data; 33 | } 34 | 35 | public String getMessage() { 36 | return message; 37 | } 38 | 39 | public void setMessage(String message) { 40 | this.message = message; 41 | } 42 | 43 | public int getState() { 44 | return state; 45 | } 46 | 47 | public void setState(int state) { 48 | this.state = state; 49 | } 50 | 51 | public T getData() { 52 | return data; 53 | } 54 | 55 | public void setData(T data) { 56 | this.data = data; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/basebeans/factories/IBeanFactory.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.basebeans.factories; 2 | 3 | 4 | /** 5 | * Created by 陆正威 on 2017/4/4. 6 | */ 7 | 8 | public interface IBeanFactory { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/fresco/FrescoCacheParams.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.fresco; 2 | 3 | import android.app.ActivityManager; 4 | import android.os.Build; 5 | 6 | import com.facebook.common.internal.Supplier; 7 | import com.facebook.common.util.ByteConstants; 8 | import com.facebook.imagepipeline.cache.MemoryCacheParams; 9 | 10 | /** 11 | * Created by 陆正威 on 2017/4/8. 12 | */ 13 | 14 | public class FrescoCacheParams implements Supplier { 15 | private ActivityManager activityManager; 16 | 17 | public FrescoCacheParams(ActivityManager activityManager){ 18 | this.activityManager = activityManager; 19 | } 20 | @Override 21 | public MemoryCacheParams get() { 22 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 23 | return new MemoryCacheParams( 24 | getMaxCacheSize(), 25 | Integer.MAX_VALUE, 26 | getMaxCacheSize(), 27 | Integer.MAX_VALUE, 28 | Integer.MAX_VALUE); 29 | }else { 30 | return new MemoryCacheParams( 31 | getMaxCacheSize(), 32 | Integer.MAX_VALUE, 33 | getMaxCacheSize(), 34 | Integer.MAX_VALUE, 35 | Integer.MAX_VALUE); 36 | } 37 | } 38 | private int getMaxCacheSize(){ 39 | final int maxMemory = Math.min(activityManager.getMemoryClass() * ByteConstants.MB, Integer.MAX_VALUE); 40 | if(maxMemory < 32 *ByteConstants.MB){ 41 | return 4 * ByteConstants.MB; 42 | }else if(maxMemory < 64* ByteConstants.MB){ 43 | return 6 * ByteConstants.MB; 44 | }else { 45 | return maxMemory/4; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/fresco/FrescoImageLoader.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.fresco; 2 | 3 | import android.content.Context; 4 | import android.net.Uri; 5 | import android.widget.ImageView; 6 | 7 | import com.facebook.drawee.backends.pipeline.Fresco; 8 | import com.facebook.drawee.drawable.ScalingUtils; 9 | import com.facebook.drawee.interfaces.DraweeController; 10 | import com.facebook.drawee.view.DraweeView; 11 | import com.facebook.drawee.view.SimpleDraweeView; 12 | import com.facebook.imagepipeline.common.ResizeOptions; 13 | import com.facebook.imagepipeline.request.ImageRequest; 14 | import com.facebook.imagepipeline.request.ImageRequestBuilder; 15 | import com.imnjh.imagepicker.ImageLoader; 16 | 17 | /** 18 | * Created by 陆正威 on 2017/4/15. 19 | */ 20 | 21 | public class FrescoImageLoader implements ImageLoader { 22 | 23 | public FrescoImageLoader() { 24 | } 25 | 26 | @Override 27 | public void bindImage(ImageView photoImageView, Uri uri, int width, int height) { 28 | DraweeView draweeView = (DraweeView) photoImageView; 29 | final ImageRequestBuilder requestBuilder = ImageRequestBuilder.newBuilderWithSource(uri); 30 | if (width > 0 && height > 0) { 31 | requestBuilder.setResizeOptions(new ResizeOptions(width, height)); 32 | } 33 | ImageRequest imageRequest = requestBuilder.build(); 34 | DraweeController controller = Fresco.newDraweeControllerBuilder() 35 | .setOldController(draweeView.getController()) 36 | .setImageRequest(imageRequest).build(); 37 | draweeView.setController(controller); 38 | } 39 | 40 | @Override 41 | public void bindImage(ImageView imageView, Uri uri) { 42 | bindImage(imageView, uri, 0, 0); 43 | } 44 | 45 | @Override 46 | public ImageView createImageView(Context context) { 47 | SimpleDraweeView simpleDraweeView = new SimpleDraweeView(context); 48 | return simpleDraweeView; 49 | } 50 | 51 | @Override 52 | public ImageView createFakeImageView(Context context) { 53 | SimpleDraweeView fakeImage = new SimpleDraweeView(context); 54 | fakeImage.getHierarchy().setActualImageScaleType(ScalingUtils.ScaleType.CENTER_CROP); 55 | return fakeImage; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/mvp/BasePresenterImpl.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.mvp; 2 | 3 | 4 | import android.support.annotation.NonNull; 5 | 6 | 7 | 8 | import java.lang.ref.SoftReference; 9 | 10 | import cn.ddy.richeditorweb.base.depence.mvp.Baseinterfaces.BasePresenter; 11 | import cn.ddy.richeditorweb.base.depence.mvp.Baseinterfaces.BaseView; 12 | import io.reactivex.disposables.CompositeDisposable; 13 | import io.reactivex.disposables.Disposable; 14 | 15 | 16 | /** 17 | * Created by 陆正威 on 2017/3/31. 18 | */ 19 | 20 | /******************************************************************************************** 21 | * 22 | * 解决presenter因为持有View的引用而导致的内存泄露 23 | * 这里持有View的软引用并在下层(Activity层)调用和 24 | * 管理View的生命周期 25 | * 26 | ********************************************************************************************/ 27 | public abstract class BasePresenterImpl implements BasePresenter { 28 | private SoftReference mBaseView; 29 | private CompositeDisposable compositeDisposable; 30 | private boolean hasConnected; 31 | 32 | public BasePresenterImpl() { 33 | hasConnected = false; 34 | compositeDisposable = new CompositeDisposable(); 35 | mBaseView = null; 36 | } 37 | 38 | void attachView(@NonNull T t) { 39 | //Log.e("attach",t.getClass().getSimpleName()); 40 | mBaseView = new SoftReference<>(t); 41 | hasConnected = true; 42 | } 43 | 44 | protected T getView() { 45 | return mBaseView == null ? null:mBaseView.get(); 46 | } 47 | 48 | void detachView() { 49 | removeAllDisposables(); 50 | if (mBaseView != null) { 51 | //Log.e("detachView",""); 52 | mBaseView.clear(); 53 | mBaseView = null; 54 | hasConnected = false; 55 | } 56 | } 57 | 58 | public boolean isHasConnected() { 59 | return hasConnected; 60 | } 61 | 62 | public void addCompositeDisposables(Disposable disposable) { 63 | compositeDisposable.add(disposable); 64 | } 65 | 66 | public void removeCompositeDisposables(Disposable disposable) { 67 | compositeDisposable.remove(disposable); 68 | } 69 | 70 | public void removeAllDisposables() { 71 | compositeDisposable.clear(); 72 | } 73 | 74 | public void start() { 75 | 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/mvp/Baseinterfaces/BaseModel.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.mvp.Baseinterfaces; 2 | 3 | /** 4 | * Created by 陆正威 on 2017/3/31. 5 | */ 6 | 7 | public interface BaseModel { 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/mvp/Baseinterfaces/BaseModelCallBack.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.mvp.Baseinterfaces; 2 | 3 | /** 4 | * Created by 陆正威 on 2017/3/31. 5 | */ 6 | 7 | public interface BaseModelCallBack { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/mvp/Baseinterfaces/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.mvp.Baseinterfaces; 2 | 3 | /** 4 | * Created by 陆正威 on 2017/3/31. 5 | */ 6 | 7 | public interface BasePresenter { 8 | void start(); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/mvp/Baseinterfaces/BaseView.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.mvp.Baseinterfaces; 2 | 3 | /** 4 | * Created by 陆正威 on 2017/3/31. 5 | */ 6 | 7 | public interface BaseView { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/mvp/LazyFragment.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.mvp; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | import android.view.View; 7 | 8 | 9 | /** 10 | * Created by 陆正威 on 2017/4/7. 11 | */ 12 | 13 | public abstract class LazyFragment extends Fragment { 14 | 15 | public interface onFragmentVisibleListener{ 16 | void onVisible(boolean isFirstVisiable); 17 | } 18 | public interface onFragmentInVisibleListener{ 19 | void onInVisible(); 20 | } 21 | 22 | public void setInVisibleListener(onFragmentInVisibleListener inVisibleListener) { 23 | this.inVisibleListener = inVisibleListener; 24 | } 25 | 26 | public void setVisibleListener(onFragmentVisibleListener visibleListener) { 27 | this.visibleListener = visibleListener; 28 | } 29 | 30 | private onFragmentInVisibleListener inVisibleListener; 31 | private onFragmentVisibleListener visibleListener; 32 | /** 33 | * rootView是否初始化标志,防止回调函数在rootView为空的时候触发 34 | */ 35 | private boolean hasCreateView; 36 | private boolean isInViewPager = true; 37 | 38 | /** 39 | * 当前Fragment是否处于可见状态标志,防止因ViewPager的缓存机制而导致回调函数的触发 40 | */ 41 | private boolean isFragmentVisible; 42 | private boolean isFirstVisible; 43 | 44 | /** 45 | * onCreateView()里返回的view,修饰为protected,所以子类继承该类时,在onCreateView里必须对该变量进行初始化 46 | */ 47 | protected View rootView; 48 | 49 | public void setInViewPager(boolean flag){ 50 | isInViewPager = flag; 51 | } 52 | 53 | @Override 54 | public void setUserVisibleHint(boolean isVisibleToUser) { 55 | super.setUserVisibleHint(isVisibleToUser); 56 | //Log.d(getTAG(), "setUserVisibleHint() -> isVisibleToUser: " + isVisibleToUser); 57 | if (rootView == null) { 58 | return; 59 | } 60 | hasCreateView = true; 61 | if (isVisibleToUser) { 62 | if(!isFirstVisible) { 63 | onFragmentVisibleChange(true, true); 64 | isFirstVisible = true; 65 | } 66 | else 67 | onFragmentVisibleChange(true,false); 68 | isFragmentVisible = true; 69 | return; 70 | } 71 | if (isFragmentVisible) { 72 | onFragmentVisibleChange(false,false); 73 | isFragmentVisible = false; 74 | } 75 | 76 | } 77 | 78 | @Override 79 | public void onCreate(@Nullable Bundle savedInstanceState) { 80 | super.onCreate(savedInstanceState); 81 | initVariable(); 82 | } 83 | 84 | @Override 85 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 86 | super.onViewCreated(view,savedInstanceState); 87 | if (!hasCreateView && getUserVisibleHint()) { 88 | if(!isFirstVisible) { 89 | onFragmentVisibleChange(true, true); 90 | isFirstVisible = true; 91 | } 92 | else 93 | onFragmentVisibleChange(true,false); 94 | isFragmentVisible = true; 95 | } 96 | super.onViewCreated(view, savedInstanceState); 97 | } 98 | 99 | protected void initVariable() { 100 | hasCreateView = false; 101 | isFragmentVisible = false; 102 | isFirstVisible = false; 103 | } 104 | 105 | 106 | protected boolean isFragmentVisible(){ 107 | return !isFragmentVisible; 108 | } 109 | /************************************************************** 110 | * 自定义的回调方法,子类可根据需求重写 111 | *************************************************************/ 112 | 113 | /** 114 | * 当前fragment可见状态发生变化时会回调该方法 115 | * 如果当前fragment是第一次加载,等待onCreateView后才会回调该方法,其它情况回调时机跟 {@link #setUserVisibleHint(boolean)}一致 116 | * 在该回调方法中你可以做一些加载数据操作,甚至是控件的操作,因为配合fragment的view复用机制,你不用担心在对控件操作中会报 null 异常 117 | * 118 | * @param isVisible true 不可见 -> 可见 119 | * false 可见 -> 不可见 120 | */ 121 | private void onFragmentVisibleChange(boolean isVisible,boolean isFirstVisible) { 122 | if(isVisible){ 123 | if(visibleListener != null) 124 | visibleListener.onVisible(isFirstVisible); 125 | onFragmentVisible(isFirstVisible); 126 | }else{ 127 | if(inVisibleListener != null) 128 | inVisibleListener.onInVisible(); 129 | onFragmentInVisible(); 130 | } 131 | //Log.e("", "onFragmentVisibleChange -> isVisible: " + isVisible); 132 | } 133 | 134 | protected void onFragmentVisible(boolean isFirstVisible) {} 135 | protected void onFragmentInVisible(){} 136 | 137 | @Override 138 | public void onDetach() { 139 | super.onDetach(); 140 | /*防止ViewPager的直接调用,对于ViewPage在MVP架构时,Presenter会获得View的引用,当View 141 | 被销毁后,该引用会为null.而使用ViewPager管理fragment时,会直接通过fragmentManger间接调用fragment的 142 | onDetach(),onAttach().setUserVisible()函数,当使用EventBus时,传递异步消息到多个View(View中会接收和视图相关的信息)时, 143 | 中间存在延迟,如果快速切换ViewPager,相邻的fragment(他们被预加载过但任然是不可见状态),会直接调用onDetach()函数 144 | 跳过onFragmentInVisible,从而导致EventBus等异步订阅取消失败,异步消息一段延时后传入回调函数, 145 | 但此时View为null,发生错误; 146 | */ 147 | if(isInViewPager) 148 | onFragmentInVisible(); 149 | inVisibleListener = null; 150 | visibleListener = null; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/mvp/MvpBaseActivity.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.mvp; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.SupportActivity; 6 | 7 | import cn.ddy.richeditorweb.base.depence.mvp.Baseinterfaces.BaseView; 8 | import cn.ddy.richeditorweb.base.depence.tools.Utils; 9 | 10 | 11 | /** 12 | * Created by 陆正威 on 2017/3/31. 13 | */ 14 | 15 | /************************************************************************************************************************ 16 | * 17 | * 泛型参数V ,P 分别代表View层和Presenter层,其中Presenter层持有View层的弱引用并已经对其做好管理函数,attach是将View 18 | * 存入Presenter层的函数,detach则反之,在Activity(View)创建时,将本身传入Presenter层,作为软引用,不会影响View的释放 19 | * 在View destroy时解除引用。 20 | * 21 | ***********************************************************************************************************************/ 22 | 23 | 24 | public abstract class MvpBaseActivity extends SupportActivity { 25 | 26 | public final String TAG = "MvpBaseActivity"; 27 | protected P mPresenter; 28 | 29 | @Override 30 | protected void onCreate(@Nullable Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | if (isTransparent()) 33 | Utils.TRANSPARENT(getWindow()); 34 | mPresenter = createPresent(); 35 | mPresenter.attachView((V) this); 36 | } 37 | 38 | @Override 39 | protected void onDestroy() { 40 | super.onDestroy(); 41 | mPresenter.detachView(); 42 | } 43 | 44 | protected abstract P createPresent(); 45 | 46 | protected abstract boolean isTransparent(); 47 | 48 | public String getTAG() { 49 | return TAG; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/mvp/MvpBaseFragment.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.mvp; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | 7 | import cn.ddy.richeditorweb.base.depence.mvp.Baseinterfaces.BaseView; 8 | 9 | 10 | /** 11 | * Created by 陆正威 on 2017/4/3. 12 | */ 13 | 14 | public abstract class MvpBaseFragment extends LazyFragment{ 15 | protected P mPresenter; 16 | public final String TAG = "MVPBASE"; 17 | 18 | public String getTAG(){ 19 | return TAG; 20 | } 21 | 22 | @Override 23 | public void onCreate(@Nullable Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | } 26 | 27 | 28 | @Override 29 | public void onAttach(Context context) { 30 | super.onAttach(context); 31 | mPresenter = createPresent(); 32 | mPresenter.attachView((V)this); 33 | } 34 | 35 | 36 | @Override 37 | public void onDetach() { 38 | super.onDetach(); 39 | mPresenter.detachView(); 40 | } 41 | 42 | protected abstract P createPresent(); 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/NetworkNoAvailableException.java: -------------------------------------------------------------------------------- 1 | package com.lu.base.depence.retrofit; 2 | 3 | /** 4 | * Created by 陆正威 on 2017/8/1. 5 | */ 6 | 7 | public class NetworkNoAvailableException extends Exception { 8 | public NetworkNoAvailableException(String message) { 9 | super(message); 10 | } 11 | 12 | @Override 13 | public String getMessage() { 14 | return super.getMessage(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/RetrofitClient.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.retrofit; 2 | 3 | import android.util.Log; 4 | 5 | import com.google.gson.FieldNamingPolicy; 6 | import com.google.gson.Gson; 7 | import com.google.gson.GsonBuilder; 8 | 9 | import java.security.SecureRandom; 10 | import java.security.cert.CertificateException; 11 | import java.security.cert.X509Certificate; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | import javax.net.ssl.HostnameVerifier; 15 | import javax.net.ssl.SSLContext; 16 | import javax.net.ssl.SSLSession; 17 | import javax.net.ssl.SSLSocketFactory; 18 | import javax.net.ssl.TrustManager; 19 | import javax.net.ssl.X509TrustManager; 20 | 21 | import okhttp3.OkHttpClient; 22 | import okhttp3.logging.HttpLoggingInterceptor; 23 | import retrofit2.Retrofit; 24 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; 25 | import retrofit2.converter.gson.GsonConverterFactory; 26 | 27 | /** 28 | * 29 | * Created by 陆正威 on 2017/4/5. 30 | */ 31 | @SuppressWarnings({"unused"}) 32 | public class RetrofitClient { 33 | 34 | @SuppressWarnings("WeakerAccess") 35 | public static long DEFAULT_TIMEOUT = 10; 36 | 37 | public static String BASE_URL = "http://www.lhbzimo.cn/"; 38 | private Retrofit mRetrofit; 39 | private OkHttpClient mOkHttpClient; 40 | private static volatile RetrofitClient mInstance; 41 | 42 | private RetrofitClient(){ 43 | OkHttpClient.Builder builder = new OkHttpClient.Builder(); 44 | builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) 45 | .sslSocketFactory(createSSLSocketFactory(),new TrustAllManager())//信任所有 46 | .addInterceptor(new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { 47 | @Override 48 | public void log(String message) { 49 | Log.i("okhttp32",message); 50 | } 51 | }).setLevel(HttpLoggingInterceptor.Level.BODY)) 52 | ; 53 | 54 | mOkHttpClient = builder.build(); 55 | mRetrofit = new Retrofit.Builder() 56 | .client(mOkHttpClient) 57 | .baseUrl(BASE_URL) 58 | .addConverterFactory(GsonConverterFactory.create(buildGson())) 59 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 60 | .build(); 61 | } 62 | 63 | public static RetrofitClient getInstance() 64 | { 65 | if(mInstance == null) 66 | { 67 | synchronized (RetrofitClient.class) { 68 | mInstance = new RetrofitClient(); 69 | } 70 | } 71 | return mInstance; 72 | } 73 | private static Gson buildGson() { 74 | return new GsonBuilder() 75 | .serializeNulls() 76 | .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY) 77 | // 此处可以添加Gson 自定义TypeAdapter 78 | .create(); 79 | } 80 | 81 | private static SSLSocketFactory createSSLSocketFactory() { 82 | 83 | SSLSocketFactory sSLSocketFactory = null; 84 | 85 | try { 86 | SSLContext sc = SSLContext.getInstance("TLS"); 87 | sc.init(null, new TrustManager[]{new TrustAllManager()}, 88 | new SecureRandom()); 89 | sSLSocketFactory = sc.getSocketFactory(); 90 | } catch (Exception ignored) { 91 | } 92 | 93 | return sSLSocketFactory; 94 | } 95 | 96 | private static class TrustAllManager implements X509TrustManager { 97 | @Override 98 | public void checkClientTrusted(X509Certificate[] chain, String authType) 99 | throws CertificateException { 100 | //do nothing trust all clients 101 | } 102 | 103 | @Override 104 | public void checkServerTrusted(X509Certificate[] chain, String authType) 105 | throws CertificateException { 106 | //do nothing trust all servers 107 | } 108 | 109 | @Override 110 | public X509Certificate[] getAcceptedIssuers() { 111 | return new X509Certificate[0]; 112 | } 113 | } 114 | 115 | private static class TrustAllHostnameVerifier implements HostnameVerifier { 116 | @Override 117 | public boolean verify(String hostname, SSLSession session) { 118 | return true; 119 | } 120 | } 121 | 122 | public static String appendBaseUrl(String url){ 123 | url = RetrofitClient.BASE_URL.concat(url.substring(1)); 124 | return url; 125 | } 126 | 127 | @SuppressWarnings({"WeakerAccess"}) 128 | public Retrofit getRetrofit() 129 | { 130 | return mRetrofit; 131 | } 132 | 133 | @SuppressWarnings({"WeakerAccess"}) 134 | public OkHttpClient getOkHttpClient(){return mOkHttpClient;} 135 | } 136 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/uploader/api/UploadState.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.retrofit.uploader.api; 2 | 3 | 4 | /** 5 | * Created by 陆正威 on 2017/7/31. 6 | */ 7 | @SuppressWarnings("unused") 8 | public class UploadState { 9 | public static int start = 0x000; 10 | public static int failed = 0x001; 11 | public static int completed = 0x002; 12 | //public static int pause = 0x004; 13 | public static int stop = 0x008; 14 | public static int uploading = 0x010; 15 | public static int finish = 0x020; 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/uploader/api/Uploader.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.retrofit.uploader.api; 2 | 3 | 4 | import cn.ddy.richeditorweb.base.depence.retrofit.uploader.RxUploader; 5 | import cn.ddy.richeditorweb.base.depence.retrofit.uploader.beans.UploadProgress; 6 | import okhttp3.ResponseBody; 7 | 8 | /** 9 | * Created by 陆正威 on 2017/8/1. 10 | */ 11 | public interface Uploader{ 12 | interface UploadTaskInfo { 13 | String getUUID(); 14 | } 15 | 16 | interface OnTaskAutoFinishedListener { 17 | void onTaskAutoFinished(RxUploader.TaskController taskController); 18 | } 19 | 20 | interface OnUploadListener{ 21 | void onStart(); 22 | void onUploading(String filePath, UploadProgress progress); 23 | void onCompleted(String filePath, ResponseBody responseBody); 24 | void onFailed(String filePath, Throwable throwable); 25 | } 26 | 27 | interface AfterOperationTaskHandler extends TaskHandler{ 28 | void preHandleSuccess(Long fromTaskId, RxUploader.TaskController taskController); 29 | } 30 | 31 | interface TaskHandler{ 32 | void handle(Long fromTaskId, RxUploader.TaskController taskController); 33 | void touchTaskFailed(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/uploader/beans/BaseUploadBean.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.retrofit.uploader.beans; 2 | 3 | 4 | /** 5 | * Created by 陆正威 on 2017/7/31. 6 | */ 7 | @SuppressWarnings("unused") 8 | public abstract class BaseUploadBean { 9 | private String filePath; 10 | private int state; 11 | T data; 12 | 13 | BaseUploadBean(){ 14 | } 15 | 16 | BaseUploadBean(int state){ 17 | this(state,null); 18 | } 19 | 20 | BaseUploadBean(int state, String filePath){ 21 | this(state,filePath,null); 22 | } 23 | 24 | BaseUploadBean(int state, String filePath, T data){ 25 | this.state = state; 26 | this.filePath = filePath; 27 | this.data = data; 28 | } 29 | 30 | public int getState() { 31 | return state; 32 | } 33 | 34 | public String getFilePath() { 35 | return filePath; 36 | } 37 | 38 | public T getData(){ 39 | return data; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/uploader/beans/EmptyBean.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.retrofit.uploader.beans; 2 | 3 | /** 4 | * Created by 陆正威 on 2017/8/2. 5 | */ 6 | 7 | public class EmptyBean extends BaseUploadBean { 8 | EmptyBean(int state){ 9 | super(state); 10 | } 11 | 12 | public EmptyBean(int state, String filePath) { 13 | super(state, filePath); 14 | } 15 | 16 | public EmptyBean(int state, String filePath, Object data) { 17 | super(state, filePath, data); 18 | } 19 | 20 | public EmptyBean() { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/uploader/beans/FailedBean.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.retrofit.uploader.beans; 2 | 3 | 4 | import cn.ddy.richeditorweb.base.depence.retrofit.uploader.api.UploadState; 5 | 6 | /** 7 | * Created by 陆正威 on 2017/8/2. 8 | */ 9 | 10 | public class FailedBean extends BaseUploadBean { 11 | FailedBean(String filePath,Throwable data){ 12 | super(UploadState.failed,filePath,data); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/uploader/beans/RequestBodyWrapper.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.retrofit.uploader.beans; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | 6 | import java.io.IOException; 7 | 8 | import cn.ddy.richeditorweb.base.depence.retrofit.uploader.api.UploadState; 9 | import io.reactivex.Emitter; 10 | import io.reactivex.processors.BehaviorProcessor; 11 | import io.reactivex.processors.FlowableProcessor; 12 | import okhttp3.MediaType; 13 | import okhttp3.RequestBody; 14 | import okio.BufferedSink; 15 | import okio.ForwardingSink; 16 | import okio.Okio; 17 | import okio.Sink; 18 | 19 | /** 20 | * RequestBody的包装类,增加对其写入的监听,近似的监听上传速度 21 | * Emitter的包装类。 22 | * Created by 陆正威 on 2017/7/30. 23 | */ 24 | @SuppressWarnings({"WeakerAccess"}) 25 | public class RequestBodyWrapper extends RequestBody implements Emitter { 26 | 27 | private RequestBody mRequestBody; 28 | private String mFilePath; 29 | private FlowableProcessor mUploadProcessor; 30 | 31 | public RequestBodyWrapper(@NonNull RequestBody requestBody, String filePath) { 32 | this.mRequestBody = requestBody; 33 | this.mFilePath = filePath; 34 | this.mUploadProcessor = BehaviorProcessor.create(); 35 | } 36 | 37 | public FlowableProcessor getUploadProcessor() { 38 | return mUploadProcessor; 39 | } 40 | 41 | @Override 42 | public void onNext(BaseUploadBean baseUploadBean){ 43 | if(mUploadProcessor!=null) { 44 | mUploadProcessor.onNext(baseUploadBean); 45 | } 46 | } 47 | 48 | @Override 49 | public void onError(Throwable throwable){ 50 | if(mUploadProcessor != null && throwable != null) { 51 | mUploadProcessor.onNext(UploadBeanFactory.failed(mFilePath,throwable)); 52 | } 53 | } 54 | 55 | @Override 56 | public void onComplete() { 57 | if(mUploadProcessor != null ) { 58 | mUploadProcessor.onComplete(); 59 | } 60 | } 61 | 62 | @Override 63 | public MediaType contentType() { 64 | return mRequestBody.contentType(); 65 | } 66 | 67 | @Override 68 | public long contentLength() throws IOException { 69 | return mRequestBody.contentLength(); 70 | } 71 | 72 | @Override 73 | public void writeTo(BufferedSink sink)throws IOException{ 74 | CountingSink countingSink = new CountingSink(sink); 75 | BufferedSink bufferedSink = Okio.buffer(countingSink); 76 | mRequestBody.writeTo(bufferedSink); 77 | //必须调用flush,否则最后一部分数据可能不会被写入 78 | bufferedSink.flush(); 79 | onNext(UploadBeanFactory.empty(UploadState.finish)); 80 | } 81 | 82 | private class CountingSink extends ForwardingSink { 83 | private long bytesWritten = 0; 84 | CountingSink(Sink delegate) { 85 | super(delegate); 86 | } 87 | 88 | @Override 89 | public void close() throws IOException { 90 | super.close(); 91 | } 92 | 93 | @Override 94 | public void write(okio.Buffer source, long byteCount) throws IOException { 95 | super.write(source, byteCount); 96 | bytesWritten += byteCount; 97 | if(bytesWritten < contentLength()) 98 | onNext(UploadBeanFactory.uploading(mFilePath, bytesWritten,contentLength())); 99 | } 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/uploader/beans/SuccessBean.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.retrofit.uploader.beans; 2 | 3 | 4 | 5 | import cn.ddy.richeditorweb.base.depence.retrofit.uploader.api.UploadState; 6 | import okhttp3.ResponseBody; 7 | 8 | /** 9 | * Created by 陆正威 on 2017/8/2. 10 | */ 11 | 12 | public class SuccessBean extends BaseUploadBean { 13 | SuccessBean(String filePath,ResponseBody responseBody){ 14 | super(UploadState.completed,filePath,responseBody); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/uploader/beans/UploadBeanFactory.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.retrofit.uploader.beans; 2 | 3 | import okhttp3.ResponseBody; 4 | 5 | /** 6 | * Created by 陆正威 on 2017/8/2. 7 | */ 8 | @SuppressWarnings("unused") 9 | public class UploadBeanFactory { 10 | public static BaseUploadBean failed(String filePath, Throwable throwable){ 11 | return new FailedBean(filePath,throwable); 12 | } 13 | public static BaseUploadBean uploading(String filePath, UploadProgress progress){ 14 | return new UploadInfoBean(filePath,progress); 15 | } 16 | public static BaseUploadBean uploading(String filePath, long progress1, long progress2){ 17 | return new UploadInfoBean(filePath,new UploadProgress(progress1,progress2)); 18 | } 19 | public static BaseUploadBean completed(String filePath, ResponseBody responseBody){ 20 | return new SuccessBean(filePath,responseBody); 21 | } 22 | public static BaseUploadBean empty(){ 23 | return new EmptyBean(); 24 | } 25 | 26 | public static BaseUploadBean empty(int state){ 27 | return new EmptyBean(state); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/uploader/beans/UploadInfoBean.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.retrofit.uploader.beans; 2 | 3 | 4 | import cn.ddy.richeditorweb.base.depence.retrofit.uploader.api.UploadState; 5 | 6 | /** 7 | * 8 | * Created by 陆正威 on 2017/8/2. 9 | */ 10 | 11 | public class UploadInfoBean extends BaseUploadBean { 12 | public UploadInfoBean(String filePath, UploadProgress data) { 13 | super(UploadState.uploading, filePath, data); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/uploader/beans/UploadProgress.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.retrofit.uploader.beans; 2 | 3 | /** 4 | * 5 | * Created by 陆正威 on 2017/8/2. 6 | */ 7 | @SuppressWarnings("unused") 8 | public class UploadProgress { 9 | private long writtenBytes; 10 | private long totalBytes; 11 | 12 | UploadProgress(long writtenBytes,long totalBytes){ 13 | this.totalBytes = totalBytes; 14 | this.writtenBytes = writtenBytes; 15 | } 16 | 17 | public long getTotalBytes() { 18 | return totalBytes; 19 | } 20 | 21 | public long getWrittenBytes() { 22 | return writtenBytes; 23 | } 24 | 25 | public float getProgress(){ 26 | if(totalBytes > 0){ 27 | return (float) ((double)writtenBytes / (double)totalBytes)*100; 28 | } 29 | return 0f; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/uploader/utils/UploadBeanUtil.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.retrofit.uploader.utils; 2 | 3 | 4 | import cn.ddy.richeditorweb.base.depence.retrofit.uploader.api.UploadState; 5 | import cn.ddy.richeditorweb.base.depence.retrofit.uploader.beans.BaseUploadBean; 6 | 7 | /** 8 | * Created by 陆正威 on 2017/8/2. 9 | */ 10 | 11 | public class UploadBeanUtil { 12 | public static boolean isFailed(BaseUploadBean bean){ 13 | return bean.getState() == UploadState.failed; 14 | } 15 | 16 | public static boolean isCompleted(BaseUploadBean bean){ 17 | return bean.getState() == UploadState.completed; 18 | } 19 | 20 | public static boolean isUploading(BaseUploadBean bean){ 21 | return bean.getState() == UploadState.uploading; 22 | } 23 | 24 | public static boolean isFinished(BaseUploadBean bean){ 25 | return bean.getState() == UploadState.finish; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/retrofit/uploader/utils/UploadHelper.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.retrofit.uploader.utils; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import java.io.File; 6 | import java.util.HashSet; 7 | 8 | 9 | import cn.ddy.richeditorweb.base.depence.retrofit.RetrofitClient; 10 | import cn.ddy.richeditorweb.base.depence.retrofit.uploader.beans.BaseUploadBean; 11 | import cn.ddy.richeditorweb.base.depence.retrofit.uploader.beans.RequestBodyWrapper; 12 | import cn.ddy.richeditorweb.base.depence.retrofit.uploader.beans.UploadInfoBean; 13 | import io.reactivex.Flowable; 14 | import io.reactivex.Observable; 15 | import io.reactivex.android.schedulers.AndroidSchedulers; 16 | import io.reactivex.functions.Predicate; 17 | import io.reactivex.schedulers.Schedulers; 18 | import okhttp3.Interceptor; 19 | import okhttp3.MultipartBody; 20 | import okhttp3.OkHttpClient; 21 | import okhttp3.ResponseBody; 22 | import retrofit2.http.Multipart; 23 | import retrofit2.http.POST; 24 | import retrofit2.http.Part; 25 | import retrofit2.http.Url; 26 | 27 | import static com.facebook.common.util.ByteConstants.KB; 28 | 29 | /** 30 | * 上传单个文件 31 | * Created by 陆正威 on 2017/7/30. 32 | */ 33 | @SuppressWarnings({"unused","WeakerAccess"}) 34 | public class UploadHelper { 35 | public final static String DEFAULT_MEDIA_TYPE = "application/octet-stream"; 36 | public final static String DEFAULT_FILE_KEY = "file"; 37 | public static long MIN_GRAD = 128 * KB; 38 | 39 | public interface Api{ 40 | @Multipart 41 | @POST 42 | Observable uploadFile(@Url String url, @Part MultipartBody.Part file); 43 | } 44 | 45 | public static HashSet getAllInterceptorClasses(OkHttpClient client){ 46 | final int interceptorNum = client.interceptors().size(); 47 | final HashSet interceptorClasses = new HashSet<>(); 48 | if(interceptorNum>0){ 49 | for(Interceptor interceptor: RetrofitClient.getInstance().getOkHttpClient().interceptors()){ 50 | interceptorClasses.add(interceptor.getClass()); 51 | } 52 | } 53 | return interceptorClasses; 54 | } 55 | 56 | public static Flowable generateFlowable(@NonNull RequestBodyWrapper uploadBeanEmitter, final String filePath){ 57 | Flowable flowable = uploadBeanEmitter.getUploadProcessor() 58 | .publish() 59 | .autoConnect(); 60 | 61 | return flowable 62 | .filter(new Predicate() { 63 | long oldProgress = 0; 64 | @Override 65 | public boolean test(BaseUploadBean baseUploadBean) throws Exception { 66 | if(baseUploadBean instanceof UploadInfoBean){ 67 | long progress = ((UploadInfoBean) baseUploadBean).getData().getWrittenBytes(); 68 | if(progress - oldProgress > MIN_GRAD) { 69 | oldProgress = progress; 70 | return true; 71 | } 72 | return false; 73 | } 74 | oldProgress = 0; 75 | return true; 76 | } 77 | }) 78 | //.throttleLast(100, TimeUnit.MILLISECONDS).mergeWith(flowable.takeLast(1)) 79 | .subscribeOn(Schedulers.io()) 80 | .observeOn(AndroidSchedulers.mainThread()); 81 | } 82 | 83 | public static MultipartBody.Part generateMultiPart(String parName,String filePath,RequestBodyWrapper uploadFileRequestBody){ 84 | File file = new File(filePath); 85 | return MultipartBody.Part.createFormData(parName, file.getName(),uploadFileRequestBody); 86 | } 87 | 88 | public static MultipartBody.Part generateMultiPart(String parName,File file,RequestBodyWrapper uploadFileRequestBody){ 89 | return MultipartBody.Part.createFormData(parName, file.getName(),uploadFileRequestBody); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/rxjava/BaseHttpObserver.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.rxjava; 2 | 3 | import android.util.Log; 4 | 5 | import cn.ddy.richeditorweb.base.depence.basebeans.HttpResponseBase; 6 | import io.reactivex.Observer; 7 | 8 | 9 | /** 10 | * Created by 陆正威 on 2017/4/6. 11 | */ 12 | @SuppressWarnings({"unused"}) 13 | public abstract class BaseHttpObserver implements Observer> { 14 | private static final String TAG = "BaseHttpObserver"; 15 | 16 | @Override 17 | public void onNext(HttpResponseBase value) { 18 | if (value.isSuccessful()) { 19 | T t = value.getData(); 20 | onHandleSuccess(t); 21 | } else { 22 | onHandleError(value.getMessage()); 23 | } 24 | } 25 | 26 | @Override 27 | public void onError(Throwable e) { 28 | Log.e(TAG, "error:" + e.toString()); 29 | } 30 | 31 | @Override 32 | public void onComplete() { 33 | Log.d(TAG, "onComplete"); 34 | } 35 | 36 | @SuppressWarnings({"WeakerAccess"}) 37 | protected abstract void onHandleSuccess(T t); 38 | 39 | @SuppressWarnings({"WeakerAccess"}) 40 | protected void onHandleError(String msg) { 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/rxjava/HttpResBase2Object.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.rxjava; 2 | 3 | 4 | import cn.ddy.richeditorweb.base.depence.basebeans.HttpResponseBase; 5 | import io.reactivex.functions.Function; 6 | 7 | /** 8 | * Created by 陆正威 on 2017/4/6. 9 | */ 10 | @SuppressWarnings({"unused"}) 11 | public class HttpResBase2Object implements Function,T> { 12 | 13 | @Override 14 | public T apply(HttpResponseBase tHttpResponseBase) throws Exception { 15 | if(tHttpResponseBase.isSuccessful() && tHttpResponseBase.getData() != null) { 16 | return tHttpResponseBase.getData(); 17 | }else{ 18 | throw new Exception(tHttpResponseBase.getError()); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/rxjava/Notify.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.rxjava; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * Created by 陆正威 on 2017/4/7. 9 | */ 10 | 11 | public abstract class Notify implements Serializable { 12 | private final static Long TAG = 20170407L; 13 | 14 | private final int id; 15 | public final static int NORMAL = 0; 16 | public final static int CRITICAL = 1; 17 | public final static int FAKE = 3; 18 | private String title = ""; 19 | private String content = ""; 20 | private int State = NORMAL; 21 | 22 | public Notify(){ 23 | id = 0; 24 | } 25 | public Notify(int id) { 26 | this.id = id; 27 | } 28 | 29 | public Notify(int id,String title,String content){ 30 | this.id = id; 31 | this.title = title; 32 | this.content = content; 33 | } 34 | 35 | public Notify(String title){ 36 | this.id = 1; 37 | this.title = title; 38 | } 39 | 40 | public Notify(String title,int state){ 41 | this.id = 1; 42 | this.title = title; 43 | this.State = (Math.abs(state) > 3 ? 0 : Math.abs(state)); 44 | } 45 | 46 | public int getState() { 47 | return State; 48 | } 49 | 50 | public void setState(int state) { 51 | State = state; 52 | } 53 | 54 | public void setContent(@NonNull String content) { 55 | this.content = content; 56 | } 57 | 58 | public void setTitle(@NonNull String title) { 59 | this.title = title; 60 | } 61 | 62 | public String getTitle() { 63 | return title; 64 | } 65 | 66 | public String getContent() { 67 | return content; 68 | } 69 | 70 | public int getId() { 71 | return id; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/rxjava/Progrezz.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.rxjava; 2 | 3 | /** 4 | * Created by 陆正威 on 2017/4/7. 5 | */ 6 | 7 | //this is a clazz that can count the completeabe of one thing, if reach the end_var it well notify any one who has observed it; 8 | 9 | @SuppressWarnings({"unused"}) 10 | public class Progrezz { 11 | private String TAG; 12 | private int begin; 13 | private int end; 14 | private volatile int here; 15 | private final boolean autoreset; 16 | private OnProgrezzListener onProgrezzListener; 17 | private OnProgrezzEndListener onProgrezzEndListener; 18 | 19 | @SuppressWarnings({"WeakerAccess"}) 20 | public interface OnProgrezzListener { 21 | void onStart(); 22 | 23 | void onEnd(); 24 | 25 | void onWhere(int here); 26 | } 27 | 28 | @SuppressWarnings({"WeakerAccess"}) 29 | public interface OnProgrezzEndListener { 30 | void onEnd(); 31 | } 32 | 33 | public void setOnProgrezzEndListener(OnProgrezzEndListener onProgrezzEndListener){ 34 | this.onProgrezzEndListener = onProgrezzEndListener; 35 | } 36 | 37 | public void setOnProgrezzListener(OnProgrezzListener onProgrezzListener) { 38 | this.onProgrezzListener = onProgrezzListener; 39 | } 40 | 41 | public static Progrezz create(String tag , int end){ 42 | return (new Progrezz(end)).setTAG(tag); 43 | } 44 | 45 | public static Progrezz create(String tag ,int begin,int end){ 46 | return (new Progrezz(begin,end)).setTAG(tag); 47 | } 48 | 49 | public static Progrezz create(String tag ,int begin,int end,boolean g){ 50 | return (new Progrezz(begin,end,g)).setTAG(tag); 51 | } 52 | 53 | public static Progrezz create(String tag,int end,boolean g){ 54 | return (new Progrezz(end,g)).setTAG(tag); 55 | } 56 | 57 | private Progrezz(int begin, int end) { 58 | if (begin > end) { 59 | int temp = begin; 60 | begin = end; 61 | end = temp; 62 | } 63 | this.begin = begin; 64 | this.end = end; 65 | autoreset = true; 66 | TAG = "NOMAL_TAG"; 67 | here = begin; 68 | } 69 | 70 | @SuppressWarnings({"WeakerAccess"}) 71 | public Progrezz(int begin, int end, boolean isAutoreset) { 72 | if (begin > end) { 73 | int temp = begin; 74 | begin = end; 75 | end = temp; 76 | } 77 | this.begin = begin; 78 | this.end = end; 79 | autoreset = isAutoreset; 80 | TAG = "NOMAL_TAG"; 81 | here = begin; 82 | } 83 | 84 | private Progrezz(int end) { 85 | if (end < 0) { 86 | end = -end; 87 | } 88 | this.begin = 0; 89 | this.end = end; 90 | autoreset = true; 91 | TAG = "NOMAL_TAG"; 92 | here = begin; 93 | } 94 | 95 | private Progrezz(int end, boolean isautoreset) { 96 | if (end < 0) { 97 | end = -end; 98 | } 99 | this.begin = 0; 100 | this.end = end; 101 | autoreset = isautoreset; 102 | TAG = "NOMAL_TAG"; 103 | here = begin; 104 | } 105 | 106 | private Progrezz setTAG(String TAG) { 107 | this.TAG = TAG; 108 | return this; 109 | } 110 | 111 | public void go(int step) { 112 | if (step <= 0) { 113 | step = -step; 114 | } 115 | synchronized (this) { 116 | here += step; 117 | if(here >= end){ 118 | if(onProgrezzListener != null) 119 | onProgrezzListener.onEnd(); 120 | if(onProgrezzEndListener != null) 121 | onProgrezzEndListener.onEnd(); 122 | if(autoreset){ 123 | here = begin; 124 | if (onProgrezzListener != null) { 125 | onProgrezzListener.onWhere(here); 126 | onProgrezzListener.onStart(); 127 | } 128 | }else{ 129 | here = end; 130 | if (onProgrezzListener != null) { 131 | onProgrezzListener.onWhere(here); 132 | } 133 | } 134 | }else{ 135 | if (onProgrezzListener != null) 136 | onProgrezzListener.onWhere(here); 137 | } 138 | } 139 | } 140 | 141 | public void go(){ 142 | here++; 143 | if(here >= end){ 144 | if(onProgrezzListener != null) 145 | onProgrezzListener.onEnd(); 146 | if(onProgrezzEndListener != null) 147 | onProgrezzEndListener.onEnd(); 148 | 149 | if(autoreset){ 150 | here = begin; 151 | if(onProgrezzListener != null) { 152 | onProgrezzListener.onWhere(here); 153 | onProgrezzListener.onStart(); 154 | } 155 | }else{ 156 | here = end; 157 | if (onProgrezzListener != null) 158 | onProgrezzListener.onWhere(here); 159 | } 160 | }else{ 161 | if (onProgrezzListener != null) 162 | onProgrezzListener.onWhere(here); 163 | } 164 | } 165 | 166 | public String getTAG() { 167 | return TAG; 168 | } 169 | 170 | public synchronized void reset(){ 171 | here = begin; 172 | if (onProgrezzListener != null) { 173 | onProgrezzListener.onStart(); 174 | onProgrezzListener.onWhere(here); 175 | } 176 | } 177 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/rxjava/RxBus.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.rxjava; 2 | 3 | import com.jakewharton.rxrelay2.PublishRelay; 4 | import com.jakewharton.rxrelay2.Relay; 5 | 6 | import io.reactivex.Observable; 7 | import io.reactivex.Scheduler; 8 | import io.reactivex.android.schedulers.AndroidSchedulers; 9 | import io.reactivex.disposables.Disposable; 10 | import io.reactivex.functions.Action; 11 | import io.reactivex.functions.Consumer; 12 | 13 | /** 14 | * Created by 陆正威 on 2017/4/7. 15 | */ 16 | 17 | @SuppressWarnings({"unused"}) 18 | public final class RxBus { 19 | private Relay bus = null; 20 | private static RxBus instance; 21 | 22 | //禁用构造方法 23 | private RxBus() { 24 | bus = PublishRelay.create().toSerialized(); 25 | } 26 | 27 | public static RxBus getInstance() { 28 | if (instance == null) { 29 | synchronized (RxBus.class) { 30 | if (instance == null) { 31 | instance = new RxBus(); 32 | } 33 | } 34 | } 35 | return instance; 36 | } 37 | 38 | public void send(Object event) { 39 | bus.accept(event); 40 | } 41 | 42 | private Observable toObservable(Class eventType) { 43 | return bus.ofType(eventType); 44 | } 45 | 46 | public boolean hasObservers() { 47 | return bus.hasObservers(); 48 | } 49 | 50 | public Disposable register(Class eventType, Scheduler scheduler, Consumer onNext) { 51 | return toObservable(eventType).observeOn(scheduler).subscribe(onNext); 52 | } 53 | 54 | public Disposable register(Class eventType, Scheduler scheduler, Consumer onNext, Consumer onError, 55 | Action onComplete, Consumer onSubscribe) { 56 | return toObservable(eventType).observeOn(scheduler).subscribe(onNext, onError, onComplete, onSubscribe); 57 | } 58 | 59 | public Disposable register(Class eventType, Scheduler scheduler, Consumer onNext, Consumer onError, 60 | Action onComplete) { 61 | return toObservable(eventType).observeOn(scheduler).subscribe(onNext, onError, onComplete); 62 | } 63 | 64 | public Disposable register(Class eventType, Scheduler scheduler, Consumer onNext, Consumer onError) { 65 | return toObservable(eventType).observeOn(scheduler).subscribe(onNext, onError); 66 | } 67 | 68 | public Disposable register(Class eventType, Consumer onNext) { 69 | return toObservable(eventType).observeOn(AndroidSchedulers.mainThread()).subscribe(onNext); 70 | } 71 | 72 | public Disposable register(Class eventType, Consumer onNext, Consumer onError, 73 | Action onComplete, Consumer onSubscribe) { 74 | return toObservable(eventType).observeOn(AndroidSchedulers.mainThread()).subscribe(onNext, onError, onComplete, onSubscribe); 75 | } 76 | 77 | public Disposable register(Class eventType, Consumer onNext, Consumer onError, 78 | Action onComplete) { 79 | return toObservable(eventType).observeOn(AndroidSchedulers.mainThread()).subscribe(onNext, onError, onComplete); 80 | } 81 | 82 | public Disposable register(Class eventType, Consumer onNext, Consumer onError) { 83 | return toObservable(eventType).observeOn(AndroidSchedulers.mainThread()).subscribe(onNext, onError); 84 | } 85 | 86 | public void unregister(Disposable disposable) { 87 | if (disposable != null && !disposable.isDisposed()) { 88 | disposable.dispose(); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/rxjava/RxSchedulers.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.rxjava; 2 | 3 | import cn.ddy.richeditorweb.base.depence.tools.Utils; 4 | import io.reactivex.Observable; 5 | import io.reactivex.ObservableSource; 6 | import io.reactivex.ObservableTransformer; 7 | import io.reactivex.android.schedulers.AndroidSchedulers; 8 | import io.reactivex.disposables.Disposable; 9 | import io.reactivex.functions.Consumer; 10 | import io.reactivex.schedulers.Schedulers; 11 | 12 | 13 | 14 | /** 15 | * Created by 陆正威 on 2017/4/5. 16 | */ 17 | 18 | public class RxSchedulers { 19 | public static ObservableTransformer compose() { 20 | return new ObservableTransformer() { 21 | @Override 22 | public ObservableSource apply(Observable observable) { 23 | return observable 24 | .subscribeOn(Schedulers.io()) 25 | .doOnSubscribe(new Consumer() { 26 | @Override 27 | public void accept(Disposable disposable) throws Exception { 28 | if (!Utils.isNetworkAvailable()) { 29 | //disposable.dispose(); 30 | //throw new NetworkNoAvailableException("no network,please check and retry"); 31 | //Utils.MakeShortToast("no network,please check and retry"); 32 | //throw new Exception(); 33 | } 34 | } 35 | }) 36 | .observeOn(AndroidSchedulers.mainThread()); 37 | } 38 | }; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/tools/AESOperator.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.tools; 2 | 3 | /** 4 | * Created by 陆正威 on 2017/4/30. 5 | */ 6 | import android.util.Base64; 7 | 8 | import javax.crypto.Cipher; 9 | import javax.crypto.spec.IvParameterSpec; 10 | import javax.crypto.spec.SecretKeySpec; 11 | 12 | /** 13 | * AES 是一种可逆加密算法,对用户的敏感信息加密处理 对原始数据进行AES加密后,在进行Base64编码转化; 14 | */ 15 | public class AESOperator { 16 | 17 | /* 18 | * 加密用的Key 可以用26个字母和数字组成 此处使用AES-128-CBC加密模式,key需要为16位。 19 | */ 20 | private String sKey = "1234567812345678"; 21 | private String ivParameter = sKey; 22 | 23 | private static AESOperator instance = null; 24 | 25 | private AESOperator() { 26 | 27 | } 28 | 29 | public static AESOperator getInstance() { 30 | if (instance == null) 31 | instance = new AESOperator(); 32 | return instance; 33 | } 34 | 35 | public static String Encrypt(String encData , String secretKey, String vector) throws Exception { 36 | 37 | if(secretKey == null) { 38 | return null; 39 | } 40 | if(secretKey.length() != 16) { 41 | return null; 42 | } 43 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 44 | byte[] raw = secretKey.getBytes(); 45 | SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 46 | IvParameterSpec iv = new IvParameterSpec(vector.getBytes());// 使用CBC模式,需要一个向量iv,可增加加密算法的强度 47 | cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); 48 | byte[] encrypted = cipher.doFinal(encData.getBytes("utf-8")); 49 | return Base64.encodeToString(encrypted,Base64.DEFAULT);// 此处使用BASE64做转码。 50 | } 51 | 52 | 53 | // 加密 54 | public String encrypt(String sSrc) throws Exception { 55 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 56 | byte[] raw = sKey.getBytes(); 57 | SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 58 | IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());// 使用CBC模式,需要一个向量iv,可增加加密算法的强度 59 | cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); 60 | byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8")); 61 | return Base64.encodeToString(encrypted,Base64.DEFAULT);// 此处使用BASE64做转码。 62 | } 63 | 64 | // 解密 65 | public String decrypt(String sSrc) throws Exception { 66 | try { 67 | byte[] raw = sKey.getBytes("ASCII"); 68 | SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 69 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 70 | IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes()); 71 | cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); 72 | byte[] encrypted1 = Base64.decode(sSrc,Base64.DEFAULT);// 先用base64解密 73 | byte[] original = cipher.doFinal(encrypted1); 74 | return new String(original, "utf-8"); 75 | } catch (Exception ex) { 76 | return null; 77 | } 78 | } 79 | 80 | public String decrypt(String sSrc,String key,String ivs) throws Exception { 81 | try { 82 | byte[] raw = key.getBytes("ASCII"); 83 | SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 84 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 85 | IvParameterSpec iv = new IvParameterSpec(ivs.getBytes()); 86 | cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); 87 | byte[] encrypted1 = Base64.decode(sSrc,Base64.DEFAULT);// 先用base64解密 88 | byte[] original = cipher.doFinal(encrypted1); 89 | return new String(original, "utf-8"); 90 | } catch (Exception ex) { 91 | return null; 92 | } 93 | } 94 | 95 | public static String encodeBytes(byte[] bytes) { 96 | StringBuilder strBuf = new StringBuilder(); 97 | 98 | for (byte aByte : bytes) { 99 | strBuf.append((char) (((aByte >> 4) & 0xF) + ((int) 'a'))); 100 | strBuf.append((char) (((aByte) & 0xF) + ((int) 'a'))); 101 | } 102 | 103 | return strBuf.toString(); 104 | } 105 | 106 | // public static void test() { 107 | // try { 108 | // 109 | // // 需要加密的字串 110 | // String cSrc = "你好我是傻逼"; 111 | // 112 | // // 加密 113 | // long lStart = System.currentTimeMillis(); 114 | // String enString = AESOperator.getInstance().encrypt(cSrc); 115 | // System.out.println("1:" + enString); 116 | // 117 | // long lUseTime = System.currentTimeMillis() - lStart; 118 | // System.out.println("2:" + lUseTime + "ms"); 119 | // // 解密 120 | // lStart = System.currentTimeMillis(); 121 | // String DeString = AESOperator.getInstance().decrypt(enString); 122 | // System.out.println("3:" + DeString); 123 | // lUseTime = System.currentTimeMillis() - lStart; 124 | // System.out.println("4:" + lUseTime + "ms"); 125 | // } catch (Exception e) { 126 | // e.getMessage(); 127 | // } 128 | // } 129 | 130 | 131 | } 132 | 133 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/tools/AndroidBug5497Workaround.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.tools; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Rect; 5 | import android.view.View; 6 | import android.view.ViewTreeObserver; 7 | import android.widget.FrameLayout; 8 | 9 | /** 10 | * Created by 陆正威 on 2017/4/25. 11 | */ 12 | 13 | public class AndroidBug5497Workaround { 14 | 15 | // For more information, see https://code.google.com/p/android/issues/detail?id=5497 16 | // To use this class, simply invoke assistActivity() on an Activity that already has its content view set. 17 | 18 | public static void assistActivity (Activity activity,boolean isFullScreen) { 19 | new AndroidBug5497Workaround(activity,isFullScreen); 20 | } 21 | 22 | private View mChildOfContent; 23 | private int usableHeightPrevious; 24 | private FrameLayout.LayoutParams frameLayoutParams; 25 | 26 | private AndroidBug5497Workaround(Activity activity, final boolean isFullScreen) { 27 | FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); 28 | mChildOfContent = content.getChildAt(0); 29 | mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 30 | public void onGlobalLayout() { 31 | possiblyResizeChildOfContent(isFullScreen); 32 | } 33 | }); 34 | frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); 35 | } 36 | 37 | private void possiblyResizeChildOfContent(boolean isFullScreen) { 38 | int usableHeightNow = computeUsableHeight(isFullScreen); 39 | if (usableHeightNow != usableHeightPrevious) { 40 | int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); 41 | int heightDifference = usableHeightSansKeyboard - usableHeightNow; 42 | if (heightDifference > (usableHeightSansKeyboard/4)) { 43 | // keyboard probably just became visible 44 | frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; 45 | } else { 46 | // keyboard probably just became hidden 47 | frameLayoutParams.height = usableHeightSansKeyboard; 48 | } 49 | mChildOfContent.requestLayout(); 50 | usableHeightPrevious = usableHeightNow; 51 | } 52 | } 53 | 54 | private int computeUsableHeight(boolean isFullScreen) { 55 | Rect r = new Rect(); 56 | mChildOfContent.getWindowVisibleDisplayFrame(r); 57 | if(!isFullScreen) 58 | return (r.bottom - r.top);// 全屏模式下: return r.bottom 59 | else 60 | return (r.bottom ); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/tools/Constant.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.tools; 2 | 3 | /** 4 | * Created by 陆正威 on 2017/4/16. 5 | */ 6 | 7 | public class Constant { 8 | public static int screenWithPx; 9 | public static int screenHeightPx; 10 | public static int screenWithDp; 11 | public static int screenHeightDp; 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/tools/SizeUtil.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.tools; 2 | 3 | import android.graphics.BitmapFactory; 4 | 5 | /** 6 | * Created by 陆正威 on 2017/7/1. 7 | */ 8 | 9 | public class SizeUtil { 10 | public static final double ERROR_CONVER = -1d; 11 | 12 | public static final int KB = 0x001; 13 | public static final int MB = 0x002; 14 | public static final int GB =0x003; 15 | public static final int TB = 0x004; 16 | 17 | double conver(long byteSize,int flag){ 18 | if(flag <= TB && flag >= KB) 19 | return byteSize >> (flag * 10); 20 | else 21 | return ERROR_CONVER; 22 | } 23 | 24 | public static long[] getBitmapSize(String url){ 25 | BitmapFactory.Options op=new BitmapFactory.Options(); 26 | op.inJustDecodeBounds = true; 27 | BitmapFactory.decodeFile(url, op); 28 | return new long[]{op.outWidth,op.outHeight}; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/tools/StatusBarUtils.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.tools; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | 6 | /** 7 | * Created by 陆正威 on 2017/4/17. 8 | */ 9 | 10 | public class StatusBarUtils { 11 | public static int getHeight(Context context) { 12 | int statusBarHeight = 0; 13 | int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); 14 | if (resourceId > 0) { 15 | statusBarHeight = context.getResources().getDimensionPixelSize(resourceId); 16 | } 17 | if (isFlymeOs4x()) { 18 | return 2 * statusBarHeight; 19 | } 20 | 21 | return statusBarHeight; 22 | } 23 | 24 | public static boolean isFlymeOs4x() { 25 | String sysVersion = android.os.Build.VERSION.RELEASE; 26 | if ("4.4.4".equals(sysVersion)) { 27 | String sysIncrement = android.os.Build.VERSION.INCREMENTAL; 28 | String displayId = android.os.Build.DISPLAY; 29 | if (!TextUtils.isEmpty(sysIncrement)) { 30 | return sysIncrement.contains("Flyme_OS_4"); 31 | } else { 32 | return displayId.contains("Flyme OS 4"); 33 | } 34 | } 35 | return false; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/tools/TimeUtils.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.tools; 2 | 3 | import java.util.Calendar; 4 | import java.util.TimeZone; 5 | 6 | /** 7 | * Created by 陆正威 on 2017/4/20. 8 | */ 9 | 10 | public class TimeUtils { 11 | private final static Calendar calendar = Calendar.getInstance(TimeZone.getDefault()); 12 | 13 | public static long getCurTime() { 14 | return calendar.getTimeInMillis(); 15 | } 16 | 17 | public static String getCurStringTime() { 18 | return calendar.getTime().toString(); 19 | } 20 | 21 | public static String getCurTimeYMD() { 22 | return calendar.get(Calendar.YEAR) + "年 " 23 | + calendar.get(Calendar.MONTH) + "月 " 24 | + calendar.get(Calendar.DAY_OF_MONTH) + "日 " 25 | //+ calendar.get(Calendar.HOUR_OF_DAY) + "时 " 26 | //+ calendar.get(Calendar.MINUTE) + "分 " 27 | //+ calendar.get(Calendar.SECOND) + "秒" 28 | ; 29 | } 30 | 31 | public static String getCurTimeHMS() { 32 | return //calendar.get(Calendar.YEAR) + "年 " 33 | //+ calendar.get(Calendar.MONTH) + "月 " 34 | //+ calendar.get(Calendar.DAY_OF_MONTH) + "日 " 35 | +calendar.get(Calendar.HOUR_OF_DAY) + "时 " 36 | + calendar.get(Calendar.MINUTE) + "分 " 37 | + calendar.get(Calendar.SECOND) + "秒" 38 | ; 39 | } 40 | 41 | public static String getCurTimeMDHM() { 42 | return //calendar.get(Calendar.YEAR) + "年 " 43 | +calendar.get(Calendar.MONTH) + "月 " 44 | + calendar.get(Calendar.DAY_OF_MONTH) + "日 " 45 | + calendar.get(Calendar.HOUR_OF_DAY) + "时 " 46 | + calendar.get(Calendar.MINUTE) + "分 " 47 | //+ calendar.get(Calendar.SECOND) + "秒" 48 | ; 49 | } 50 | 51 | public static String getCurTimeMDH() { 52 | return //calendar.get(Calendar.YEAR) + "年 " 53 | +calendar.get(Calendar.MONTH) + "月 " 54 | + calendar.get(Calendar.DAY_OF_MONTH) + "日 " 55 | + calendar.get(Calendar.HOUR_OF_DAY) + "时 " 56 | //+ calendar.get(Calendar.MINUTE) + "分 " 57 | //+ calendar.get(Calendar.SECOND) + "秒" 58 | ; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/tools/Utils.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.tools; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.net.ConnectivityManager; 6 | import android.net.NetworkInfo; 7 | import android.os.Build; 8 | import android.util.DisplayMetrics; 9 | import android.view.View; 10 | import android.view.Window; 11 | import android.view.WindowManager; 12 | import android.widget.Toast; 13 | 14 | import cn.ddy.richeditorweb.base.depence.AppManager; 15 | 16 | 17 | import static android.os.Build.VERSION.SDK_INT; 18 | 19 | 20 | /** 21 | * Created by 陆正威 on 2017/4/6. 22 | */ 23 | 24 | public class Utils { 25 | 26 | public static void TRANSPARENT(Window window){ 27 | 28 | if(SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 29 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 30 | window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 31 | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); 32 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 33 | window.setStatusBarColor(Color.TRANSPARENT); 34 | }else { 35 | if (SDK_INT >= Build.VERSION_CODES.KITKAT) { 36 | WindowManager.LayoutParams localLayoutParams = window.getAttributes(); 37 | localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags); 38 | } 39 | } 40 | } 41 | 42 | public static boolean isNetworkAvailable() { 43 | try { 44 | ConnectivityManager connectivity = (ConnectivityManager) AppManager.app().getSystemService(Context.CONNECTIVITY_SERVICE); 45 | if (connectivity != null) { 46 | NetworkInfo info = connectivity.getActiveNetworkInfo(); 47 | if (info != null && info.isConnected()) { 48 | if (info.getState() == NetworkInfo.State.CONNECTED) { 49 | return true; 50 | } 51 | } 52 | } 53 | } catch (Exception e) { 54 | e.printStackTrace(); 55 | return false; 56 | } 57 | return false; 58 | } 59 | 60 | public static void MakeToast(boolean isLong, String text){ 61 | Toast.makeText(AppManager.app(),text,isLong ? Toast.LENGTH_LONG:Toast.LENGTH_SHORT).show(); 62 | } 63 | 64 | public static void MakeShortToast(String text){ 65 | Toast.makeText(AppManager.app(),text,Toast.LENGTH_SHORT).show(); 66 | } 67 | 68 | public static void MakeLongToast(String text){ 69 | Toast.makeText(AppManager.app(),text,Toast.LENGTH_LONG).show(); 70 | } 71 | 72 | public static int[] getScreenSize() { 73 | WindowManager wm = (WindowManager) AppManager.app().getSystemService(Context.WINDOW_SERVICE); 74 | DisplayMetrics outMetrics = new DisplayMetrics(); 75 | wm.getDefaultDisplay().getMetrics(outMetrics); 76 | return new int[]{outMetrics.widthPixels, outMetrics.heightPixels}; 77 | } 78 | 79 | public static int dip2px(float dpValue) { 80 | final float scale = AppManager.app().getResources().getDisplayMetrics().density; 81 | return (int) (dpValue * scale + 0.5f); 82 | } 83 | 84 | public static int px2dip(float pxValue) { 85 | final float scale = AppManager.app().getResources().getDisplayMetrics().density; 86 | return (int) (pxValue / scale + 0.5f); 87 | } 88 | 89 | 90 | 91 | 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/base/depence/tools/Validator.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.base.depence.tools; 2 | 3 | /** 4 | * Created by 陆正威 on 2017/4/29. 5 | */ 6 | 7 | import android.text.InputFilter; 8 | import android.text.Spanned; 9 | 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | /** 14 | * 校验器:利用正则表达式校验邮箱、手机号等 15 | * 16 | * @author 17 | * 18 | */ 19 | public class Validator { 20 | /** 21 | * 正则表达式:验证用户名 22 | */ 23 | public static final String REGEX_USERNAME = "^[a-zA-Z0-9\u4E00-\u9FA5]+$"; 24 | 25 | /** 26 | * 正则表达式:验证密码 27 | */ 28 | public static final String REGEX_PASSWORD = "^[a-zA-Z0-9]{6,16}$"; 29 | 30 | /** 31 | * 移动手机号码的正则表达式。 32 | */ 33 | private static final String REGEX_CHINA_MOBILE ="1(3[4-9]|4[7]|5[012789]|8[278])\\d{8}"; 34 | 35 | /** 36 | * 联通手机号码的正则表达式。 37 | */ 38 | private static final String REGEX_CHINA_UNICOM = "1(3[0-2]|5[56]|8[56])\\d{8}"; 39 | 40 | /** 41 | * 电信手机号码的正则表达式。 42 | */ 43 | private static final String REGEX_CHINA_TELECOM = "(?!00|015|013)(0\\d{9,11})|(1(33|53|80|89)\\d{8})"; 44 | 45 | /** 46 | * 正则表达式:验证手机号 47 | */ 48 | private static final String REGEX_PHONE_NUMBER = "^(0(10|2\\d|[3-9]\\d\\d)[- ]{0,3}\\d{7,8}|0?1[3584]\\d{9})$"; 49 | 50 | /** 51 | * 正则表达式:验证邮箱 52 | */ 53 | public static final String REGEX_EMAIL = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"; 54 | 55 | /** 56 | * 正则表达式:验证汉字 57 | */ 58 | public static final String REGEX_CHINESE = "^[\u4e00-\u9fa5],*$"; 59 | 60 | /** 61 | * 正则表达式:验证身份证 62 | */ 63 | public static final String REGEX_ID_CARD = "(^\\d{18}$)|(^\\d{15}$)"; 64 | 65 | /** 66 | * 正则表达式:验证URL 67 | */ 68 | public static final String REGEX_URL = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?"; 69 | 70 | /** 71 | * 正则表达式:验证IP地址 72 | */ 73 | public static final String REGEX_IP_ADDR = "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)"; 74 | 75 | /** 76 | * 校验用户名 77 | * 78 | * @param username 79 | * @return 校验通过返回true,否则返回false 80 | */ 81 | public static boolean isUsername(String username) { 82 | return Pattern.matches(REGEX_USERNAME, username); 83 | } 84 | 85 | /** 86 | * 校验密码 87 | * 88 | * @param password 89 | * @return 校验通过返回true,否则返回false 90 | */ 91 | public static boolean isPassword(String password) { 92 | return Pattern.matches(REGEX_PASSWORD, password); 93 | } 94 | 95 | /** 96 | * 校验手机号 97 | * 98 | * @param mobile 99 | * @return 校验通过返回true,否则返回false 100 | */ 101 | public static boolean isMobile(String mobile) { 102 | return Pattern.matches(REGEX_PHONE_NUMBER, mobile); 103 | } 104 | 105 | /** 106 | * 校验邮箱 107 | * 108 | * @param email 109 | * @return 校验通过返回true,否则返回false 110 | */ 111 | public static boolean isEmail(String email) { 112 | return Pattern.matches(REGEX_EMAIL, email); 113 | } 114 | 115 | /** 116 | * 校验汉字 117 | * 118 | * @param chinese 119 | * @return 校验通过返回true,否则返回false 120 | */ 121 | public static boolean isChinese(String chinese) { 122 | return Pattern.matches(REGEX_CHINESE, chinese); 123 | } 124 | 125 | /** 126 | * 校验身份证 127 | * 128 | * @param idCard 129 | * @return 校验通过返回true,否则返回false 130 | */ 131 | public static boolean isIDCard(String idCard) { 132 | return Pattern.matches(REGEX_ID_CARD, idCard); 133 | } 134 | 135 | /** 136 | * 校验URL 137 | * 138 | * @param url 139 | * @return 校验通过返回true,否则返回false 140 | */ 141 | public static boolean isUrl(String url) { 142 | return Pattern.matches(REGEX_URL, url); 143 | } 144 | 145 | /** 146 | * 校验IP地址 147 | * 148 | * @param ipAddr 149 | * @return 150 | */ 151 | public static boolean isIPAddr(String ipAddr) { 152 | return Pattern.matches(REGEX_IP_ADDR, ipAddr); 153 | } 154 | 155 | public static class NameLengthFilter implements InputFilter{ 156 | 157 | private int mMax = 16; 158 | 159 | public NameLengthFilter(int mMax) { 160 | mMax = mMax; 161 | } 162 | 163 | public void setMax(int mMax) { 164 | mMax = mMax; 165 | } 166 | 167 | public int getMax() { 168 | return mMax; 169 | } 170 | 171 | @Override 172 | public CharSequence filter(CharSequence source, int start, int end, 173 | Spanned dest, int dstart, int dend) { 174 | int destCount = dest.toString().length() 175 | + getChineseCount(dest.toString()); 176 | int sourceCount = source.toString().length() 177 | + getChineseCount(source.toString()); 178 | if (destCount + sourceCount > mMax) { 179 | return ""; 180 | 181 | } else { 182 | return source; 183 | } 184 | } 185 | 186 | private int getChineseCount(String str) { 187 | int count = 0; 188 | Pattern p = Pattern.compile("[\u4e00-\u9fa5]"); 189 | Matcher m = p.matcher(str); 190 | while (m.find()) { 191 | for (int i = 0; i <= m.groupCount(); i++) { 192 | count = count + 1; 193 | } 194 | } 195 | return count; 196 | } 197 | } 198 | 199 | public static boolean isTooShort(String s,int length){ 200 | return length > getLength(s); 201 | } 202 | 203 | private static int getLength(String s){ 204 | int length = 0; 205 | for(char c : s.toCharArray()){ 206 | if(c>128){ 207 | length+=2; 208 | }else { 209 | length++; 210 | } 211 | } 212 | return length; 213 | } 214 | 215 | } 216 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/richtexteditor/SingleFileLimitInterceptor.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.richtexteditor; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | import android.os.Parcel; 7 | import android.support.v7.app.AlertDialog; 8 | 9 | import com.imnjh.imagepicker.FileChooseInterceptor; 10 | import com.imnjh.imagepicker.PickerAction; 11 | 12 | import java.io.File; 13 | import java.util.ArrayList; 14 | 15 | import cn.ddy.richeditorweb.R; 16 | 17 | import static com.facebook.common.util.ByteConstants.MB; 18 | 19 | /** 20 | * SImagePicker 单文件大小限制拦截器 21 | * Created by 陆正威 on 2017/9/12. 22 | */ 23 | @SuppressWarnings("WeakerAccess") 24 | public class SingleFileLimitInterceptor implements FileChooseInterceptor { 25 | 26 | private static final long MAX_FILE_SIZE_ORIGINAL = 2 * MB; // 2MB 27 | 28 | public SingleFileLimitInterceptor() {} 29 | 30 | @Override 31 | public boolean onFileChosen(Context context, ArrayList selectedPic, 32 | boolean original, 33 | int resultCode, PickerAction action) { 34 | if (resultCode != Activity.RESULT_OK) { 35 | return true; 36 | } 37 | if (original) { 38 | ArrayList confirmedFiles = new ArrayList<>(); 39 | for (String filePath : selectedPic) { 40 | File file = new File(filePath); 41 | if (file.exists()) { 42 | if (file.length() <= MAX_FILE_SIZE_ORIGINAL) { 43 | confirmedFiles.add(filePath); 44 | } 45 | } 46 | } 47 | if (confirmedFiles.size() < selectedPic.size()) { 48 | showSingleFileLimitDialog(context, true, resultCode, action, confirmedFiles); 49 | return false; 50 | } 51 | } 52 | return true; 53 | } 54 | 55 | private void showSingleFileLimitDialog(Context context, final boolean original, 56 | final int resultCode, 57 | final PickerAction action, final ArrayList confirmedFiles) { 58 | new AlertDialog.Builder(context) 59 | .setMessage(R.string.pic_out_of_size) 60 | .setPositiveButton( 61 | R.string.general_ok, new DialogInterface.OnClickListener() { 62 | @Override 63 | public void onClick(DialogInterface dialog, int which) { 64 | action.proceedResultAndFinish(confirmedFiles, original, resultCode); 65 | } 66 | }) 67 | .setNegativeButton(R.string.general_cancel, new DialogInterface.OnClickListener() { 68 | @Override 69 | public void onClick(DialogInterface dialog, int which) {} 70 | }) 71 | .show(); 72 | } 73 | 74 | @Override 75 | public int describeContents() { 76 | return 0; 77 | } 78 | 79 | @Override 80 | public void writeToParcel(Parcel dest, int flags) { 81 | 82 | } 83 | 84 | protected SingleFileLimitInterceptor(Parcel in) {} 85 | 86 | public static final Creator CREATOR = 87 | new Creator() { 88 | @Override 89 | public SingleFileLimitInterceptor createFromParcel(Parcel source) { 90 | return new SingleFileLimitInterceptor(source); 91 | } 92 | 93 | @Override 94 | public SingleFileLimitInterceptor[] newArray(int size) { 95 | return new SingleFileLimitInterceptor[size]; 96 | } 97 | }; 98 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/richtexteditor/bean/Response.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.richtexteditor.bean; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 图片上传的Response 7 | * Response Body Gson 映射类 8 | * Created by 陆正威 on 2017/9/15. 9 | */ 10 | 11 | public class Response { 12 | 13 | /** 14 | * res_code : 0 15 | * data : ["uploads/529137ac-0856-42a6-9d54-694cbc15b29d.octet-stream"] 16 | */ 17 | 18 | private int res_code; 19 | private List data; 20 | 21 | public int getRes_code() { 22 | return res_code; 23 | } 24 | 25 | public void setRes_code(int res_code) { 26 | this.res_code = res_code; 27 | } 28 | 29 | public List getData() { 30 | return data; 31 | } 32 | 33 | public void setData(List data) { 34 | this.data = data; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/richtexteditor/dialogs/LinkDialog.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.richtexteditor.dialogs; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.BaseDialogFragment; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.view.Window; 10 | import android.widget.Button; 11 | import android.widget.EditText; 12 | 13 | import cn.ddy.richeditorweb.R; 14 | 15 | 16 | /** 17 | * 链接创建对话框 18 | * Created by 陆正威 on 2017/9/11. 19 | */ 20 | 21 | public class LinkDialog extends BaseDialogFragment { 22 | public static final String Tag = "link_dialog_fragment"; 23 | 24 | private OnDialogClickListener listener; 25 | private String name; 26 | private String url; 27 | 28 | public static LinkDialog createLinkDialog(String name,String url){ 29 | LinkDialog dialog = createLinkDialog(); 30 | dialog.setUrl(url); 31 | dialog.setName(name); 32 | return dialog; 33 | } 34 | 35 | public static LinkDialog createLinkDialog(){ 36 | 37 | return new LinkDialog(); 38 | } 39 | 40 | public LinkDialog(){ 41 | 42 | } 43 | 44 | @Override 45 | public void onCreate(@Nullable Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | setCancelable(true); 48 | } 49 | 50 | @Nullable 51 | @Override 52 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 53 | View dialog = inflater.inflate(R.layout.dialog_fragment_link, container, false); 54 | Button comb = (Button) dialog.findViewById(R.id.confirm_btn); 55 | Button canb = (Button) dialog.findViewById(R.id.cancel_btn); 56 | final EditText urledt = (EditText) dialog.findViewById(R.id.url_edt); 57 | final EditText nameedt = (EditText) dialog.findViewById(R.id.name_edt); 58 | 59 | if(name != null){ 60 | nameedt.setText(name); 61 | } 62 | if(url != null){ 63 | urledt.setText(url); 64 | } 65 | 66 | comb.setOnClickListener(new View.OnClickListener() { 67 | @Override 68 | public void onClick(View v) { 69 | if(listener!=null) 70 | listener.onConfirmButtonClick(nameedt.getText().toString(),urledt.getText().toString()); 71 | } 72 | }); 73 | 74 | canb.setOnClickListener(new View.OnClickListener() { 75 | @Override 76 | public void onClick(View v) { 77 | if(listener!=null) 78 | listener.onCancelButtonClick(); 79 | } 80 | }); 81 | 82 | getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);//remove title 83 | return dialog; 84 | } 85 | 86 | public void setListener(OnDialogClickListener listener) { 87 | this.listener = listener; 88 | } 89 | 90 | public String getName() { 91 | return name; 92 | } 93 | 94 | public void setName(String name) { 95 | this.name = name; 96 | } 97 | 98 | @SuppressWarnings("unused") 99 | public String getUrl() { 100 | return url; 101 | } 102 | 103 | public void setUrl(String url) { 104 | this.url = url; 105 | } 106 | 107 | public interface OnDialogClickListener { 108 | void onConfirmButtonClick(String name,String url); 109 | void onCancelButtonClick(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ddy/richeditorweb/richtexteditor/dialogs/PictureHandleDialog.java: -------------------------------------------------------------------------------- 1 | package cn.ddy.richeditorweb.richtexteditor.dialogs; 2 | 3 | import android.app.Dialog; 4 | import android.content.DialogInterface; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.support.v4.app.BaseDialogFragment; 8 | import android.support.v7.app.AlertDialog; 9 | 10 | import cn.ddy.richeditorweb.R; 11 | 12 | /** 13 | * 图片处理对话框 14 | * Created by 陆正威 on 2017/9/12. 15 | */ 16 | 17 | public class PictureHandleDialog extends BaseDialogFragment { 18 | public static final String Tag = "delete_dialog_fragment"; 19 | private Long imageId; 20 | private CharSequence[] items; 21 | private OnDialogClickListener listener; 22 | 23 | public static PictureHandleDialog createDeleteDialog(Long imageId){ 24 | final PictureHandleDialog newDialog = new PictureHandleDialog(); 25 | newDialog.setImageId(imageId); 26 | return newDialog; 27 | } 28 | 29 | public PictureHandleDialog(){ 30 | } 31 | 32 | @NonNull 33 | @Override 34 | public Dialog onCreateDialog(Bundle savedInstanceState) { 35 | return new AlertDialog.Builder(getActivity()) 36 | .setItems(items, new DialogInterface.OnClickListener() { 37 | @Override 38 | public void onClick(DialogInterface dialog, int which) { 39 | if(listener != null) 40 | switch (which){ 41 | case 0: 42 | listener.onDeleteButtonClick(imageId); 43 | break; 44 | case 1: 45 | listener.onReloadButtonClick(imageId); 46 | break; 47 | } 48 | 49 | } 50 | }) 51 | .setTitle(R.string.handles).create(); 52 | } 53 | 54 | @SuppressWarnings("unused") 55 | public Long getImageId() { 56 | return imageId; 57 | } 58 | 59 | public void setImageId(Long imageId) { 60 | this.imageId = imageId; 61 | } 62 | 63 | public void setListener(OnDialogClickListener listener) { 64 | this.listener = listener; 65 | } 66 | 67 | public void setItems(CharSequence[] items) { 68 | this.items = items; 69 | } 70 | 71 | public interface OnDialogClickListener { 72 | void onDeleteButtonClick(Long id); 73 | void onReloadButtonClick(Long id); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/left_arrow_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dengdaoyus/RichEditorWeb/551925ad2fc2bc0ddf48dd337ec4b0a74bfd4dfd/app/src/main/res/drawable/left_arrow_black.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/left_arrow_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dengdaoyus/RichEditorWeb/551925ad2fc2bc0ddf48dd337ec4b0a74bfd4dfd/app/src/main/res/drawable/left_arrow_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dengdaoyus/RichEditorWeb/551925ad2fc2bc0ddf48dd337ec4b0a74bfd4dfd/app/src/main/res/drawable/theme.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 23 | 24 | 25 | 38 | 39 | 47 | 48 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_fragment_link.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 16 | 26 | 27 | 28 | 40 | 41 |